121042e41SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2d4a17304SKalle Valo 3d4a17304SKalle Valo /* 4d4a17304SKalle Valo * Linux device driver for ADMtek ADM8211 (IEEE 802.11b MAC/BBP) 5d4a17304SKalle Valo * 6d4a17304SKalle Valo * Copyright (c) 2003, Jouni Malinen <j@w1.fi> 7d4a17304SKalle Valo * Copyright (c) 2004-2007, Michael Wu <flamingice@sourmilk.net> 8d4a17304SKalle Valo * Some parts copyright (c) 2003 by David Young <dyoung@pobox.com> 9d4a17304SKalle Valo * and used with permission. 10d4a17304SKalle Valo * 11d4a17304SKalle Valo * Much thanks to Infineon-ADMtek for their support of this driver. 12d4a17304SKalle Valo */ 13d4a17304SKalle Valo 14d4a17304SKalle Valo #include <linux/interrupt.h> 15d4a17304SKalle Valo #include <linux/if.h> 16d4a17304SKalle Valo #include <linux/skbuff.h> 17d4a17304SKalle Valo #include <linux/slab.h> 18d4a17304SKalle Valo #include <linux/etherdevice.h> 19d4a17304SKalle Valo #include <linux/pci.h> 20d4a17304SKalle Valo #include <linux/delay.h> 21d4a17304SKalle Valo #include <linux/crc32.h> 22d4a17304SKalle Valo #include <linux/eeprom_93cx6.h> 23d4a17304SKalle Valo #include <linux/module.h> 24d4a17304SKalle Valo #include <net/mac80211.h> 25d4a17304SKalle Valo 26d4a17304SKalle Valo #include "adm8211.h" 27d4a17304SKalle Valo 28d4a17304SKalle Valo MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); 29d4a17304SKalle Valo MODULE_AUTHOR("Jouni Malinen <j@w1.fi>"); 30d4a17304SKalle Valo MODULE_DESCRIPTION("Driver for IEEE 802.11b wireless cards based on ADMtek ADM8211"); 31d4a17304SKalle Valo MODULE_SUPPORTED_DEVICE("ADM8211"); 32d4a17304SKalle Valo MODULE_LICENSE("GPL"); 33d4a17304SKalle Valo 34d4a17304SKalle Valo static unsigned int tx_ring_size __read_mostly = 16; 35d4a17304SKalle Valo static unsigned int rx_ring_size __read_mostly = 16; 36d4a17304SKalle Valo 37d4a17304SKalle Valo module_param(tx_ring_size, uint, 0); 38d4a17304SKalle Valo module_param(rx_ring_size, uint, 0); 39d4a17304SKalle Valo 40d4a17304SKalle Valo static const struct pci_device_id adm8211_pci_id_table[] = { 41d4a17304SKalle Valo /* ADMtek ADM8211 */ 42d4a17304SKalle Valo { PCI_DEVICE(0x10B7, 0x6000) }, /* 3Com 3CRSHPW796 */ 43d4a17304SKalle Valo { PCI_DEVICE(0x1200, 0x8201) }, /* ? */ 44d4a17304SKalle Valo { PCI_DEVICE(0x1317, 0x8201) }, /* ADM8211A */ 45d4a17304SKalle Valo { PCI_DEVICE(0x1317, 0x8211) }, /* ADM8211B/C */ 46d4a17304SKalle Valo { 0 } 47d4a17304SKalle Valo }; 48d4a17304SKalle Valo 49d4a17304SKalle Valo static struct ieee80211_rate adm8211_rates[] = { 50d4a17304SKalle Valo { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, 51d4a17304SKalle Valo { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, 52d4a17304SKalle Valo { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, 53d4a17304SKalle Valo { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, 54d4a17304SKalle Valo { .bitrate = 220, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, /* XX ?? */ 55d4a17304SKalle Valo }; 56d4a17304SKalle Valo 57d4a17304SKalle Valo static const struct ieee80211_channel adm8211_channels[] = { 58d4a17304SKalle Valo { .center_freq = 2412}, 59d4a17304SKalle Valo { .center_freq = 2417}, 60d4a17304SKalle Valo { .center_freq = 2422}, 61d4a17304SKalle Valo { .center_freq = 2427}, 62d4a17304SKalle Valo { .center_freq = 2432}, 63d4a17304SKalle Valo { .center_freq = 2437}, 64d4a17304SKalle Valo { .center_freq = 2442}, 65d4a17304SKalle Valo { .center_freq = 2447}, 66d4a17304SKalle Valo { .center_freq = 2452}, 67d4a17304SKalle Valo { .center_freq = 2457}, 68d4a17304SKalle Valo { .center_freq = 2462}, 69d4a17304SKalle Valo { .center_freq = 2467}, 70d4a17304SKalle Valo { .center_freq = 2472}, 71d4a17304SKalle Valo { .center_freq = 2484}, 72d4a17304SKalle Valo }; 73d4a17304SKalle Valo 74d4a17304SKalle Valo 75d4a17304SKalle Valo static void adm8211_eeprom_register_read(struct eeprom_93cx6 *eeprom) 76d4a17304SKalle Valo { 77d4a17304SKalle Valo struct adm8211_priv *priv = eeprom->data; 78d4a17304SKalle Valo u32 reg = ADM8211_CSR_READ(SPR); 79d4a17304SKalle Valo 80d4a17304SKalle Valo eeprom->reg_data_in = reg & ADM8211_SPR_SDI; 81d4a17304SKalle Valo eeprom->reg_data_out = reg & ADM8211_SPR_SDO; 82d4a17304SKalle Valo eeprom->reg_data_clock = reg & ADM8211_SPR_SCLK; 83d4a17304SKalle Valo eeprom->reg_chip_select = reg & ADM8211_SPR_SCS; 84d4a17304SKalle Valo } 85d4a17304SKalle Valo 86d4a17304SKalle Valo static void adm8211_eeprom_register_write(struct eeprom_93cx6 *eeprom) 87d4a17304SKalle Valo { 88d4a17304SKalle Valo struct adm8211_priv *priv = eeprom->data; 89d4a17304SKalle Valo u32 reg = 0x4000 | ADM8211_SPR_SRS; 90d4a17304SKalle Valo 91d4a17304SKalle Valo if (eeprom->reg_data_in) 92d4a17304SKalle Valo reg |= ADM8211_SPR_SDI; 93d4a17304SKalle Valo if (eeprom->reg_data_out) 94d4a17304SKalle Valo reg |= ADM8211_SPR_SDO; 95d4a17304SKalle Valo if (eeprom->reg_data_clock) 96d4a17304SKalle Valo reg |= ADM8211_SPR_SCLK; 97d4a17304SKalle Valo if (eeprom->reg_chip_select) 98d4a17304SKalle Valo reg |= ADM8211_SPR_SCS; 99d4a17304SKalle Valo 100d4a17304SKalle Valo ADM8211_CSR_WRITE(SPR, reg); 101d4a17304SKalle Valo ADM8211_CSR_READ(SPR); /* eeprom_delay */ 102d4a17304SKalle Valo } 103d4a17304SKalle Valo 104d4a17304SKalle Valo static int adm8211_read_eeprom(struct ieee80211_hw *dev) 105d4a17304SKalle Valo { 106d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 107d4a17304SKalle Valo unsigned int words, i; 108d4a17304SKalle Valo struct ieee80211_chan_range chan_range; 109d4a17304SKalle Valo u16 cr49; 110d4a17304SKalle Valo struct eeprom_93cx6 eeprom = { 111d4a17304SKalle Valo .data = priv, 112d4a17304SKalle Valo .register_read = adm8211_eeprom_register_read, 113d4a17304SKalle Valo .register_write = adm8211_eeprom_register_write 114d4a17304SKalle Valo }; 115d4a17304SKalle Valo 116d4a17304SKalle Valo if (ADM8211_CSR_READ(CSR_TEST0) & ADM8211_CSR_TEST0_EPTYP) { 117d4a17304SKalle Valo /* 256 * 16-bit = 512 bytes */ 118d4a17304SKalle Valo eeprom.width = PCI_EEPROM_WIDTH_93C66; 119d4a17304SKalle Valo words = 256; 120d4a17304SKalle Valo } else { 121d4a17304SKalle Valo /* 64 * 16-bit = 128 bytes */ 122d4a17304SKalle Valo eeprom.width = PCI_EEPROM_WIDTH_93C46; 123d4a17304SKalle Valo words = 64; 124d4a17304SKalle Valo } 125d4a17304SKalle Valo 126d4a17304SKalle Valo priv->eeprom_len = words * 2; 127d4a17304SKalle Valo priv->eeprom = kmalloc(priv->eeprom_len, GFP_KERNEL); 128d4a17304SKalle Valo if (!priv->eeprom) 129d4a17304SKalle Valo return -ENOMEM; 130d4a17304SKalle Valo 131d4a17304SKalle Valo eeprom_93cx6_multiread(&eeprom, 0, (__le16 *)priv->eeprom, words); 132d4a17304SKalle Valo 133d4a17304SKalle Valo cr49 = le16_to_cpu(priv->eeprom->cr49); 134d4a17304SKalle Valo priv->rf_type = (cr49 >> 3) & 0x7; 135d4a17304SKalle Valo switch (priv->rf_type) { 136d4a17304SKalle Valo case ADM8211_TYPE_INTERSIL: 137d4a17304SKalle Valo case ADM8211_TYPE_RFMD: 138d4a17304SKalle Valo case ADM8211_TYPE_MARVEL: 139d4a17304SKalle Valo case ADM8211_TYPE_AIROHA: 140d4a17304SKalle Valo case ADM8211_TYPE_ADMTEK: 141d4a17304SKalle Valo break; 142d4a17304SKalle Valo 143d4a17304SKalle Valo default: 144d4a17304SKalle Valo if (priv->pdev->revision < ADM8211_REV_CA) 145d4a17304SKalle Valo priv->rf_type = ADM8211_TYPE_RFMD; 146d4a17304SKalle Valo else 147d4a17304SKalle Valo priv->rf_type = ADM8211_TYPE_AIROHA; 148d4a17304SKalle Valo 149d4a17304SKalle Valo printk(KERN_WARNING "%s (adm8211): Unknown RFtype %d\n", 150d4a17304SKalle Valo pci_name(priv->pdev), (cr49 >> 3) & 0x7); 151d4a17304SKalle Valo } 152d4a17304SKalle Valo 153d4a17304SKalle Valo priv->bbp_type = cr49 & 0x7; 154d4a17304SKalle Valo switch (priv->bbp_type) { 155d4a17304SKalle Valo case ADM8211_TYPE_INTERSIL: 156d4a17304SKalle Valo case ADM8211_TYPE_RFMD: 157d4a17304SKalle Valo case ADM8211_TYPE_MARVEL: 158d4a17304SKalle Valo case ADM8211_TYPE_AIROHA: 159d4a17304SKalle Valo case ADM8211_TYPE_ADMTEK: 160d4a17304SKalle Valo break; 161d4a17304SKalle Valo default: 162d4a17304SKalle Valo if (priv->pdev->revision < ADM8211_REV_CA) 163d4a17304SKalle Valo priv->bbp_type = ADM8211_TYPE_RFMD; 164d4a17304SKalle Valo else 165d4a17304SKalle Valo priv->bbp_type = ADM8211_TYPE_ADMTEK; 166d4a17304SKalle Valo 167d4a17304SKalle Valo printk(KERN_WARNING "%s (adm8211): Unknown BBPtype: %d\n", 168d4a17304SKalle Valo pci_name(priv->pdev), cr49 >> 3); 169d4a17304SKalle Valo } 170d4a17304SKalle Valo 171d4a17304SKalle Valo if (priv->eeprom->country_code >= ARRAY_SIZE(cranges)) { 172d4a17304SKalle Valo printk(KERN_WARNING "%s (adm8211): Invalid country code (%d)\n", 173d4a17304SKalle Valo pci_name(priv->pdev), priv->eeprom->country_code); 174d4a17304SKalle Valo 175d4a17304SKalle Valo chan_range = cranges[2]; 176d4a17304SKalle Valo } else 177d4a17304SKalle Valo chan_range = cranges[priv->eeprom->country_code]; 178d4a17304SKalle Valo 179d4a17304SKalle Valo printk(KERN_DEBUG "%s (adm8211): Channel range: %d - %d\n", 180d4a17304SKalle Valo pci_name(priv->pdev), (int)chan_range.min, (int)chan_range.max); 181d4a17304SKalle Valo 182d4a17304SKalle Valo BUILD_BUG_ON(sizeof(priv->channels) != sizeof(adm8211_channels)); 183d4a17304SKalle Valo 184d4a17304SKalle Valo memcpy(priv->channels, adm8211_channels, sizeof(priv->channels)); 185d4a17304SKalle Valo priv->band.channels = priv->channels; 186d4a17304SKalle Valo priv->band.n_channels = ARRAY_SIZE(adm8211_channels); 187d4a17304SKalle Valo priv->band.bitrates = adm8211_rates; 188d4a17304SKalle Valo priv->band.n_bitrates = ARRAY_SIZE(adm8211_rates); 189d4a17304SKalle Valo 190d4a17304SKalle Valo for (i = 1; i <= ARRAY_SIZE(adm8211_channels); i++) 191d4a17304SKalle Valo if (i < chan_range.min || i > chan_range.max) 192d4a17304SKalle Valo priv->channels[i - 1].flags |= IEEE80211_CHAN_DISABLED; 193d4a17304SKalle Valo 194d4a17304SKalle Valo switch (priv->eeprom->specific_bbptype) { 195d4a17304SKalle Valo case ADM8211_BBP_RFMD3000: 196d4a17304SKalle Valo case ADM8211_BBP_RFMD3002: 197d4a17304SKalle Valo case ADM8211_BBP_ADM8011: 198d4a17304SKalle Valo priv->specific_bbptype = priv->eeprom->specific_bbptype; 199d4a17304SKalle Valo break; 200d4a17304SKalle Valo 201d4a17304SKalle Valo default: 202d4a17304SKalle Valo if (priv->pdev->revision < ADM8211_REV_CA) 203d4a17304SKalle Valo priv->specific_bbptype = ADM8211_BBP_RFMD3000; 204d4a17304SKalle Valo else 205d4a17304SKalle Valo priv->specific_bbptype = ADM8211_BBP_ADM8011; 206d4a17304SKalle Valo 207d4a17304SKalle Valo printk(KERN_WARNING "%s (adm8211): Unknown specific BBP: %d\n", 208d4a17304SKalle Valo pci_name(priv->pdev), priv->eeprom->specific_bbptype); 209d4a17304SKalle Valo } 210d4a17304SKalle Valo 211d4a17304SKalle Valo switch (priv->eeprom->specific_rftype) { 212d4a17304SKalle Valo case ADM8211_RFMD2948: 213d4a17304SKalle Valo case ADM8211_RFMD2958: 214d4a17304SKalle Valo case ADM8211_RFMD2958_RF3000_CONTROL_POWER: 215d4a17304SKalle Valo case ADM8211_MAX2820: 216d4a17304SKalle Valo case ADM8211_AL2210L: 217d4a17304SKalle Valo priv->transceiver_type = priv->eeprom->specific_rftype; 218d4a17304SKalle Valo break; 219d4a17304SKalle Valo 220d4a17304SKalle Valo default: 221d4a17304SKalle Valo if (priv->pdev->revision == ADM8211_REV_BA) 222d4a17304SKalle Valo priv->transceiver_type = ADM8211_RFMD2958_RF3000_CONTROL_POWER; 223d4a17304SKalle Valo else if (priv->pdev->revision == ADM8211_REV_CA) 224d4a17304SKalle Valo priv->transceiver_type = ADM8211_AL2210L; 225d4a17304SKalle Valo else if (priv->pdev->revision == ADM8211_REV_AB) 226d4a17304SKalle Valo priv->transceiver_type = ADM8211_RFMD2948; 227d4a17304SKalle Valo 228d4a17304SKalle Valo printk(KERN_WARNING "%s (adm8211): Unknown transceiver: %d\n", 229d4a17304SKalle Valo pci_name(priv->pdev), priv->eeprom->specific_rftype); 230d4a17304SKalle Valo 231d4a17304SKalle Valo break; 232d4a17304SKalle Valo } 233d4a17304SKalle Valo 234d4a17304SKalle Valo printk(KERN_DEBUG "%s (adm8211): RFtype=%d BBPtype=%d Specific BBP=%d " 235d4a17304SKalle Valo "Transceiver=%d\n", pci_name(priv->pdev), priv->rf_type, 236d4a17304SKalle Valo priv->bbp_type, priv->specific_bbptype, priv->transceiver_type); 237d4a17304SKalle Valo 238d4a17304SKalle Valo return 0; 239d4a17304SKalle Valo } 240d4a17304SKalle Valo 241d4a17304SKalle Valo static inline void adm8211_write_sram(struct ieee80211_hw *dev, 242d4a17304SKalle Valo u32 addr, u32 data) 243d4a17304SKalle Valo { 244d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 245d4a17304SKalle Valo 246d4a17304SKalle Valo ADM8211_CSR_WRITE(WEPCTL, addr | ADM8211_WEPCTL_TABLE_WR | 247d4a17304SKalle Valo (priv->pdev->revision < ADM8211_REV_BA ? 248d4a17304SKalle Valo 0 : ADM8211_WEPCTL_SEL_WEPTABLE )); 249d4a17304SKalle Valo ADM8211_CSR_READ(WEPCTL); 250d4a17304SKalle Valo msleep(1); 251d4a17304SKalle Valo 252d4a17304SKalle Valo ADM8211_CSR_WRITE(WESK, data); 253d4a17304SKalle Valo ADM8211_CSR_READ(WESK); 254d4a17304SKalle Valo msleep(1); 255d4a17304SKalle Valo } 256d4a17304SKalle Valo 257d4a17304SKalle Valo static void adm8211_write_sram_bytes(struct ieee80211_hw *dev, 258d4a17304SKalle Valo unsigned int addr, u8 *buf, 259d4a17304SKalle Valo unsigned int len) 260d4a17304SKalle Valo { 261d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 262d4a17304SKalle Valo u32 reg = ADM8211_CSR_READ(WEPCTL); 263d4a17304SKalle Valo unsigned int i; 264d4a17304SKalle Valo 265d4a17304SKalle Valo if (priv->pdev->revision < ADM8211_REV_BA) { 266d4a17304SKalle Valo for (i = 0; i < len; i += 2) { 267d4a17304SKalle Valo u16 val = buf[i] | (buf[i + 1] << 8); 268d4a17304SKalle Valo adm8211_write_sram(dev, addr + i / 2, val); 269d4a17304SKalle Valo } 270d4a17304SKalle Valo } else { 271d4a17304SKalle Valo for (i = 0; i < len; i += 4) { 272d4a17304SKalle Valo u32 val = (buf[i + 0] << 0 ) | (buf[i + 1] << 8 ) | 273d4a17304SKalle Valo (buf[i + 2] << 16) | (buf[i + 3] << 24); 274d4a17304SKalle Valo adm8211_write_sram(dev, addr + i / 4, val); 275d4a17304SKalle Valo } 276d4a17304SKalle Valo } 277d4a17304SKalle Valo 278d4a17304SKalle Valo ADM8211_CSR_WRITE(WEPCTL, reg); 279d4a17304SKalle Valo } 280d4a17304SKalle Valo 281d4a17304SKalle Valo static void adm8211_clear_sram(struct ieee80211_hw *dev) 282d4a17304SKalle Valo { 283d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 284d4a17304SKalle Valo u32 reg = ADM8211_CSR_READ(WEPCTL); 285d4a17304SKalle Valo unsigned int addr; 286d4a17304SKalle Valo 287d4a17304SKalle Valo for (addr = 0; addr < ADM8211_SRAM_SIZE; addr++) 288d4a17304SKalle Valo adm8211_write_sram(dev, addr, 0); 289d4a17304SKalle Valo 290d4a17304SKalle Valo ADM8211_CSR_WRITE(WEPCTL, reg); 291d4a17304SKalle Valo } 292d4a17304SKalle Valo 293d4a17304SKalle Valo static int adm8211_get_stats(struct ieee80211_hw *dev, 294d4a17304SKalle Valo struct ieee80211_low_level_stats *stats) 295d4a17304SKalle Valo { 296d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 297d4a17304SKalle Valo 298d4a17304SKalle Valo memcpy(stats, &priv->stats, sizeof(*stats)); 299d4a17304SKalle Valo 300d4a17304SKalle Valo return 0; 301d4a17304SKalle Valo } 302d4a17304SKalle Valo 303d4a17304SKalle Valo static void adm8211_interrupt_tci(struct ieee80211_hw *dev) 304d4a17304SKalle Valo { 305d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 306d4a17304SKalle Valo unsigned int dirty_tx; 307d4a17304SKalle Valo 308d4a17304SKalle Valo spin_lock(&priv->lock); 309d4a17304SKalle Valo 310d4a17304SKalle Valo for (dirty_tx = priv->dirty_tx; priv->cur_tx - dirty_tx; dirty_tx++) { 311d4a17304SKalle Valo unsigned int entry = dirty_tx % priv->tx_ring_size; 312d4a17304SKalle Valo u32 status = le32_to_cpu(priv->tx_ring[entry].status); 313d4a17304SKalle Valo struct ieee80211_tx_info *txi; 314d4a17304SKalle Valo struct adm8211_tx_ring_info *info; 315d4a17304SKalle Valo struct sk_buff *skb; 316d4a17304SKalle Valo 317d4a17304SKalle Valo if (status & TDES0_CONTROL_OWN || 318d4a17304SKalle Valo !(status & TDES0_CONTROL_DONE)) 319d4a17304SKalle Valo break; 320d4a17304SKalle Valo 321d4a17304SKalle Valo info = &priv->tx_buffers[entry]; 322d4a17304SKalle Valo skb = info->skb; 323d4a17304SKalle Valo txi = IEEE80211_SKB_CB(skb); 324d4a17304SKalle Valo 325d4a17304SKalle Valo /* TODO: check TDES0_STATUS_TUF and TDES0_STATUS_TRO */ 326d4a17304SKalle Valo 327d4a17304SKalle Valo pci_unmap_single(priv->pdev, info->mapping, 328d4a17304SKalle Valo info->skb->len, PCI_DMA_TODEVICE); 329d4a17304SKalle Valo 330d4a17304SKalle Valo ieee80211_tx_info_clear_status(txi); 331d4a17304SKalle Valo 332d4a17304SKalle Valo skb_pull(skb, sizeof(struct adm8211_tx_hdr)); 333d4a17304SKalle Valo memcpy(skb_push(skb, info->hdrlen), skb->cb, info->hdrlen); 334d4a17304SKalle Valo if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && 335d4a17304SKalle Valo !(status & TDES0_STATUS_ES)) 336d4a17304SKalle Valo txi->flags |= IEEE80211_TX_STAT_ACK; 337d4a17304SKalle Valo 338d4a17304SKalle Valo ieee80211_tx_status_irqsafe(dev, skb); 339d4a17304SKalle Valo 340d4a17304SKalle Valo info->skb = NULL; 341d4a17304SKalle Valo } 342d4a17304SKalle Valo 343d4a17304SKalle Valo if (priv->cur_tx - dirty_tx < priv->tx_ring_size - 2) 344d4a17304SKalle Valo ieee80211_wake_queue(dev, 0); 345d4a17304SKalle Valo 346d4a17304SKalle Valo priv->dirty_tx = dirty_tx; 347d4a17304SKalle Valo spin_unlock(&priv->lock); 348d4a17304SKalle Valo } 349d4a17304SKalle Valo 350d4a17304SKalle Valo 351d4a17304SKalle Valo static void adm8211_interrupt_rci(struct ieee80211_hw *dev) 352d4a17304SKalle Valo { 353d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 354d4a17304SKalle Valo unsigned int entry = priv->cur_rx % priv->rx_ring_size; 355d4a17304SKalle Valo u32 status; 356d4a17304SKalle Valo unsigned int pktlen; 357d4a17304SKalle Valo struct sk_buff *skb, *newskb; 358d4a17304SKalle Valo unsigned int limit = priv->rx_ring_size; 359d4a17304SKalle Valo u8 rssi, rate; 360d4a17304SKalle Valo 361d4a17304SKalle Valo while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) { 362d4a17304SKalle Valo if (!limit--) 363d4a17304SKalle Valo break; 364d4a17304SKalle Valo 365d4a17304SKalle Valo status = le32_to_cpu(priv->rx_ring[entry].status); 366d4a17304SKalle Valo rate = (status & RDES0_STATUS_RXDR) >> 12; 367d4a17304SKalle Valo rssi = le32_to_cpu(priv->rx_ring[entry].length) & 368d4a17304SKalle Valo RDES1_STATUS_RSSI; 369d4a17304SKalle Valo 370d4a17304SKalle Valo pktlen = status & RDES0_STATUS_FL; 371d4a17304SKalle Valo if (pktlen > RX_PKT_SIZE) { 372d4a17304SKalle Valo if (net_ratelimit()) 373d4a17304SKalle Valo wiphy_debug(dev->wiphy, "frame too long (%d)\n", 374d4a17304SKalle Valo pktlen); 375d4a17304SKalle Valo pktlen = RX_PKT_SIZE; 376d4a17304SKalle Valo } 377d4a17304SKalle Valo 378d4a17304SKalle Valo if (!priv->soft_rx_crc && status & RDES0_STATUS_ES) { 379d4a17304SKalle Valo skb = NULL; /* old buffer will be reused */ 380d4a17304SKalle Valo /* TODO: update RX error stats */ 381d4a17304SKalle Valo /* TODO: check RDES0_STATUS_CRC*E */ 382d4a17304SKalle Valo } else if (pktlen < RX_COPY_BREAK) { 383d4a17304SKalle Valo skb = dev_alloc_skb(pktlen); 384d4a17304SKalle Valo if (skb) { 385d4a17304SKalle Valo pci_dma_sync_single_for_cpu( 386d4a17304SKalle Valo priv->pdev, 387d4a17304SKalle Valo priv->rx_buffers[entry].mapping, 388d4a17304SKalle Valo pktlen, PCI_DMA_FROMDEVICE); 38959ae1d12SJohannes Berg skb_put_data(skb, 390d4a17304SKalle Valo skb_tail_pointer(priv->rx_buffers[entry].skb), 391d4a17304SKalle Valo pktlen); 392d4a17304SKalle Valo pci_dma_sync_single_for_device( 393d4a17304SKalle Valo priv->pdev, 394d4a17304SKalle Valo priv->rx_buffers[entry].mapping, 395d4a17304SKalle Valo RX_PKT_SIZE, PCI_DMA_FROMDEVICE); 396d4a17304SKalle Valo } 397d4a17304SKalle Valo } else { 398d4a17304SKalle Valo newskb = dev_alloc_skb(RX_PKT_SIZE); 399d4a17304SKalle Valo if (newskb) { 400d4a17304SKalle Valo skb = priv->rx_buffers[entry].skb; 401d4a17304SKalle Valo skb_put(skb, pktlen); 402d4a17304SKalle Valo pci_unmap_single( 403d4a17304SKalle Valo priv->pdev, 404d4a17304SKalle Valo priv->rx_buffers[entry].mapping, 405d4a17304SKalle Valo RX_PKT_SIZE, PCI_DMA_FROMDEVICE); 406d4a17304SKalle Valo priv->rx_buffers[entry].skb = newskb; 407d4a17304SKalle Valo priv->rx_buffers[entry].mapping = 408d4a17304SKalle Valo pci_map_single(priv->pdev, 409d4a17304SKalle Valo skb_tail_pointer(newskb), 410d4a17304SKalle Valo RX_PKT_SIZE, 411d4a17304SKalle Valo PCI_DMA_FROMDEVICE); 412d15697deSAlexey Khoroshilov if (pci_dma_mapping_error(priv->pdev, 413d15697deSAlexey Khoroshilov priv->rx_buffers[entry].mapping)) { 414d15697deSAlexey Khoroshilov priv->rx_buffers[entry].skb = NULL; 415d15697deSAlexey Khoroshilov dev_kfree_skb(newskb); 416d15697deSAlexey Khoroshilov skb = NULL; 417d15697deSAlexey Khoroshilov /* TODO: update rx dropped stats */ 418d15697deSAlexey Khoroshilov } 419d4a17304SKalle Valo } else { 420d4a17304SKalle Valo skb = NULL; 421d4a17304SKalle Valo /* TODO: update rx dropped stats */ 422d4a17304SKalle Valo } 423d4a17304SKalle Valo 424d4a17304SKalle Valo priv->rx_ring[entry].buffer1 = 425d4a17304SKalle Valo cpu_to_le32(priv->rx_buffers[entry].mapping); 426d4a17304SKalle Valo } 427d4a17304SKalle Valo 428d4a17304SKalle Valo priv->rx_ring[entry].status = cpu_to_le32(RDES0_STATUS_OWN | 429d4a17304SKalle Valo RDES0_STATUS_SQL); 430d4a17304SKalle Valo priv->rx_ring[entry].length = 431d4a17304SKalle Valo cpu_to_le32(RX_PKT_SIZE | 432d4a17304SKalle Valo (entry == priv->rx_ring_size - 1 ? 433d4a17304SKalle Valo RDES1_CONTROL_RER : 0)); 434d4a17304SKalle Valo 435d4a17304SKalle Valo if (skb) { 436d4a17304SKalle Valo struct ieee80211_rx_status rx_status = {0}; 437d4a17304SKalle Valo 438d4a17304SKalle Valo if (priv->pdev->revision < ADM8211_REV_CA) 439d4a17304SKalle Valo rx_status.signal = rssi; 440d4a17304SKalle Valo else 441d4a17304SKalle Valo rx_status.signal = 100 - rssi; 442d4a17304SKalle Valo 443d4a17304SKalle Valo rx_status.rate_idx = rate; 444d4a17304SKalle Valo 445d4a17304SKalle Valo rx_status.freq = adm8211_channels[priv->channel - 1].center_freq; 44657fbcce3SJohannes Berg rx_status.band = NL80211_BAND_2GHZ; 447d4a17304SKalle Valo 448d4a17304SKalle Valo memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); 449d4a17304SKalle Valo ieee80211_rx_irqsafe(dev, skb); 450d4a17304SKalle Valo } 451d4a17304SKalle Valo 452d4a17304SKalle Valo entry = (++priv->cur_rx) % priv->rx_ring_size; 453d4a17304SKalle Valo } 454d4a17304SKalle Valo 455d4a17304SKalle Valo /* TODO: check LPC and update stats? */ 456d4a17304SKalle Valo } 457d4a17304SKalle Valo 458d4a17304SKalle Valo 459d4a17304SKalle Valo static irqreturn_t adm8211_interrupt(int irq, void *dev_id) 460d4a17304SKalle Valo { 461d4a17304SKalle Valo #define ADM8211_INT(x) \ 462d4a17304SKalle Valo do { \ 463d4a17304SKalle Valo if (unlikely(stsr & ADM8211_STSR_ ## x)) \ 464d4a17304SKalle Valo wiphy_debug(dev->wiphy, "%s\n", #x); \ 465d4a17304SKalle Valo } while (0) 466d4a17304SKalle Valo 467d4a17304SKalle Valo struct ieee80211_hw *dev = dev_id; 468d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 469d4a17304SKalle Valo u32 stsr = ADM8211_CSR_READ(STSR); 470d4a17304SKalle Valo ADM8211_CSR_WRITE(STSR, stsr); 471d4a17304SKalle Valo if (stsr == 0xffffffff) 472d4a17304SKalle Valo return IRQ_HANDLED; 473d4a17304SKalle Valo 474d4a17304SKalle Valo if (!(stsr & (ADM8211_STSR_NISS | ADM8211_STSR_AISS))) 475d4a17304SKalle Valo return IRQ_HANDLED; 476d4a17304SKalle Valo 477d4a17304SKalle Valo if (stsr & ADM8211_STSR_RCI) 478d4a17304SKalle Valo adm8211_interrupt_rci(dev); 479d4a17304SKalle Valo if (stsr & ADM8211_STSR_TCI) 480d4a17304SKalle Valo adm8211_interrupt_tci(dev); 481d4a17304SKalle Valo 482d4a17304SKalle Valo ADM8211_INT(PCF); 483d4a17304SKalle Valo ADM8211_INT(BCNTC); 484d4a17304SKalle Valo ADM8211_INT(GPINT); 485d4a17304SKalle Valo ADM8211_INT(ATIMTC); 486d4a17304SKalle Valo ADM8211_INT(TSFTF); 487d4a17304SKalle Valo ADM8211_INT(TSCZ); 488d4a17304SKalle Valo ADM8211_INT(SQL); 489d4a17304SKalle Valo ADM8211_INT(WEPTD); 490d4a17304SKalle Valo ADM8211_INT(ATIME); 491d4a17304SKalle Valo ADM8211_INT(TEIS); 492d4a17304SKalle Valo ADM8211_INT(FBE); 493d4a17304SKalle Valo ADM8211_INT(REIS); 494d4a17304SKalle Valo ADM8211_INT(GPTT); 495d4a17304SKalle Valo ADM8211_INT(RPS); 496d4a17304SKalle Valo ADM8211_INT(RDU); 497d4a17304SKalle Valo ADM8211_INT(TUF); 498d4a17304SKalle Valo ADM8211_INT(TPS); 499d4a17304SKalle Valo 500d4a17304SKalle Valo return IRQ_HANDLED; 501d4a17304SKalle Valo 502d4a17304SKalle Valo #undef ADM8211_INT 503d4a17304SKalle Valo } 504d4a17304SKalle Valo 505d4a17304SKalle Valo #define WRITE_SYN(name,v_mask,v_shift,a_mask,a_shift,bits,prewrite,postwrite)\ 506d4a17304SKalle Valo static void adm8211_rf_write_syn_ ## name (struct ieee80211_hw *dev, \ 507d4a17304SKalle Valo u16 addr, u32 value) { \ 508d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; \ 509d4a17304SKalle Valo unsigned int i; \ 510d4a17304SKalle Valo u32 reg, bitbuf; \ 511d4a17304SKalle Valo \ 512d4a17304SKalle Valo value &= v_mask; \ 513d4a17304SKalle Valo addr &= a_mask; \ 514d4a17304SKalle Valo bitbuf = (value << v_shift) | (addr << a_shift); \ 515d4a17304SKalle Valo \ 516d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_IF_SELECT_1); \ 517d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); \ 518d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_IF_SELECT_0); \ 519d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); \ 520d4a17304SKalle Valo \ 521d4a17304SKalle Valo if (prewrite) { \ 522d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_WRITE_SYNDATA_0); \ 523d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); \ 524d4a17304SKalle Valo } \ 525d4a17304SKalle Valo \ 526d4a17304SKalle Valo for (i = 0; i <= bits; i++) { \ 527d4a17304SKalle Valo if (bitbuf & (1 << (bits - i))) \ 528d4a17304SKalle Valo reg = ADM8211_SYNRF_WRITE_SYNDATA_1; \ 529d4a17304SKalle Valo else \ 530d4a17304SKalle Valo reg = ADM8211_SYNRF_WRITE_SYNDATA_0; \ 531d4a17304SKalle Valo \ 532d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, reg); \ 533d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); \ 534d4a17304SKalle Valo \ 535d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_WRITE_CLOCK_1); \ 536d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); \ 537d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_WRITE_CLOCK_0); \ 538d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); \ 539d4a17304SKalle Valo } \ 540d4a17304SKalle Valo \ 541d4a17304SKalle Valo if (postwrite == 1) { \ 542d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_IF_SELECT_0); \ 543d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); \ 544d4a17304SKalle Valo } \ 545d4a17304SKalle Valo if (postwrite == 2) { \ 546d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_IF_SELECT_1); \ 547d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); \ 548d4a17304SKalle Valo } \ 549d4a17304SKalle Valo \ 550d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, 0); \ 551d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); \ 552d4a17304SKalle Valo } 553d4a17304SKalle Valo 554d4a17304SKalle Valo WRITE_SYN(max2820, 0x00FFF, 0, 0x0F, 12, 15, 1, 1) 555d4a17304SKalle Valo WRITE_SYN(al2210l, 0xFFFFF, 4, 0x0F, 0, 23, 1, 1) 556d4a17304SKalle Valo WRITE_SYN(rfmd2958, 0x3FFFF, 0, 0x1F, 18, 23, 0, 1) 557d4a17304SKalle Valo WRITE_SYN(rfmd2948, 0x0FFFF, 4, 0x0F, 0, 21, 0, 2) 558d4a17304SKalle Valo 559d4a17304SKalle Valo #undef WRITE_SYN 560d4a17304SKalle Valo 561d4a17304SKalle Valo static int adm8211_write_bbp(struct ieee80211_hw *dev, u8 addr, u8 data) 562d4a17304SKalle Valo { 563d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 564d4a17304SKalle Valo unsigned int timeout; 565d4a17304SKalle Valo u32 reg; 566d4a17304SKalle Valo 567d4a17304SKalle Valo timeout = 10; 568d4a17304SKalle Valo while (timeout > 0) { 569d4a17304SKalle Valo reg = ADM8211_CSR_READ(BBPCTL); 570d4a17304SKalle Valo if (!(reg & (ADM8211_BBPCTL_WR | ADM8211_BBPCTL_RD))) 571d4a17304SKalle Valo break; 572d4a17304SKalle Valo timeout--; 573d4a17304SKalle Valo msleep(2); 574d4a17304SKalle Valo } 575d4a17304SKalle Valo 576d4a17304SKalle Valo if (timeout == 0) { 577d4a17304SKalle Valo wiphy_debug(dev->wiphy, 578d4a17304SKalle Valo "adm8211_write_bbp(%d,%d) failed prewrite (reg=0x%08x)\n", 579d4a17304SKalle Valo addr, data, reg); 580d4a17304SKalle Valo return -ETIMEDOUT; 581d4a17304SKalle Valo } 582d4a17304SKalle Valo 583d4a17304SKalle Valo switch (priv->bbp_type) { 584d4a17304SKalle Valo case ADM8211_TYPE_INTERSIL: 585d4a17304SKalle Valo reg = ADM8211_BBPCTL_MMISEL; /* three wire interface */ 586d4a17304SKalle Valo break; 587d4a17304SKalle Valo case ADM8211_TYPE_RFMD: 588d4a17304SKalle Valo reg = (0x20 << 24) | ADM8211_BBPCTL_TXCE | ADM8211_BBPCTL_CCAP | 589d4a17304SKalle Valo (0x01 << 18); 590d4a17304SKalle Valo break; 591d4a17304SKalle Valo case ADM8211_TYPE_ADMTEK: 592d4a17304SKalle Valo reg = (0x20 << 24) | ADM8211_BBPCTL_TXCE | ADM8211_BBPCTL_CCAP | 593d4a17304SKalle Valo (0x05 << 18); 594d4a17304SKalle Valo break; 595d4a17304SKalle Valo } 596d4a17304SKalle Valo reg |= ADM8211_BBPCTL_WR | (addr << 8) | data; 597d4a17304SKalle Valo 598d4a17304SKalle Valo ADM8211_CSR_WRITE(BBPCTL, reg); 599d4a17304SKalle Valo 600d4a17304SKalle Valo timeout = 10; 601d4a17304SKalle Valo while (timeout > 0) { 602d4a17304SKalle Valo reg = ADM8211_CSR_READ(BBPCTL); 603d4a17304SKalle Valo if (!(reg & ADM8211_BBPCTL_WR)) 604d4a17304SKalle Valo break; 605d4a17304SKalle Valo timeout--; 606d4a17304SKalle Valo msleep(2); 607d4a17304SKalle Valo } 608d4a17304SKalle Valo 609d4a17304SKalle Valo if (timeout == 0) { 610d4a17304SKalle Valo ADM8211_CSR_WRITE(BBPCTL, ADM8211_CSR_READ(BBPCTL) & 611d4a17304SKalle Valo ~ADM8211_BBPCTL_WR); 612d4a17304SKalle Valo wiphy_debug(dev->wiphy, 613d4a17304SKalle Valo "adm8211_write_bbp(%d,%d) failed postwrite (reg=0x%08x)\n", 614d4a17304SKalle Valo addr, data, reg); 615d4a17304SKalle Valo return -ETIMEDOUT; 616d4a17304SKalle Valo } 617d4a17304SKalle Valo 618d4a17304SKalle Valo return 0; 619d4a17304SKalle Valo } 620d4a17304SKalle Valo 621d4a17304SKalle Valo static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan) 622d4a17304SKalle Valo { 623d4a17304SKalle Valo static const u32 adm8211_rfmd2958_reg5[] = 624d4a17304SKalle Valo {0x22BD, 0x22D2, 0x22E8, 0x22FE, 0x2314, 0x232A, 0x2340, 625d4a17304SKalle Valo 0x2355, 0x236B, 0x2381, 0x2397, 0x23AD, 0x23C2, 0x23F7}; 626d4a17304SKalle Valo static const u32 adm8211_rfmd2958_reg6[] = 627d4a17304SKalle Valo {0x05D17, 0x3A2E8, 0x2E8BA, 0x22E8B, 0x1745D, 0x0BA2E, 0x00000, 628d4a17304SKalle Valo 0x345D1, 0x28BA2, 0x1D174, 0x11745, 0x05D17, 0x3A2E8, 0x11745}; 629d4a17304SKalle Valo 630d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 631d4a17304SKalle Valo u8 ant_power = priv->ant_power > 0x3F ? 632d4a17304SKalle Valo priv->eeprom->antenna_power[chan - 1] : priv->ant_power; 633d4a17304SKalle Valo u8 tx_power = priv->tx_power > 0x3F ? 634d4a17304SKalle Valo priv->eeprom->tx_power[chan - 1] : priv->tx_power; 635d4a17304SKalle Valo u8 lpf_cutoff = priv->lpf_cutoff == 0xFF ? 636d4a17304SKalle Valo priv->eeprom->lpf_cutoff[chan - 1] : priv->lpf_cutoff; 637d4a17304SKalle Valo u8 lnags_thresh = priv->lnags_threshold == 0xFF ? 638d4a17304SKalle Valo priv->eeprom->lnags_threshold[chan - 1] : priv->lnags_threshold; 639d4a17304SKalle Valo u32 reg; 640d4a17304SKalle Valo 641d4a17304SKalle Valo ADM8211_IDLE(); 642d4a17304SKalle Valo 643d4a17304SKalle Valo /* Program synthesizer to new channel */ 644d4a17304SKalle Valo switch (priv->transceiver_type) { 645d4a17304SKalle Valo case ADM8211_RFMD2958: 646d4a17304SKalle Valo case ADM8211_RFMD2958_RF3000_CONTROL_POWER: 647d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x00, 0x04007); 648d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x02, 0x00033); 649d4a17304SKalle Valo 650d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x05, 651d4a17304SKalle Valo adm8211_rfmd2958_reg5[chan - 1]); 652d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x06, 653d4a17304SKalle Valo adm8211_rfmd2958_reg6[chan - 1]); 654d4a17304SKalle Valo break; 655d4a17304SKalle Valo 656d4a17304SKalle Valo case ADM8211_RFMD2948: 657d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2948(dev, SI4126_MAIN_CONF, 658d4a17304SKalle Valo SI4126_MAIN_XINDIV2); 659d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2948(dev, SI4126_POWERDOWN, 660d4a17304SKalle Valo SI4126_POWERDOWN_PDIB | 661d4a17304SKalle Valo SI4126_POWERDOWN_PDRB); 662d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2948(dev, SI4126_PHASE_DET_GAIN, 0); 663d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2948(dev, SI4126_RF2_N_DIV, 664d4a17304SKalle Valo (chan == 14 ? 665d4a17304SKalle Valo 2110 : (2033 + (chan * 5)))); 666d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2948(dev, SI4126_IF_N_DIV, 1496); 667d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2948(dev, SI4126_RF2_R_DIV, 44); 668d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2948(dev, SI4126_IF_R_DIV, 44); 669d4a17304SKalle Valo break; 670d4a17304SKalle Valo 671d4a17304SKalle Valo case ADM8211_MAX2820: 672d4a17304SKalle Valo adm8211_rf_write_syn_max2820(dev, 0x3, 673d4a17304SKalle Valo (chan == 14 ? 0x054 : (0x7 + (chan * 5)))); 674d4a17304SKalle Valo break; 675d4a17304SKalle Valo 676d4a17304SKalle Valo case ADM8211_AL2210L: 677d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x0, 678d4a17304SKalle Valo (chan == 14 ? 0x229B4 : (0x22967 + (chan * 5)))); 679d4a17304SKalle Valo break; 680d4a17304SKalle Valo 681d4a17304SKalle Valo default: 682d4a17304SKalle Valo wiphy_debug(dev->wiphy, "unsupported transceiver type %d\n", 683d4a17304SKalle Valo priv->transceiver_type); 684d4a17304SKalle Valo break; 685d4a17304SKalle Valo } 686d4a17304SKalle Valo 687d4a17304SKalle Valo /* write BBP regs */ 688d4a17304SKalle Valo if (priv->bbp_type == ADM8211_TYPE_RFMD) { 689d4a17304SKalle Valo 690d4a17304SKalle Valo /* SMC 2635W specific? adm8211b doesn't use the 2948 though.. */ 691d4a17304SKalle Valo /* TODO: remove if SMC 2635W doesn't need this */ 692d4a17304SKalle Valo if (priv->transceiver_type == ADM8211_RFMD2948) { 693d4a17304SKalle Valo reg = ADM8211_CSR_READ(GPIO); 694d4a17304SKalle Valo reg &= 0xfffc0000; 695d4a17304SKalle Valo reg |= ADM8211_CSR_GPIO_EN0; 696d4a17304SKalle Valo if (chan != 14) 697d4a17304SKalle Valo reg |= ADM8211_CSR_GPIO_O0; 698d4a17304SKalle Valo ADM8211_CSR_WRITE(GPIO, reg); 699d4a17304SKalle Valo } 700d4a17304SKalle Valo 701d4a17304SKalle Valo if (priv->transceiver_type == ADM8211_RFMD2958) { 702d4a17304SKalle Valo /* set PCNT2 */ 703d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x0B, 0x07100); 704d4a17304SKalle Valo /* set PCNT1 P_DESIRED/MID_BIAS */ 705d4a17304SKalle Valo reg = le16_to_cpu(priv->eeprom->cr49); 706d4a17304SKalle Valo reg >>= 13; 707d4a17304SKalle Valo reg <<= 15; 708d4a17304SKalle Valo reg |= ant_power << 9; 709d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x0A, reg); 710d4a17304SKalle Valo /* set TXRX TX_GAIN */ 711d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x09, 0x00050 | 712d4a17304SKalle Valo (priv->pdev->revision < ADM8211_REV_CA ? tx_power : 0)); 713d4a17304SKalle Valo } else { 714d4a17304SKalle Valo reg = ADM8211_CSR_READ(PLCPHD); 715d4a17304SKalle Valo reg &= 0xff00ffff; 716d4a17304SKalle Valo reg |= tx_power << 18; 717d4a17304SKalle Valo ADM8211_CSR_WRITE(PLCPHD, reg); 718d4a17304SKalle Valo } 719d4a17304SKalle Valo 720d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_SELRF | 721d4a17304SKalle Valo ADM8211_SYNRF_PE1 | ADM8211_SYNRF_PHYRST); 722d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); 723d4a17304SKalle Valo msleep(30); 724d4a17304SKalle Valo 725d4a17304SKalle Valo /* RF3000 BBP */ 726d4a17304SKalle Valo if (priv->transceiver_type != ADM8211_RFMD2958) 727d4a17304SKalle Valo adm8211_write_bbp(dev, RF3000_TX_VAR_GAIN__TX_LEN_EXT, 728d4a17304SKalle Valo tx_power<<2); 729d4a17304SKalle Valo adm8211_write_bbp(dev, RF3000_LOW_GAIN_CALIB, lpf_cutoff); 730d4a17304SKalle Valo adm8211_write_bbp(dev, RF3000_HIGH_GAIN_CALIB, lnags_thresh); 731d4a17304SKalle Valo adm8211_write_bbp(dev, 0x1c, priv->pdev->revision == ADM8211_REV_BA ? 732d4a17304SKalle Valo priv->eeprom->cr28 : 0); 733d4a17304SKalle Valo adm8211_write_bbp(dev, 0x1d, priv->eeprom->cr29); 734d4a17304SKalle Valo 735d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, 0); 736d4a17304SKalle Valo 737d4a17304SKalle Valo /* Nothing to do for ADMtek BBP */ 738d4a17304SKalle Valo } else if (priv->bbp_type != ADM8211_TYPE_ADMTEK) 739d4a17304SKalle Valo wiphy_debug(dev->wiphy, "unsupported BBP type %d\n", 740d4a17304SKalle Valo priv->bbp_type); 741d4a17304SKalle Valo 742d4a17304SKalle Valo ADM8211_RESTORE(); 743d4a17304SKalle Valo 744d4a17304SKalle Valo /* update current channel for adhoc (and maybe AP mode) */ 745d4a17304SKalle Valo reg = ADM8211_CSR_READ(CAP0); 746d4a17304SKalle Valo reg &= ~0xF; 747d4a17304SKalle Valo reg |= chan; 748d4a17304SKalle Valo ADM8211_CSR_WRITE(CAP0, reg); 749d4a17304SKalle Valo 750d4a17304SKalle Valo return 0; 751d4a17304SKalle Valo } 752d4a17304SKalle Valo 753d4a17304SKalle Valo static void adm8211_update_mode(struct ieee80211_hw *dev) 754d4a17304SKalle Valo { 755d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 756d4a17304SKalle Valo 757d4a17304SKalle Valo ADM8211_IDLE(); 758d4a17304SKalle Valo 759d4a17304SKalle Valo priv->soft_rx_crc = 0; 760d4a17304SKalle Valo switch (priv->mode) { 761d4a17304SKalle Valo case NL80211_IFTYPE_STATION: 762d4a17304SKalle Valo priv->nar &= ~(ADM8211_NAR_PR | ADM8211_NAR_EA); 763d4a17304SKalle Valo priv->nar |= ADM8211_NAR_ST | ADM8211_NAR_SR; 764d4a17304SKalle Valo break; 765d4a17304SKalle Valo case NL80211_IFTYPE_ADHOC: 766d4a17304SKalle Valo priv->nar &= ~ADM8211_NAR_PR; 767d4a17304SKalle Valo priv->nar |= ADM8211_NAR_EA | ADM8211_NAR_ST | ADM8211_NAR_SR; 768d4a17304SKalle Valo 769d4a17304SKalle Valo /* don't trust the error bits on rev 0x20 and up in adhoc */ 770d4a17304SKalle Valo if (priv->pdev->revision >= ADM8211_REV_BA) 771d4a17304SKalle Valo priv->soft_rx_crc = 1; 772d4a17304SKalle Valo break; 773d4a17304SKalle Valo case NL80211_IFTYPE_MONITOR: 774d4a17304SKalle Valo priv->nar &= ~(ADM8211_NAR_EA | ADM8211_NAR_ST); 775d4a17304SKalle Valo priv->nar |= ADM8211_NAR_PR | ADM8211_NAR_SR; 776d4a17304SKalle Valo break; 777d4a17304SKalle Valo } 778d4a17304SKalle Valo 779d4a17304SKalle Valo ADM8211_RESTORE(); 780d4a17304SKalle Valo } 781d4a17304SKalle Valo 782d4a17304SKalle Valo static void adm8211_hw_init_syn(struct ieee80211_hw *dev) 783d4a17304SKalle Valo { 784d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 785d4a17304SKalle Valo 786d4a17304SKalle Valo switch (priv->transceiver_type) { 787d4a17304SKalle Valo case ADM8211_RFMD2958: 788d4a17304SKalle Valo case ADM8211_RFMD2958_RF3000_CONTROL_POWER: 789d4a17304SKalle Valo /* comments taken from ADMtek vendor driver */ 790d4a17304SKalle Valo 791d4a17304SKalle Valo /* Reset RF2958 after power on */ 792d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x1F, 0x00000); 793d4a17304SKalle Valo /* Initialize RF VCO Core Bias to maximum */ 794d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x0C, 0x3001F); 795d4a17304SKalle Valo /* Initialize IF PLL */ 796d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x01, 0x29C03); 797d4a17304SKalle Valo /* Initialize IF PLL Coarse Tuning */ 798d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x03, 0x1FF6F); 799d4a17304SKalle Valo /* Initialize RF PLL */ 800d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x04, 0x29403); 801d4a17304SKalle Valo /* Initialize RF PLL Coarse Tuning */ 802d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x07, 0x1456F); 803d4a17304SKalle Valo /* Initialize TX gain and filter BW (R9) */ 804d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x09, 805d4a17304SKalle Valo (priv->transceiver_type == ADM8211_RFMD2958 ? 806d4a17304SKalle Valo 0x10050 : 0x00050)); 807d4a17304SKalle Valo /* Initialize CAL register */ 808d4a17304SKalle Valo adm8211_rf_write_syn_rfmd2958(dev, 0x08, 0x3FFF8); 809d4a17304SKalle Valo break; 810d4a17304SKalle Valo 811d4a17304SKalle Valo case ADM8211_MAX2820: 812d4a17304SKalle Valo adm8211_rf_write_syn_max2820(dev, 0x1, 0x01E); 813d4a17304SKalle Valo adm8211_rf_write_syn_max2820(dev, 0x2, 0x001); 814d4a17304SKalle Valo adm8211_rf_write_syn_max2820(dev, 0x3, 0x054); 815d4a17304SKalle Valo adm8211_rf_write_syn_max2820(dev, 0x4, 0x310); 816d4a17304SKalle Valo adm8211_rf_write_syn_max2820(dev, 0x5, 0x000); 817d4a17304SKalle Valo break; 818d4a17304SKalle Valo 819d4a17304SKalle Valo case ADM8211_AL2210L: 820d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x0, 0x0196C); 821d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x1, 0x007CB); 822d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x2, 0x3582F); 823d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x3, 0x010A9); 824d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x4, 0x77280); 825d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x5, 0x45641); 826d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x6, 0xEA130); 827d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x7, 0x80000); 828d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x8, 0x7850F); 829d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0x9, 0xF900C); 830d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0xA, 0x00000); 831d4a17304SKalle Valo adm8211_rf_write_syn_al2210l(dev, 0xB, 0x00000); 832d4a17304SKalle Valo break; 833d4a17304SKalle Valo 834d4a17304SKalle Valo case ADM8211_RFMD2948: 835d4a17304SKalle Valo default: 836d4a17304SKalle Valo break; 837d4a17304SKalle Valo } 838d4a17304SKalle Valo } 839d4a17304SKalle Valo 840d4a17304SKalle Valo static int adm8211_hw_init_bbp(struct ieee80211_hw *dev) 841d4a17304SKalle Valo { 842d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 843d4a17304SKalle Valo u32 reg; 844d4a17304SKalle Valo 845d4a17304SKalle Valo /* write addresses */ 846d4a17304SKalle Valo if (priv->bbp_type == ADM8211_TYPE_INTERSIL) { 847d4a17304SKalle Valo ADM8211_CSR_WRITE(MMIWA, 0x100E0C0A); 848d4a17304SKalle Valo ADM8211_CSR_WRITE(MMIRD0, 0x00007C7E); 849d4a17304SKalle Valo ADM8211_CSR_WRITE(MMIRD1, 0x00100000); 850d4a17304SKalle Valo } else if (priv->bbp_type == ADM8211_TYPE_RFMD || 851d4a17304SKalle Valo priv->bbp_type == ADM8211_TYPE_ADMTEK) { 852d4a17304SKalle Valo /* check specific BBP type */ 853d4a17304SKalle Valo switch (priv->specific_bbptype) { 854d4a17304SKalle Valo case ADM8211_BBP_RFMD3000: 855d4a17304SKalle Valo case ADM8211_BBP_RFMD3002: 856d4a17304SKalle Valo ADM8211_CSR_WRITE(MMIWA, 0x00009101); 857d4a17304SKalle Valo ADM8211_CSR_WRITE(MMIRD0, 0x00000301); 858d4a17304SKalle Valo break; 859d4a17304SKalle Valo 860d4a17304SKalle Valo case ADM8211_BBP_ADM8011: 861d4a17304SKalle Valo ADM8211_CSR_WRITE(MMIWA, 0x00008903); 862d4a17304SKalle Valo ADM8211_CSR_WRITE(MMIRD0, 0x00001716); 863d4a17304SKalle Valo 864d4a17304SKalle Valo reg = ADM8211_CSR_READ(BBPCTL); 865d4a17304SKalle Valo reg &= ~ADM8211_BBPCTL_TYPE; 866d4a17304SKalle Valo reg |= 0x5 << 18; 867d4a17304SKalle Valo ADM8211_CSR_WRITE(BBPCTL, reg); 868d4a17304SKalle Valo break; 869d4a17304SKalle Valo } 870d4a17304SKalle Valo 871d4a17304SKalle Valo switch (priv->pdev->revision) { 872d4a17304SKalle Valo case ADM8211_REV_CA: 873d4a17304SKalle Valo if (priv->transceiver_type == ADM8211_RFMD2958 || 874d4a17304SKalle Valo priv->transceiver_type == ADM8211_RFMD2958_RF3000_CONTROL_POWER || 875d4a17304SKalle Valo priv->transceiver_type == ADM8211_RFMD2948) 876d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNCTL, 0x1 << 22); 877d4a17304SKalle Valo else if (priv->transceiver_type == ADM8211_MAX2820 || 878d4a17304SKalle Valo priv->transceiver_type == ADM8211_AL2210L) 879d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNCTL, 0x3 << 22); 880d4a17304SKalle Valo break; 881d4a17304SKalle Valo 882d4a17304SKalle Valo case ADM8211_REV_BA: 883d4a17304SKalle Valo reg = ADM8211_CSR_READ(MMIRD1); 884d4a17304SKalle Valo reg &= 0x0000FFFF; 885d4a17304SKalle Valo reg |= 0x7e100000; 886d4a17304SKalle Valo ADM8211_CSR_WRITE(MMIRD1, reg); 887d4a17304SKalle Valo break; 888d4a17304SKalle Valo 889d4a17304SKalle Valo case ADM8211_REV_AB: 890d4a17304SKalle Valo case ADM8211_REV_AF: 891d4a17304SKalle Valo default: 892d4a17304SKalle Valo ADM8211_CSR_WRITE(MMIRD1, 0x7e100000); 893d4a17304SKalle Valo break; 894d4a17304SKalle Valo } 895d4a17304SKalle Valo 896d4a17304SKalle Valo /* For RFMD */ 897d4a17304SKalle Valo ADM8211_CSR_WRITE(MACTEST, 0x800); 898d4a17304SKalle Valo } 899d4a17304SKalle Valo 900d4a17304SKalle Valo adm8211_hw_init_syn(dev); 901d4a17304SKalle Valo 902d4a17304SKalle Valo /* Set RF Power control IF pin to PE1+PHYRST# */ 903d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_SELRF | 904d4a17304SKalle Valo ADM8211_SYNRF_PE1 | ADM8211_SYNRF_PHYRST); 905d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); 906d4a17304SKalle Valo msleep(20); 907d4a17304SKalle Valo 908d4a17304SKalle Valo /* write BBP regs */ 909d4a17304SKalle Valo if (priv->bbp_type == ADM8211_TYPE_RFMD) { 910d4a17304SKalle Valo /* RF3000 BBP */ 911d4a17304SKalle Valo /* another set: 912d4a17304SKalle Valo * 11: c8 913d4a17304SKalle Valo * 14: 14 914d4a17304SKalle Valo * 15: 50 (chan 1..13; chan 14: d0) 915d4a17304SKalle Valo * 1c: 00 916d4a17304SKalle Valo * 1d: 84 917d4a17304SKalle Valo */ 918d4a17304SKalle Valo adm8211_write_bbp(dev, RF3000_CCA_CTRL, 0x80); 919d4a17304SKalle Valo /* antenna selection: diversity */ 920d4a17304SKalle Valo adm8211_write_bbp(dev, RF3000_DIVERSITY__RSSI, 0x80); 921d4a17304SKalle Valo adm8211_write_bbp(dev, RF3000_TX_VAR_GAIN__TX_LEN_EXT, 0x74); 922d4a17304SKalle Valo adm8211_write_bbp(dev, RF3000_LOW_GAIN_CALIB, 0x38); 923d4a17304SKalle Valo adm8211_write_bbp(dev, RF3000_HIGH_GAIN_CALIB, 0x40); 924d4a17304SKalle Valo 925d4a17304SKalle Valo if (priv->eeprom->major_version < 2) { 926d4a17304SKalle Valo adm8211_write_bbp(dev, 0x1c, 0x00); 927d4a17304SKalle Valo adm8211_write_bbp(dev, 0x1d, 0x80); 928d4a17304SKalle Valo } else { 929d4a17304SKalle Valo if (priv->pdev->revision == ADM8211_REV_BA) 930d4a17304SKalle Valo adm8211_write_bbp(dev, 0x1c, priv->eeprom->cr28); 931d4a17304SKalle Valo else 932d4a17304SKalle Valo adm8211_write_bbp(dev, 0x1c, 0x00); 933d4a17304SKalle Valo 934d4a17304SKalle Valo adm8211_write_bbp(dev, 0x1d, priv->eeprom->cr29); 935d4a17304SKalle Valo } 936d4a17304SKalle Valo } else if (priv->bbp_type == ADM8211_TYPE_ADMTEK) { 937d4a17304SKalle Valo /* reset baseband */ 938d4a17304SKalle Valo adm8211_write_bbp(dev, 0x00, 0xFF); 939d4a17304SKalle Valo /* antenna selection: diversity */ 940d4a17304SKalle Valo adm8211_write_bbp(dev, 0x07, 0x0A); 941d4a17304SKalle Valo 942d4a17304SKalle Valo /* TODO: find documentation for this */ 943d4a17304SKalle Valo switch (priv->transceiver_type) { 944d4a17304SKalle Valo case ADM8211_RFMD2958: 945d4a17304SKalle Valo case ADM8211_RFMD2958_RF3000_CONTROL_POWER: 946d4a17304SKalle Valo adm8211_write_bbp(dev, 0x00, 0x00); 947d4a17304SKalle Valo adm8211_write_bbp(dev, 0x01, 0x00); 948d4a17304SKalle Valo adm8211_write_bbp(dev, 0x02, 0x00); 949d4a17304SKalle Valo adm8211_write_bbp(dev, 0x03, 0x00); 950d4a17304SKalle Valo adm8211_write_bbp(dev, 0x06, 0x0f); 951d4a17304SKalle Valo adm8211_write_bbp(dev, 0x09, 0x00); 952d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0a, 0x00); 953d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0b, 0x00); 954d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0c, 0x00); 955d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0f, 0xAA); 956d4a17304SKalle Valo adm8211_write_bbp(dev, 0x10, 0x8c); 957d4a17304SKalle Valo adm8211_write_bbp(dev, 0x11, 0x43); 958d4a17304SKalle Valo adm8211_write_bbp(dev, 0x18, 0x40); 959d4a17304SKalle Valo adm8211_write_bbp(dev, 0x20, 0x23); 960d4a17304SKalle Valo adm8211_write_bbp(dev, 0x21, 0x02); 961d4a17304SKalle Valo adm8211_write_bbp(dev, 0x22, 0x28); 962d4a17304SKalle Valo adm8211_write_bbp(dev, 0x23, 0x30); 963d4a17304SKalle Valo adm8211_write_bbp(dev, 0x24, 0x2d); 964d4a17304SKalle Valo adm8211_write_bbp(dev, 0x28, 0x35); 965d4a17304SKalle Valo adm8211_write_bbp(dev, 0x2a, 0x8c); 966d4a17304SKalle Valo adm8211_write_bbp(dev, 0x2b, 0x81); 967d4a17304SKalle Valo adm8211_write_bbp(dev, 0x2c, 0x44); 968d4a17304SKalle Valo adm8211_write_bbp(dev, 0x2d, 0x0A); 969d4a17304SKalle Valo adm8211_write_bbp(dev, 0x29, 0x40); 970d4a17304SKalle Valo adm8211_write_bbp(dev, 0x60, 0x08); 971d4a17304SKalle Valo adm8211_write_bbp(dev, 0x64, 0x01); 972d4a17304SKalle Valo break; 973d4a17304SKalle Valo 974d4a17304SKalle Valo case ADM8211_MAX2820: 975d4a17304SKalle Valo adm8211_write_bbp(dev, 0x00, 0x00); 976d4a17304SKalle Valo adm8211_write_bbp(dev, 0x01, 0x00); 977d4a17304SKalle Valo adm8211_write_bbp(dev, 0x02, 0x00); 978d4a17304SKalle Valo adm8211_write_bbp(dev, 0x03, 0x00); 979d4a17304SKalle Valo adm8211_write_bbp(dev, 0x06, 0x0f); 980d4a17304SKalle Valo adm8211_write_bbp(dev, 0x09, 0x05); 981d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0a, 0x02); 982d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0b, 0x00); 983d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0c, 0x0f); 984d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0f, 0x55); 985d4a17304SKalle Valo adm8211_write_bbp(dev, 0x10, 0x8d); 986d4a17304SKalle Valo adm8211_write_bbp(dev, 0x11, 0x43); 987d4a17304SKalle Valo adm8211_write_bbp(dev, 0x18, 0x4a); 988d4a17304SKalle Valo adm8211_write_bbp(dev, 0x20, 0x20); 989d4a17304SKalle Valo adm8211_write_bbp(dev, 0x21, 0x02); 990d4a17304SKalle Valo adm8211_write_bbp(dev, 0x22, 0x23); 991d4a17304SKalle Valo adm8211_write_bbp(dev, 0x23, 0x30); 992d4a17304SKalle Valo adm8211_write_bbp(dev, 0x24, 0x2d); 993d4a17304SKalle Valo adm8211_write_bbp(dev, 0x2a, 0x8c); 994d4a17304SKalle Valo adm8211_write_bbp(dev, 0x2b, 0x81); 995d4a17304SKalle Valo adm8211_write_bbp(dev, 0x2c, 0x44); 996d4a17304SKalle Valo adm8211_write_bbp(dev, 0x29, 0x4a); 997d4a17304SKalle Valo adm8211_write_bbp(dev, 0x60, 0x2b); 998d4a17304SKalle Valo adm8211_write_bbp(dev, 0x64, 0x01); 999d4a17304SKalle Valo break; 1000d4a17304SKalle Valo 1001d4a17304SKalle Valo case ADM8211_AL2210L: 1002d4a17304SKalle Valo adm8211_write_bbp(dev, 0x00, 0x00); 1003d4a17304SKalle Valo adm8211_write_bbp(dev, 0x01, 0x00); 1004d4a17304SKalle Valo adm8211_write_bbp(dev, 0x02, 0x00); 1005d4a17304SKalle Valo adm8211_write_bbp(dev, 0x03, 0x00); 1006d4a17304SKalle Valo adm8211_write_bbp(dev, 0x06, 0x0f); 1007d4a17304SKalle Valo adm8211_write_bbp(dev, 0x07, 0x05); 1008d4a17304SKalle Valo adm8211_write_bbp(dev, 0x08, 0x03); 1009d4a17304SKalle Valo adm8211_write_bbp(dev, 0x09, 0x00); 1010d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0a, 0x00); 1011d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0b, 0x00); 1012d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0c, 0x10); 1013d4a17304SKalle Valo adm8211_write_bbp(dev, 0x0f, 0x55); 1014d4a17304SKalle Valo adm8211_write_bbp(dev, 0x10, 0x8d); 1015d4a17304SKalle Valo adm8211_write_bbp(dev, 0x11, 0x43); 1016d4a17304SKalle Valo adm8211_write_bbp(dev, 0x18, 0x4a); 1017d4a17304SKalle Valo adm8211_write_bbp(dev, 0x20, 0x20); 1018d4a17304SKalle Valo adm8211_write_bbp(dev, 0x21, 0x02); 1019d4a17304SKalle Valo adm8211_write_bbp(dev, 0x22, 0x23); 1020d4a17304SKalle Valo adm8211_write_bbp(dev, 0x23, 0x30); 1021d4a17304SKalle Valo adm8211_write_bbp(dev, 0x24, 0x2d); 1022d4a17304SKalle Valo adm8211_write_bbp(dev, 0x2a, 0xaa); 1023d4a17304SKalle Valo adm8211_write_bbp(dev, 0x2b, 0x81); 1024d4a17304SKalle Valo adm8211_write_bbp(dev, 0x2c, 0x44); 1025d4a17304SKalle Valo adm8211_write_bbp(dev, 0x29, 0xfa); 1026d4a17304SKalle Valo adm8211_write_bbp(dev, 0x60, 0x2d); 1027d4a17304SKalle Valo adm8211_write_bbp(dev, 0x64, 0x01); 1028d4a17304SKalle Valo break; 1029d4a17304SKalle Valo 1030d4a17304SKalle Valo case ADM8211_RFMD2948: 1031d4a17304SKalle Valo break; 1032d4a17304SKalle Valo 1033d4a17304SKalle Valo default: 1034d4a17304SKalle Valo wiphy_debug(dev->wiphy, "unsupported transceiver %d\n", 1035d4a17304SKalle Valo priv->transceiver_type); 1036d4a17304SKalle Valo break; 1037d4a17304SKalle Valo } 1038d4a17304SKalle Valo } else 1039d4a17304SKalle Valo wiphy_debug(dev->wiphy, "unsupported BBP %d\n", priv->bbp_type); 1040d4a17304SKalle Valo 1041d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, 0); 1042d4a17304SKalle Valo 1043d4a17304SKalle Valo /* Set RF CAL control source to MAC control */ 1044d4a17304SKalle Valo reg = ADM8211_CSR_READ(SYNCTL); 1045d4a17304SKalle Valo reg |= ADM8211_SYNCTL_SELCAL; 1046d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNCTL, reg); 1047d4a17304SKalle Valo 1048d4a17304SKalle Valo return 0; 1049d4a17304SKalle Valo } 1050d4a17304SKalle Valo 1051d4a17304SKalle Valo /* configures hw beacons/probe responses */ 1052d4a17304SKalle Valo static int adm8211_set_rate(struct ieee80211_hw *dev) 1053d4a17304SKalle Valo { 1054d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1055d4a17304SKalle Valo u32 reg; 1056d4a17304SKalle Valo int i = 0; 1057d4a17304SKalle Valo u8 rate_buf[12] = {0}; 1058d4a17304SKalle Valo 1059d4a17304SKalle Valo /* write supported rates */ 1060d4a17304SKalle Valo if (priv->pdev->revision != ADM8211_REV_BA) { 1061d4a17304SKalle Valo rate_buf[0] = ARRAY_SIZE(adm8211_rates); 1062d4a17304SKalle Valo for (i = 0; i < ARRAY_SIZE(adm8211_rates); i++) 1063d4a17304SKalle Valo rate_buf[i + 1] = (adm8211_rates[i].bitrate / 5) | 0x80; 1064d4a17304SKalle Valo } else { 1065d4a17304SKalle Valo /* workaround for rev BA specific bug */ 1066d4a17304SKalle Valo rate_buf[0] = 0x04; 1067d4a17304SKalle Valo rate_buf[1] = 0x82; 1068d4a17304SKalle Valo rate_buf[2] = 0x04; 1069d4a17304SKalle Valo rate_buf[3] = 0x0b; 1070d4a17304SKalle Valo rate_buf[4] = 0x16; 1071d4a17304SKalle Valo } 1072d4a17304SKalle Valo 1073d4a17304SKalle Valo adm8211_write_sram_bytes(dev, ADM8211_SRAM_SUPP_RATE, rate_buf, 1074d4a17304SKalle Valo ARRAY_SIZE(adm8211_rates) + 1); 1075d4a17304SKalle Valo 1076d4a17304SKalle Valo reg = ADM8211_CSR_READ(PLCPHD) & 0x00FFFFFF; /* keep bits 0-23 */ 1077d4a17304SKalle Valo reg |= 1 << 15; /* short preamble */ 1078d4a17304SKalle Valo reg |= 110 << 24; 1079d4a17304SKalle Valo ADM8211_CSR_WRITE(PLCPHD, reg); 1080d4a17304SKalle Valo 1081d4a17304SKalle Valo /* MTMLT = 512 TU (max TX MSDU lifetime) 1082d4a17304SKalle Valo * BCNTSIG = plcp_signal (beacon, probe resp, and atim TX rate) 1083d4a17304SKalle Valo * SRTYLIM = 224 (short retry limit, TX header value is default) */ 1084d4a17304SKalle Valo ADM8211_CSR_WRITE(TXLMT, (512 << 16) | (110 << 8) | (224 << 0)); 1085d4a17304SKalle Valo 1086d4a17304SKalle Valo return 0; 1087d4a17304SKalle Valo } 1088d4a17304SKalle Valo 1089d4a17304SKalle Valo static void adm8211_hw_init(struct ieee80211_hw *dev) 1090d4a17304SKalle Valo { 1091d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1092d4a17304SKalle Valo u32 reg; 1093d4a17304SKalle Valo u8 cline; 1094d4a17304SKalle Valo 1095d4a17304SKalle Valo reg = ADM8211_CSR_READ(PAR); 1096d4a17304SKalle Valo reg |= ADM8211_PAR_MRLE | ADM8211_PAR_MRME; 1097d4a17304SKalle Valo reg &= ~(ADM8211_PAR_BAR | ADM8211_PAR_CAL); 1098d4a17304SKalle Valo 1099d4a17304SKalle Valo if (!pci_set_mwi(priv->pdev)) { 1100d4a17304SKalle Valo reg |= 0x1 << 24; 1101d4a17304SKalle Valo pci_read_config_byte(priv->pdev, PCI_CACHE_LINE_SIZE, &cline); 1102d4a17304SKalle Valo 1103d4a17304SKalle Valo switch (cline) { 1104d4a17304SKalle Valo case 0x8: 1105d4a17304SKalle Valo reg |= (0x1 << 14); 1106d4a17304SKalle Valo break; 1107d4a17304SKalle Valo case 0x10: 1108d4a17304SKalle Valo reg |= (0x2 << 14); 1109d4a17304SKalle Valo break; 1110d4a17304SKalle Valo case 0x20: 1111d4a17304SKalle Valo reg |= (0x3 << 14); 1112d4a17304SKalle Valo break; 1113d4a17304SKalle Valo default: 1114d4a17304SKalle Valo reg |= (0x0 << 14); 1115d4a17304SKalle Valo break; 1116d4a17304SKalle Valo } 1117d4a17304SKalle Valo } 1118d4a17304SKalle Valo 1119d4a17304SKalle Valo ADM8211_CSR_WRITE(PAR, reg); 1120d4a17304SKalle Valo 1121d4a17304SKalle Valo reg = ADM8211_CSR_READ(CSR_TEST1); 1122d4a17304SKalle Valo reg &= ~(0xF << 28); 1123d4a17304SKalle Valo reg |= (1 << 28) | (1 << 31); 1124d4a17304SKalle Valo ADM8211_CSR_WRITE(CSR_TEST1, reg); 1125d4a17304SKalle Valo 1126d4a17304SKalle Valo /* lose link after 4 lost beacons */ 1127d4a17304SKalle Valo reg = (0x04 << 21) | ADM8211_WCSR_TSFTWE | ADM8211_WCSR_LSOE; 1128d4a17304SKalle Valo ADM8211_CSR_WRITE(WCSR, reg); 1129d4a17304SKalle Valo 1130d4a17304SKalle Valo /* Disable APM, enable receive FIFO threshold, and set drain receive 1131d4a17304SKalle Valo * threshold to store-and-forward */ 1132d4a17304SKalle Valo reg = ADM8211_CSR_READ(CMDR); 1133d4a17304SKalle Valo reg &= ~(ADM8211_CMDR_APM | ADM8211_CMDR_DRT); 1134d4a17304SKalle Valo reg |= ADM8211_CMDR_RTE | ADM8211_CMDR_DRT_SF; 1135d4a17304SKalle Valo ADM8211_CSR_WRITE(CMDR, reg); 1136d4a17304SKalle Valo 1137d4a17304SKalle Valo adm8211_set_rate(dev); 1138d4a17304SKalle Valo 1139d4a17304SKalle Valo /* 4-bit values: 1140d4a17304SKalle Valo * PWR1UP = 8 * 2 ms 1141d4a17304SKalle Valo * PWR0PAPE = 8 us or 5 us 1142d4a17304SKalle Valo * PWR1PAPE = 1 us or 3 us 1143d4a17304SKalle Valo * PWR0TRSW = 5 us 1144d4a17304SKalle Valo * PWR1TRSW = 12 us 1145d4a17304SKalle Valo * PWR0PE2 = 13 us 1146d4a17304SKalle Valo * PWR1PE2 = 1 us 1147d4a17304SKalle Valo * PWR0TXPE = 8 or 6 */ 1148d4a17304SKalle Valo if (priv->pdev->revision < ADM8211_REV_CA) 1149d4a17304SKalle Valo ADM8211_CSR_WRITE(TOFS2, 0x8815cd18); 1150d4a17304SKalle Valo else 1151d4a17304SKalle Valo ADM8211_CSR_WRITE(TOFS2, 0x8535cd16); 1152d4a17304SKalle Valo 1153d4a17304SKalle Valo /* Enable store and forward for transmit */ 1154d4a17304SKalle Valo priv->nar = ADM8211_NAR_SF | ADM8211_NAR_PB; 1155d4a17304SKalle Valo ADM8211_CSR_WRITE(NAR, priv->nar); 1156d4a17304SKalle Valo 1157d4a17304SKalle Valo /* Reset RF */ 1158d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_RADIO); 1159d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); 1160d4a17304SKalle Valo msleep(10); 1161d4a17304SKalle Valo ADM8211_CSR_WRITE(SYNRF, 0); 1162d4a17304SKalle Valo ADM8211_CSR_READ(SYNRF); 1163d4a17304SKalle Valo msleep(5); 1164d4a17304SKalle Valo 1165d4a17304SKalle Valo /* Set CFP Max Duration to 0x10 TU */ 1166d4a17304SKalle Valo reg = ADM8211_CSR_READ(CFPP); 1167d4a17304SKalle Valo reg &= ~(0xffff << 8); 1168d4a17304SKalle Valo reg |= 0x0010 << 8; 1169d4a17304SKalle Valo ADM8211_CSR_WRITE(CFPP, reg); 1170d4a17304SKalle Valo 1171d4a17304SKalle Valo /* USCNT = 0x16 (number of system clocks, 22 MHz, in 1us 1172d4a17304SKalle Valo * TUCNT = 0x3ff - Tu counter 1024 us */ 1173d4a17304SKalle Valo ADM8211_CSR_WRITE(TOFS0, (0x16 << 24) | 0x3ff); 1174d4a17304SKalle Valo 1175d4a17304SKalle Valo /* SLOT=20 us, SIFS=110 cycles of 22 MHz (5 us), 1176d4a17304SKalle Valo * DIFS=50 us, EIFS=100 us */ 1177d4a17304SKalle Valo if (priv->pdev->revision < ADM8211_REV_CA) 1178d4a17304SKalle Valo ADM8211_CSR_WRITE(IFST, (20 << 23) | (110 << 15) | 1179d4a17304SKalle Valo (50 << 9) | 100); 1180d4a17304SKalle Valo else 1181d4a17304SKalle Valo ADM8211_CSR_WRITE(IFST, (20 << 23) | (24 << 15) | 1182d4a17304SKalle Valo (50 << 9) | 100); 1183d4a17304SKalle Valo 1184d4a17304SKalle Valo /* PCNT = 1 (MAC idle time awake/sleep, unit S) 1185d4a17304SKalle Valo * RMRD = 2346 * 8 + 1 us (max RX duration) */ 1186d4a17304SKalle Valo ADM8211_CSR_WRITE(RMD, (1 << 16) | 18769); 1187d4a17304SKalle Valo 1188d4a17304SKalle Valo /* MART=65535 us, MIRT=256 us, TSFTOFST=0 us */ 1189d4a17304SKalle Valo ADM8211_CSR_WRITE(RSPT, 0xffffff00); 1190d4a17304SKalle Valo 1191d4a17304SKalle Valo /* Initialize BBP (and SYN) */ 1192d4a17304SKalle Valo adm8211_hw_init_bbp(dev); 1193d4a17304SKalle Valo 1194d4a17304SKalle Valo /* make sure interrupts are off */ 1195d4a17304SKalle Valo ADM8211_CSR_WRITE(IER, 0); 1196d4a17304SKalle Valo 1197d4a17304SKalle Valo /* ACK interrupts */ 1198d4a17304SKalle Valo ADM8211_CSR_WRITE(STSR, ADM8211_CSR_READ(STSR)); 1199d4a17304SKalle Valo 1200d4a17304SKalle Valo /* Setup WEP (turns it off for now) */ 1201d4a17304SKalle Valo reg = ADM8211_CSR_READ(MACTEST); 1202d4a17304SKalle Valo reg &= ~(7 << 20); 1203d4a17304SKalle Valo ADM8211_CSR_WRITE(MACTEST, reg); 1204d4a17304SKalle Valo 1205d4a17304SKalle Valo reg = ADM8211_CSR_READ(WEPCTL); 1206d4a17304SKalle Valo reg &= ~ADM8211_WEPCTL_WEPENABLE; 1207d4a17304SKalle Valo reg |= ADM8211_WEPCTL_WEPRXBYP; 1208d4a17304SKalle Valo ADM8211_CSR_WRITE(WEPCTL, reg); 1209d4a17304SKalle Valo 1210d4a17304SKalle Valo /* Clear the missed-packet counter. */ 1211d4a17304SKalle Valo ADM8211_CSR_READ(LPC); 1212d4a17304SKalle Valo } 1213d4a17304SKalle Valo 1214d4a17304SKalle Valo static int adm8211_hw_reset(struct ieee80211_hw *dev) 1215d4a17304SKalle Valo { 1216d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1217d4a17304SKalle Valo u32 reg, tmp; 1218d4a17304SKalle Valo int timeout = 100; 1219d4a17304SKalle Valo 1220d4a17304SKalle Valo /* Power-on issue */ 1221d4a17304SKalle Valo /* TODO: check if this is necessary */ 1222d4a17304SKalle Valo ADM8211_CSR_WRITE(FRCTL, 0); 1223d4a17304SKalle Valo 1224d4a17304SKalle Valo /* Reset the chip */ 1225d4a17304SKalle Valo tmp = ADM8211_CSR_READ(PAR); 1226d4a17304SKalle Valo ADM8211_CSR_WRITE(PAR, ADM8211_PAR_SWR); 1227d4a17304SKalle Valo 1228d4a17304SKalle Valo while ((ADM8211_CSR_READ(PAR) & ADM8211_PAR_SWR) && timeout--) 1229d4a17304SKalle Valo msleep(50); 1230d4a17304SKalle Valo 1231d4a17304SKalle Valo if (timeout <= 0) 1232d4a17304SKalle Valo return -ETIMEDOUT; 1233d4a17304SKalle Valo 1234d4a17304SKalle Valo ADM8211_CSR_WRITE(PAR, tmp); 1235d4a17304SKalle Valo 1236d4a17304SKalle Valo if (priv->pdev->revision == ADM8211_REV_BA && 1237d4a17304SKalle Valo (priv->transceiver_type == ADM8211_RFMD2958_RF3000_CONTROL_POWER || 1238d4a17304SKalle Valo priv->transceiver_type == ADM8211_RFMD2958)) { 1239d4a17304SKalle Valo reg = ADM8211_CSR_READ(CSR_TEST1); 1240d4a17304SKalle Valo reg |= (1 << 4) | (1 << 5); 1241d4a17304SKalle Valo ADM8211_CSR_WRITE(CSR_TEST1, reg); 1242d4a17304SKalle Valo } else if (priv->pdev->revision == ADM8211_REV_CA) { 1243d4a17304SKalle Valo reg = ADM8211_CSR_READ(CSR_TEST1); 1244d4a17304SKalle Valo reg &= ~((1 << 4) | (1 << 5)); 1245d4a17304SKalle Valo ADM8211_CSR_WRITE(CSR_TEST1, reg); 1246d4a17304SKalle Valo } 1247d4a17304SKalle Valo 1248d4a17304SKalle Valo ADM8211_CSR_WRITE(FRCTL, 0); 1249d4a17304SKalle Valo 1250d4a17304SKalle Valo reg = ADM8211_CSR_READ(CSR_TEST0); 1251d4a17304SKalle Valo reg |= ADM8211_CSR_TEST0_EPRLD; /* EEPROM Recall */ 1252d4a17304SKalle Valo ADM8211_CSR_WRITE(CSR_TEST0, reg); 1253d4a17304SKalle Valo 1254d4a17304SKalle Valo adm8211_clear_sram(dev); 1255d4a17304SKalle Valo 1256d4a17304SKalle Valo return 0; 1257d4a17304SKalle Valo } 1258d4a17304SKalle Valo 1259d4a17304SKalle Valo static u64 adm8211_get_tsft(struct ieee80211_hw *dev, 1260d4a17304SKalle Valo struct ieee80211_vif *vif) 1261d4a17304SKalle Valo { 1262d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1263d4a17304SKalle Valo u32 tsftl; 1264d4a17304SKalle Valo u64 tsft; 1265d4a17304SKalle Valo 1266d4a17304SKalle Valo tsftl = ADM8211_CSR_READ(TSFTL); 1267d4a17304SKalle Valo tsft = ADM8211_CSR_READ(TSFTH); 1268d4a17304SKalle Valo tsft <<= 32; 1269d4a17304SKalle Valo tsft |= tsftl; 1270d4a17304SKalle Valo 1271d4a17304SKalle Valo return tsft; 1272d4a17304SKalle Valo } 1273d4a17304SKalle Valo 1274d4a17304SKalle Valo static void adm8211_set_interval(struct ieee80211_hw *dev, 1275d4a17304SKalle Valo unsigned short bi, unsigned short li) 1276d4a17304SKalle Valo { 1277d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1278d4a17304SKalle Valo u32 reg; 1279d4a17304SKalle Valo 1280d4a17304SKalle Valo /* BP (beacon interval) = data->beacon_interval 1281d4a17304SKalle Valo * LI (listen interval) = data->listen_interval (in beacon intervals) */ 1282d4a17304SKalle Valo reg = (bi << 16) | li; 1283d4a17304SKalle Valo ADM8211_CSR_WRITE(BPLI, reg); 1284d4a17304SKalle Valo } 1285d4a17304SKalle Valo 1286d4a17304SKalle Valo static void adm8211_set_bssid(struct ieee80211_hw *dev, const u8 *bssid) 1287d4a17304SKalle Valo { 1288d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1289d4a17304SKalle Valo u32 reg; 1290d4a17304SKalle Valo 1291d4a17304SKalle Valo ADM8211_CSR_WRITE(BSSID0, le32_to_cpu(*(__le32 *)bssid)); 1292d4a17304SKalle Valo reg = ADM8211_CSR_READ(ABDA1); 1293d4a17304SKalle Valo reg &= 0x0000ffff; 1294d4a17304SKalle Valo reg |= (bssid[4] << 16) | (bssid[5] << 24); 1295d4a17304SKalle Valo ADM8211_CSR_WRITE(ABDA1, reg); 1296d4a17304SKalle Valo } 1297d4a17304SKalle Valo 1298d4a17304SKalle Valo static int adm8211_config(struct ieee80211_hw *dev, u32 changed) 1299d4a17304SKalle Valo { 1300d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1301d4a17304SKalle Valo struct ieee80211_conf *conf = &dev->conf; 1302d4a17304SKalle Valo int channel = 1303d4a17304SKalle Valo ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); 1304d4a17304SKalle Valo 1305d4a17304SKalle Valo if (channel != priv->channel) { 1306d4a17304SKalle Valo priv->channel = channel; 1307d4a17304SKalle Valo adm8211_rf_set_channel(dev, priv->channel); 1308d4a17304SKalle Valo } 1309d4a17304SKalle Valo 1310d4a17304SKalle Valo return 0; 1311d4a17304SKalle Valo } 1312d4a17304SKalle Valo 1313d4a17304SKalle Valo static void adm8211_bss_info_changed(struct ieee80211_hw *dev, 1314d4a17304SKalle Valo struct ieee80211_vif *vif, 1315d4a17304SKalle Valo struct ieee80211_bss_conf *conf, 1316d4a17304SKalle Valo u32 changes) 1317d4a17304SKalle Valo { 1318d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1319d4a17304SKalle Valo 1320d4a17304SKalle Valo if (!(changes & BSS_CHANGED_BSSID)) 1321d4a17304SKalle Valo return; 1322d4a17304SKalle Valo 1323d4a17304SKalle Valo if (!ether_addr_equal(conf->bssid, priv->bssid)) { 1324d4a17304SKalle Valo adm8211_set_bssid(dev, conf->bssid); 1325d4a17304SKalle Valo memcpy(priv->bssid, conf->bssid, ETH_ALEN); 1326d4a17304SKalle Valo } 1327d4a17304SKalle Valo } 1328d4a17304SKalle Valo 1329d4a17304SKalle Valo static u64 adm8211_prepare_multicast(struct ieee80211_hw *hw, 1330d4a17304SKalle Valo struct netdev_hw_addr_list *mc_list) 1331d4a17304SKalle Valo { 1332d4a17304SKalle Valo unsigned int bit_nr; 1333d4a17304SKalle Valo u32 mc_filter[2]; 1334d4a17304SKalle Valo struct netdev_hw_addr *ha; 1335d4a17304SKalle Valo 1336d4a17304SKalle Valo mc_filter[1] = mc_filter[0] = 0; 1337d4a17304SKalle Valo 1338d4a17304SKalle Valo netdev_hw_addr_list_for_each(ha, mc_list) { 1339d4a17304SKalle Valo bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; 1340d4a17304SKalle Valo 1341d4a17304SKalle Valo bit_nr &= 0x3F; 1342d4a17304SKalle Valo mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); 1343d4a17304SKalle Valo } 1344d4a17304SKalle Valo 1345d4a17304SKalle Valo return mc_filter[0] | ((u64)(mc_filter[1]) << 32); 1346d4a17304SKalle Valo } 1347d4a17304SKalle Valo 1348d4a17304SKalle Valo static void adm8211_configure_filter(struct ieee80211_hw *dev, 1349d4a17304SKalle Valo unsigned int changed_flags, 1350d4a17304SKalle Valo unsigned int *total_flags, 1351d4a17304SKalle Valo u64 multicast) 1352d4a17304SKalle Valo { 1353d4a17304SKalle Valo static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 1354d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1355d4a17304SKalle Valo unsigned int new_flags; 1356d4a17304SKalle Valo u32 mc_filter[2]; 1357d4a17304SKalle Valo 1358d4a17304SKalle Valo mc_filter[0] = multicast; 1359d4a17304SKalle Valo mc_filter[1] = multicast >> 32; 1360d4a17304SKalle Valo 1361d4a17304SKalle Valo new_flags = 0; 1362d4a17304SKalle Valo 1363d4a17304SKalle Valo if (*total_flags & FIF_ALLMULTI || multicast == ~(0ULL)) { 1364d4a17304SKalle Valo new_flags |= FIF_ALLMULTI; 1365d4a17304SKalle Valo priv->nar &= ~ADM8211_NAR_PR; 1366d4a17304SKalle Valo priv->nar |= ADM8211_NAR_MM; 1367d4a17304SKalle Valo mc_filter[1] = mc_filter[0] = ~0; 1368d4a17304SKalle Valo } else { 1369d4a17304SKalle Valo priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR); 1370d4a17304SKalle Valo } 1371d4a17304SKalle Valo 1372d4a17304SKalle Valo ADM8211_IDLE_RX(); 1373d4a17304SKalle Valo 1374d4a17304SKalle Valo ADM8211_CSR_WRITE(MAR0, mc_filter[0]); 1375d4a17304SKalle Valo ADM8211_CSR_WRITE(MAR1, mc_filter[1]); 1376d4a17304SKalle Valo ADM8211_CSR_READ(NAR); 1377d4a17304SKalle Valo 1378d4a17304SKalle Valo if (priv->nar & ADM8211_NAR_PR) 1379d4a17304SKalle Valo ieee80211_hw_set(dev, RX_INCLUDES_FCS); 1380d4a17304SKalle Valo else 1381d4a17304SKalle Valo __clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, dev->flags); 1382d4a17304SKalle Valo 1383d4a17304SKalle Valo if (*total_flags & FIF_BCN_PRBRESP_PROMISC) 1384d4a17304SKalle Valo adm8211_set_bssid(dev, bcast); 1385d4a17304SKalle Valo else 1386d4a17304SKalle Valo adm8211_set_bssid(dev, priv->bssid); 1387d4a17304SKalle Valo 1388d4a17304SKalle Valo ADM8211_RESTORE(); 1389d4a17304SKalle Valo 1390d4a17304SKalle Valo *total_flags = new_flags; 1391d4a17304SKalle Valo } 1392d4a17304SKalle Valo 1393d4a17304SKalle Valo static int adm8211_add_interface(struct ieee80211_hw *dev, 1394d4a17304SKalle Valo struct ieee80211_vif *vif) 1395d4a17304SKalle Valo { 1396d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1397d4a17304SKalle Valo if (priv->mode != NL80211_IFTYPE_MONITOR) 1398d4a17304SKalle Valo return -EOPNOTSUPP; 1399d4a17304SKalle Valo 1400d4a17304SKalle Valo switch (vif->type) { 1401d4a17304SKalle Valo case NL80211_IFTYPE_STATION: 1402d4a17304SKalle Valo priv->mode = vif->type; 1403d4a17304SKalle Valo break; 1404d4a17304SKalle Valo default: 1405d4a17304SKalle Valo return -EOPNOTSUPP; 1406d4a17304SKalle Valo } 1407d4a17304SKalle Valo 1408d4a17304SKalle Valo ADM8211_IDLE(); 1409d4a17304SKalle Valo 1410d4a17304SKalle Valo ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)vif->addr)); 1411d4a17304SKalle Valo ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(vif->addr + 4))); 1412d4a17304SKalle Valo 1413d4a17304SKalle Valo adm8211_update_mode(dev); 1414d4a17304SKalle Valo 1415d4a17304SKalle Valo ADM8211_RESTORE(); 1416d4a17304SKalle Valo 1417d4a17304SKalle Valo return 0; 1418d4a17304SKalle Valo } 1419d4a17304SKalle Valo 1420d4a17304SKalle Valo static void adm8211_remove_interface(struct ieee80211_hw *dev, 1421d4a17304SKalle Valo struct ieee80211_vif *vif) 1422d4a17304SKalle Valo { 1423d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1424d4a17304SKalle Valo priv->mode = NL80211_IFTYPE_MONITOR; 1425d4a17304SKalle Valo } 1426d4a17304SKalle Valo 1427d4a17304SKalle Valo static int adm8211_init_rings(struct ieee80211_hw *dev) 1428d4a17304SKalle Valo { 1429d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1430d4a17304SKalle Valo struct adm8211_desc *desc = NULL; 1431d4a17304SKalle Valo struct adm8211_rx_ring_info *rx_info; 1432d4a17304SKalle Valo struct adm8211_tx_ring_info *tx_info; 1433d4a17304SKalle Valo unsigned int i; 1434d4a17304SKalle Valo 1435d4a17304SKalle Valo for (i = 0; i < priv->rx_ring_size; i++) { 1436d4a17304SKalle Valo desc = &priv->rx_ring[i]; 1437d4a17304SKalle Valo desc->status = 0; 1438d4a17304SKalle Valo desc->length = cpu_to_le32(RX_PKT_SIZE); 1439d4a17304SKalle Valo priv->rx_buffers[i].skb = NULL; 1440d4a17304SKalle Valo } 1441d4a17304SKalle Valo /* Mark the end of RX ring; hw returns to base address after this 1442d4a17304SKalle Valo * descriptor */ 1443d4a17304SKalle Valo desc->length |= cpu_to_le32(RDES1_CONTROL_RER); 1444d4a17304SKalle Valo 1445d4a17304SKalle Valo for (i = 0; i < priv->rx_ring_size; i++) { 1446d4a17304SKalle Valo desc = &priv->rx_ring[i]; 1447d4a17304SKalle Valo rx_info = &priv->rx_buffers[i]; 1448d4a17304SKalle Valo 1449d4a17304SKalle Valo rx_info->skb = dev_alloc_skb(RX_PKT_SIZE); 1450d4a17304SKalle Valo if (rx_info->skb == NULL) 1451d4a17304SKalle Valo break; 1452d4a17304SKalle Valo rx_info->mapping = pci_map_single(priv->pdev, 1453d4a17304SKalle Valo skb_tail_pointer(rx_info->skb), 1454d4a17304SKalle Valo RX_PKT_SIZE, 1455d4a17304SKalle Valo PCI_DMA_FROMDEVICE); 1456d15697deSAlexey Khoroshilov if (pci_dma_mapping_error(priv->pdev, rx_info->mapping)) { 1457d15697deSAlexey Khoroshilov dev_kfree_skb(rx_info->skb); 1458d15697deSAlexey Khoroshilov rx_info->skb = NULL; 1459d15697deSAlexey Khoroshilov break; 1460d15697deSAlexey Khoroshilov } 1461d15697deSAlexey Khoroshilov 1462d4a17304SKalle Valo desc->buffer1 = cpu_to_le32(rx_info->mapping); 1463d4a17304SKalle Valo desc->status = cpu_to_le32(RDES0_STATUS_OWN | RDES0_STATUS_SQL); 1464d4a17304SKalle Valo } 1465d4a17304SKalle Valo 1466d4a17304SKalle Valo /* Setup TX ring. TX buffers descriptors will be filled in as needed */ 1467d4a17304SKalle Valo for (i = 0; i < priv->tx_ring_size; i++) { 1468d4a17304SKalle Valo desc = &priv->tx_ring[i]; 1469d4a17304SKalle Valo tx_info = &priv->tx_buffers[i]; 1470d4a17304SKalle Valo 1471d4a17304SKalle Valo tx_info->skb = NULL; 1472d4a17304SKalle Valo tx_info->mapping = 0; 1473d4a17304SKalle Valo desc->status = 0; 1474d4a17304SKalle Valo } 1475d4a17304SKalle Valo desc->length = cpu_to_le32(TDES1_CONTROL_TER); 1476d4a17304SKalle Valo 1477d4a17304SKalle Valo priv->cur_rx = priv->cur_tx = priv->dirty_tx = 0; 1478d4a17304SKalle Valo ADM8211_CSR_WRITE(RDB, priv->rx_ring_dma); 1479d4a17304SKalle Valo ADM8211_CSR_WRITE(TDBD, priv->tx_ring_dma); 1480d4a17304SKalle Valo 1481d4a17304SKalle Valo return 0; 1482d4a17304SKalle Valo } 1483d4a17304SKalle Valo 1484d4a17304SKalle Valo static void adm8211_free_rings(struct ieee80211_hw *dev) 1485d4a17304SKalle Valo { 1486d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1487d4a17304SKalle Valo unsigned int i; 1488d4a17304SKalle Valo 1489d4a17304SKalle Valo for (i = 0; i < priv->rx_ring_size; i++) { 1490d4a17304SKalle Valo if (!priv->rx_buffers[i].skb) 1491d4a17304SKalle Valo continue; 1492d4a17304SKalle Valo 1493d4a17304SKalle Valo pci_unmap_single( 1494d4a17304SKalle Valo priv->pdev, 1495d4a17304SKalle Valo priv->rx_buffers[i].mapping, 1496d4a17304SKalle Valo RX_PKT_SIZE, PCI_DMA_FROMDEVICE); 1497d4a17304SKalle Valo 1498d4a17304SKalle Valo dev_kfree_skb(priv->rx_buffers[i].skb); 1499d4a17304SKalle Valo } 1500d4a17304SKalle Valo 1501d4a17304SKalle Valo for (i = 0; i < priv->tx_ring_size; i++) { 1502d4a17304SKalle Valo if (!priv->tx_buffers[i].skb) 1503d4a17304SKalle Valo continue; 1504d4a17304SKalle Valo 1505d4a17304SKalle Valo pci_unmap_single(priv->pdev, 1506d4a17304SKalle Valo priv->tx_buffers[i].mapping, 1507d4a17304SKalle Valo priv->tx_buffers[i].skb->len, 1508d4a17304SKalle Valo PCI_DMA_TODEVICE); 1509d4a17304SKalle Valo 1510d4a17304SKalle Valo dev_kfree_skb(priv->tx_buffers[i].skb); 1511d4a17304SKalle Valo } 1512d4a17304SKalle Valo } 1513d4a17304SKalle Valo 1514d4a17304SKalle Valo static int adm8211_start(struct ieee80211_hw *dev) 1515d4a17304SKalle Valo { 1516d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1517d4a17304SKalle Valo int retval; 1518d4a17304SKalle Valo 1519d4a17304SKalle Valo /* Power up MAC and RF chips */ 1520d4a17304SKalle Valo retval = adm8211_hw_reset(dev); 1521d4a17304SKalle Valo if (retval) { 1522d4a17304SKalle Valo wiphy_err(dev->wiphy, "hardware reset failed\n"); 1523d4a17304SKalle Valo goto fail; 1524d4a17304SKalle Valo } 1525d4a17304SKalle Valo 1526d4a17304SKalle Valo retval = adm8211_init_rings(dev); 1527d4a17304SKalle Valo if (retval) { 1528d4a17304SKalle Valo wiphy_err(dev->wiphy, "failed to initialize rings\n"); 1529d4a17304SKalle Valo goto fail; 1530d4a17304SKalle Valo } 1531d4a17304SKalle Valo 1532d4a17304SKalle Valo /* Init hardware */ 1533d4a17304SKalle Valo adm8211_hw_init(dev); 1534d4a17304SKalle Valo adm8211_rf_set_channel(dev, priv->channel); 1535d4a17304SKalle Valo 1536d4a17304SKalle Valo retval = request_irq(priv->pdev->irq, adm8211_interrupt, 1537d4a17304SKalle Valo IRQF_SHARED, "adm8211", dev); 1538d4a17304SKalle Valo if (retval) { 1539d4a17304SKalle Valo wiphy_err(dev->wiphy, "failed to register IRQ handler\n"); 1540d4a17304SKalle Valo goto fail; 1541d4a17304SKalle Valo } 1542d4a17304SKalle Valo 1543d4a17304SKalle Valo ADM8211_CSR_WRITE(IER, ADM8211_IER_NIE | ADM8211_IER_AIE | 1544d4a17304SKalle Valo ADM8211_IER_RCIE | ADM8211_IER_TCIE | 1545d4a17304SKalle Valo ADM8211_IER_TDUIE | ADM8211_IER_GPTIE); 1546d4a17304SKalle Valo priv->mode = NL80211_IFTYPE_MONITOR; 1547d4a17304SKalle Valo adm8211_update_mode(dev); 1548d4a17304SKalle Valo ADM8211_CSR_WRITE(RDR, 0); 1549d4a17304SKalle Valo 1550d4a17304SKalle Valo adm8211_set_interval(dev, 100, 10); 1551d4a17304SKalle Valo return 0; 1552d4a17304SKalle Valo 1553d4a17304SKalle Valo fail: 1554d4a17304SKalle Valo return retval; 1555d4a17304SKalle Valo } 1556d4a17304SKalle Valo 1557d4a17304SKalle Valo static void adm8211_stop(struct ieee80211_hw *dev) 1558d4a17304SKalle Valo { 1559d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1560d4a17304SKalle Valo 1561d4a17304SKalle Valo priv->mode = NL80211_IFTYPE_UNSPECIFIED; 1562d4a17304SKalle Valo priv->nar = 0; 1563d4a17304SKalle Valo ADM8211_CSR_WRITE(NAR, 0); 1564d4a17304SKalle Valo ADM8211_CSR_WRITE(IER, 0); 1565d4a17304SKalle Valo ADM8211_CSR_READ(NAR); 1566d4a17304SKalle Valo 1567d4a17304SKalle Valo free_irq(priv->pdev->irq, dev); 1568d4a17304SKalle Valo 1569d4a17304SKalle Valo adm8211_free_rings(dev); 1570d4a17304SKalle Valo } 1571d4a17304SKalle Valo 1572d4a17304SKalle Valo static void adm8211_calc_durations(int *dur, int *plcp, size_t payload_len, int len, 1573d4a17304SKalle Valo int plcp_signal, int short_preamble) 1574d4a17304SKalle Valo { 1575d4a17304SKalle Valo /* Alternative calculation from NetBSD: */ 1576d4a17304SKalle Valo 1577d4a17304SKalle Valo /* IEEE 802.11b durations for DSSS PHY in microseconds */ 1578d4a17304SKalle Valo #define IEEE80211_DUR_DS_LONG_PREAMBLE 144 1579d4a17304SKalle Valo #define IEEE80211_DUR_DS_SHORT_PREAMBLE 72 1580d4a17304SKalle Valo #define IEEE80211_DUR_DS_FAST_PLCPHDR 24 1581d4a17304SKalle Valo #define IEEE80211_DUR_DS_SLOW_PLCPHDR 48 1582d4a17304SKalle Valo #define IEEE80211_DUR_DS_SLOW_ACK 112 1583d4a17304SKalle Valo #define IEEE80211_DUR_DS_FAST_ACK 56 1584d4a17304SKalle Valo #define IEEE80211_DUR_DS_SLOW_CTS 112 1585d4a17304SKalle Valo #define IEEE80211_DUR_DS_FAST_CTS 56 1586d4a17304SKalle Valo #define IEEE80211_DUR_DS_SLOT 20 1587d4a17304SKalle Valo #define IEEE80211_DUR_DS_SIFS 10 1588d4a17304SKalle Valo 1589d4a17304SKalle Valo int remainder; 1590d4a17304SKalle Valo 1591d4a17304SKalle Valo *dur = (80 * (24 + payload_len) + plcp_signal - 1) 1592d4a17304SKalle Valo / plcp_signal; 1593d4a17304SKalle Valo 1594d4a17304SKalle Valo if (plcp_signal <= PLCP_SIGNAL_2M) 1595d4a17304SKalle Valo /* 1-2Mbps WLAN: send ACK/CTS at 1Mbps */ 1596d4a17304SKalle Valo *dur += 3 * (IEEE80211_DUR_DS_SIFS + 1597d4a17304SKalle Valo IEEE80211_DUR_DS_SHORT_PREAMBLE + 1598d4a17304SKalle Valo IEEE80211_DUR_DS_FAST_PLCPHDR) + 1599d4a17304SKalle Valo IEEE80211_DUR_DS_SLOW_CTS + IEEE80211_DUR_DS_SLOW_ACK; 1600d4a17304SKalle Valo else 1601d4a17304SKalle Valo /* 5-11Mbps WLAN: send ACK/CTS at 2Mbps */ 1602d4a17304SKalle Valo *dur += 3 * (IEEE80211_DUR_DS_SIFS + 1603d4a17304SKalle Valo IEEE80211_DUR_DS_SHORT_PREAMBLE + 1604d4a17304SKalle Valo IEEE80211_DUR_DS_FAST_PLCPHDR) + 1605d4a17304SKalle Valo IEEE80211_DUR_DS_FAST_CTS + IEEE80211_DUR_DS_FAST_ACK; 1606d4a17304SKalle Valo 1607d4a17304SKalle Valo /* lengthen duration if long preamble */ 1608d4a17304SKalle Valo if (!short_preamble) 1609d4a17304SKalle Valo *dur += 3 * (IEEE80211_DUR_DS_LONG_PREAMBLE - 1610d4a17304SKalle Valo IEEE80211_DUR_DS_SHORT_PREAMBLE) + 1611d4a17304SKalle Valo 3 * (IEEE80211_DUR_DS_SLOW_PLCPHDR - 1612d4a17304SKalle Valo IEEE80211_DUR_DS_FAST_PLCPHDR); 1613d4a17304SKalle Valo 1614d4a17304SKalle Valo 1615d4a17304SKalle Valo *plcp = (80 * len) / plcp_signal; 1616d4a17304SKalle Valo remainder = (80 * len) % plcp_signal; 1617d4a17304SKalle Valo if (plcp_signal == PLCP_SIGNAL_11M && 1618d4a17304SKalle Valo remainder <= 30 && remainder > 0) 1619d4a17304SKalle Valo *plcp = (*plcp | 0x8000) + 1; 1620d4a17304SKalle Valo else if (remainder) 1621d4a17304SKalle Valo (*plcp)++; 1622d4a17304SKalle Valo } 1623d4a17304SKalle Valo 1624d4a17304SKalle Valo /* Transmit skb w/adm8211_tx_hdr (802.11 header created by hardware) */ 1625d15697deSAlexey Khoroshilov static int adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb, 1626d4a17304SKalle Valo u16 plcp_signal, 1627d4a17304SKalle Valo size_t hdrlen) 1628d4a17304SKalle Valo { 1629d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1630d4a17304SKalle Valo unsigned long flags; 1631d4a17304SKalle Valo dma_addr_t mapping; 1632d4a17304SKalle Valo unsigned int entry; 1633d4a17304SKalle Valo u32 flag; 1634d4a17304SKalle Valo 1635d4a17304SKalle Valo mapping = pci_map_single(priv->pdev, skb->data, skb->len, 1636d4a17304SKalle Valo PCI_DMA_TODEVICE); 1637d15697deSAlexey Khoroshilov if (pci_dma_mapping_error(priv->pdev, mapping)) 1638d15697deSAlexey Khoroshilov return -ENOMEM; 1639d4a17304SKalle Valo 1640d4a17304SKalle Valo spin_lock_irqsave(&priv->lock, flags); 1641d4a17304SKalle Valo 1642d4a17304SKalle Valo if (priv->cur_tx - priv->dirty_tx == priv->tx_ring_size / 2) 1643d4a17304SKalle Valo flag = TDES1_CONTROL_IC | TDES1_CONTROL_LS | TDES1_CONTROL_FS; 1644d4a17304SKalle Valo else 1645d4a17304SKalle Valo flag = TDES1_CONTROL_LS | TDES1_CONTROL_FS; 1646d4a17304SKalle Valo 1647d4a17304SKalle Valo if (priv->cur_tx - priv->dirty_tx == priv->tx_ring_size - 2) 1648d4a17304SKalle Valo ieee80211_stop_queue(dev, 0); 1649d4a17304SKalle Valo 1650d4a17304SKalle Valo entry = priv->cur_tx % priv->tx_ring_size; 1651d4a17304SKalle Valo 1652d4a17304SKalle Valo priv->tx_buffers[entry].skb = skb; 1653d4a17304SKalle Valo priv->tx_buffers[entry].mapping = mapping; 1654d4a17304SKalle Valo priv->tx_buffers[entry].hdrlen = hdrlen; 1655d4a17304SKalle Valo priv->tx_ring[entry].buffer1 = cpu_to_le32(mapping); 1656d4a17304SKalle Valo 1657d4a17304SKalle Valo if (entry == priv->tx_ring_size - 1) 1658d4a17304SKalle Valo flag |= TDES1_CONTROL_TER; 1659d4a17304SKalle Valo priv->tx_ring[entry].length = cpu_to_le32(flag | skb->len); 1660d4a17304SKalle Valo 1661d4a17304SKalle Valo /* Set TX rate (SIGNAL field in PLCP PPDU format) */ 1662d4a17304SKalle Valo flag = TDES0_CONTROL_OWN | (plcp_signal << 20) | 8 /* ? */; 1663d4a17304SKalle Valo priv->tx_ring[entry].status = cpu_to_le32(flag); 1664d4a17304SKalle Valo 1665d4a17304SKalle Valo priv->cur_tx++; 1666d4a17304SKalle Valo 1667d4a17304SKalle Valo spin_unlock_irqrestore(&priv->lock, flags); 1668d4a17304SKalle Valo 1669d4a17304SKalle Valo /* Trigger transmit poll */ 1670d4a17304SKalle Valo ADM8211_CSR_WRITE(TDR, 0); 1671d15697deSAlexey Khoroshilov 1672d15697deSAlexey Khoroshilov return 0; 1673d4a17304SKalle Valo } 1674d4a17304SKalle Valo 1675d4a17304SKalle Valo /* Put adm8211_tx_hdr on skb and transmit */ 1676d4a17304SKalle Valo static void adm8211_tx(struct ieee80211_hw *dev, 1677d4a17304SKalle Valo struct ieee80211_tx_control *control, 1678d4a17304SKalle Valo struct sk_buff *skb) 1679d4a17304SKalle Valo { 1680d4a17304SKalle Valo struct adm8211_tx_hdr *txhdr; 1681d4a17304SKalle Valo size_t payload_len, hdrlen; 1682d4a17304SKalle Valo int plcp, dur, len, plcp_signal, short_preamble; 1683d4a17304SKalle Valo struct ieee80211_hdr *hdr; 1684d4a17304SKalle Valo struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1685d4a17304SKalle Valo struct ieee80211_rate *txrate = ieee80211_get_tx_rate(dev, info); 1686d4a17304SKalle Valo u8 rc_flags; 1687d4a17304SKalle Valo 1688d4a17304SKalle Valo rc_flags = info->control.rates[0].flags; 1689d4a17304SKalle Valo short_preamble = !!(rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE); 1690d4a17304SKalle Valo plcp_signal = txrate->bitrate; 1691d4a17304SKalle Valo 1692d4a17304SKalle Valo hdr = (struct ieee80211_hdr *)skb->data; 1693d4a17304SKalle Valo hdrlen = ieee80211_hdrlen(hdr->frame_control); 1694d4a17304SKalle Valo memcpy(skb->cb, skb->data, hdrlen); 1695d4a17304SKalle Valo hdr = (struct ieee80211_hdr *)skb->cb; 1696d4a17304SKalle Valo skb_pull(skb, hdrlen); 1697d4a17304SKalle Valo payload_len = skb->len; 1698d4a17304SKalle Valo 1699d58ff351SJohannes Berg txhdr = skb_push(skb, sizeof(*txhdr)); 1700d4a17304SKalle Valo memset(txhdr, 0, sizeof(*txhdr)); 1701d4a17304SKalle Valo memcpy(txhdr->da, ieee80211_get_DA(hdr), ETH_ALEN); 1702d4a17304SKalle Valo txhdr->signal = plcp_signal; 1703d4a17304SKalle Valo txhdr->frame_body_size = cpu_to_le16(payload_len); 1704d4a17304SKalle Valo txhdr->frame_control = hdr->frame_control; 1705d4a17304SKalle Valo 1706d4a17304SKalle Valo len = hdrlen + payload_len + FCS_LEN; 1707d4a17304SKalle Valo 1708d4a17304SKalle Valo txhdr->frag = cpu_to_le16(0x0FFF); 1709d4a17304SKalle Valo adm8211_calc_durations(&dur, &plcp, payload_len, 1710d4a17304SKalle Valo len, plcp_signal, short_preamble); 1711d4a17304SKalle Valo txhdr->plcp_frag_head_len = cpu_to_le16(plcp); 1712d4a17304SKalle Valo txhdr->plcp_frag_tail_len = cpu_to_le16(plcp); 1713d4a17304SKalle Valo txhdr->dur_frag_head = cpu_to_le16(dur); 1714d4a17304SKalle Valo txhdr->dur_frag_tail = cpu_to_le16(dur); 1715d4a17304SKalle Valo 1716d4a17304SKalle Valo txhdr->header_control = cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_EXTEND_HEADER); 1717d4a17304SKalle Valo 1718d4a17304SKalle Valo if (short_preamble) 1719d4a17304SKalle Valo txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_SHORT_PREAMBLE); 1720d4a17304SKalle Valo 1721d4a17304SKalle Valo if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) 1722d4a17304SKalle Valo txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS); 1723d4a17304SKalle Valo 1724d4a17304SKalle Valo txhdr->retry_limit = info->control.rates[0].count; 1725d4a17304SKalle Valo 1726d15697deSAlexey Khoroshilov if (adm8211_tx_raw(dev, skb, plcp_signal, hdrlen)) { 1727d15697deSAlexey Khoroshilov /* Drop packet */ 1728d15697deSAlexey Khoroshilov ieee80211_free_txskb(dev, skb); 1729d15697deSAlexey Khoroshilov } 1730d4a17304SKalle Valo } 1731d4a17304SKalle Valo 1732d4a17304SKalle Valo static int adm8211_alloc_rings(struct ieee80211_hw *dev) 1733d4a17304SKalle Valo { 1734d4a17304SKalle Valo struct adm8211_priv *priv = dev->priv; 1735d4a17304SKalle Valo unsigned int ring_size; 1736d4a17304SKalle Valo 1737d4a17304SKalle Valo priv->rx_buffers = kmalloc(sizeof(*priv->rx_buffers) * priv->rx_ring_size + 1738d4a17304SKalle Valo sizeof(*priv->tx_buffers) * priv->tx_ring_size, GFP_KERNEL); 1739d4a17304SKalle Valo if (!priv->rx_buffers) 1740d4a17304SKalle Valo return -ENOMEM; 1741d4a17304SKalle Valo 1742d4a17304SKalle Valo priv->tx_buffers = (void *)priv->rx_buffers + 1743d4a17304SKalle Valo sizeof(*priv->rx_buffers) * priv->rx_ring_size; 1744d4a17304SKalle Valo 1745d4a17304SKalle Valo /* Allocate TX/RX descriptors */ 1746d4a17304SKalle Valo ring_size = sizeof(struct adm8211_desc) * priv->rx_ring_size + 1747d4a17304SKalle Valo sizeof(struct adm8211_desc) * priv->tx_ring_size; 1748d4a17304SKalle Valo priv->rx_ring = pci_alloc_consistent(priv->pdev, ring_size, 1749d4a17304SKalle Valo &priv->rx_ring_dma); 1750d4a17304SKalle Valo 1751d4a17304SKalle Valo if (!priv->rx_ring) { 1752d4a17304SKalle Valo kfree(priv->rx_buffers); 1753d4a17304SKalle Valo priv->rx_buffers = NULL; 1754d4a17304SKalle Valo priv->tx_buffers = NULL; 1755d4a17304SKalle Valo return -ENOMEM; 1756d4a17304SKalle Valo } 1757d4a17304SKalle Valo 1758d4a17304SKalle Valo priv->tx_ring = priv->rx_ring + priv->rx_ring_size; 1759d4a17304SKalle Valo priv->tx_ring_dma = priv->rx_ring_dma + 1760d4a17304SKalle Valo sizeof(struct adm8211_desc) * priv->rx_ring_size; 1761d4a17304SKalle Valo 1762d4a17304SKalle Valo return 0; 1763d4a17304SKalle Valo } 1764d4a17304SKalle Valo 1765d4a17304SKalle Valo static const struct ieee80211_ops adm8211_ops = { 1766d4a17304SKalle Valo .tx = adm8211_tx, 1767d4a17304SKalle Valo .start = adm8211_start, 1768d4a17304SKalle Valo .stop = adm8211_stop, 1769d4a17304SKalle Valo .add_interface = adm8211_add_interface, 1770d4a17304SKalle Valo .remove_interface = adm8211_remove_interface, 1771d4a17304SKalle Valo .config = adm8211_config, 1772d4a17304SKalle Valo .bss_info_changed = adm8211_bss_info_changed, 1773d4a17304SKalle Valo .prepare_multicast = adm8211_prepare_multicast, 1774d4a17304SKalle Valo .configure_filter = adm8211_configure_filter, 1775d4a17304SKalle Valo .get_stats = adm8211_get_stats, 1776d4a17304SKalle Valo .get_tsf = adm8211_get_tsft 1777d4a17304SKalle Valo }; 1778d4a17304SKalle Valo 1779d4a17304SKalle Valo static int adm8211_probe(struct pci_dev *pdev, 1780d4a17304SKalle Valo const struct pci_device_id *id) 1781d4a17304SKalle Valo { 1782d4a17304SKalle Valo struct ieee80211_hw *dev; 1783d4a17304SKalle Valo struct adm8211_priv *priv; 1784d4a17304SKalle Valo unsigned long mem_addr, mem_len; 1785d4a17304SKalle Valo unsigned int io_addr, io_len; 1786d4a17304SKalle Valo int err; 1787d4a17304SKalle Valo u32 reg; 1788d4a17304SKalle Valo u8 perm_addr[ETH_ALEN]; 1789d4a17304SKalle Valo 1790d4a17304SKalle Valo err = pci_enable_device(pdev); 1791d4a17304SKalle Valo if (err) { 1792d4a17304SKalle Valo printk(KERN_ERR "%s (adm8211): Cannot enable new PCI device\n", 1793d4a17304SKalle Valo pci_name(pdev)); 1794d4a17304SKalle Valo return err; 1795d4a17304SKalle Valo } 1796d4a17304SKalle Valo 1797d4a17304SKalle Valo io_addr = pci_resource_start(pdev, 0); 1798d4a17304SKalle Valo io_len = pci_resource_len(pdev, 0); 1799d4a17304SKalle Valo mem_addr = pci_resource_start(pdev, 1); 1800d4a17304SKalle Valo mem_len = pci_resource_len(pdev, 1); 1801d4a17304SKalle Valo if (io_len < 256 || mem_len < 1024) { 1802d4a17304SKalle Valo printk(KERN_ERR "%s (adm8211): Too short PCI resources\n", 1803d4a17304SKalle Valo pci_name(pdev)); 1804d4a17304SKalle Valo goto err_disable_pdev; 1805d4a17304SKalle Valo } 1806d4a17304SKalle Valo 1807d4a17304SKalle Valo 1808d4a17304SKalle Valo /* check signature */ 1809d4a17304SKalle Valo pci_read_config_dword(pdev, 0x80 /* CR32 */, ®); 1810d4a17304SKalle Valo if (reg != ADM8211_SIG1 && reg != ADM8211_SIG2) { 1811d4a17304SKalle Valo printk(KERN_ERR "%s (adm8211): Invalid signature (0x%x)\n", 1812d4a17304SKalle Valo pci_name(pdev), reg); 1813d4a17304SKalle Valo goto err_disable_pdev; 1814d4a17304SKalle Valo } 1815d4a17304SKalle Valo 1816d4a17304SKalle Valo err = pci_request_regions(pdev, "adm8211"); 1817d4a17304SKalle Valo if (err) { 1818d4a17304SKalle Valo printk(KERN_ERR "%s (adm8211): Cannot obtain PCI resources\n", 1819d4a17304SKalle Valo pci_name(pdev)); 1820d4a17304SKalle Valo return err; /* someone else grabbed it? don't disable it */ 1821d4a17304SKalle Valo } 1822d4a17304SKalle Valo 1823d4a17304SKalle Valo if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) || 1824d4a17304SKalle Valo pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { 1825d4a17304SKalle Valo printk(KERN_ERR "%s (adm8211): No suitable DMA available\n", 1826d4a17304SKalle Valo pci_name(pdev)); 1827d4a17304SKalle Valo goto err_free_reg; 1828d4a17304SKalle Valo } 1829d4a17304SKalle Valo 1830d4a17304SKalle Valo pci_set_master(pdev); 1831d4a17304SKalle Valo 1832d4a17304SKalle Valo dev = ieee80211_alloc_hw(sizeof(*priv), &adm8211_ops); 1833d4a17304SKalle Valo if (!dev) { 1834d4a17304SKalle Valo printk(KERN_ERR "%s (adm8211): ieee80211 alloc failed\n", 1835d4a17304SKalle Valo pci_name(pdev)); 1836d4a17304SKalle Valo err = -ENOMEM; 1837d4a17304SKalle Valo goto err_free_reg; 1838d4a17304SKalle Valo } 1839d4a17304SKalle Valo priv = dev->priv; 1840d4a17304SKalle Valo priv->pdev = pdev; 1841d4a17304SKalle Valo 1842d4a17304SKalle Valo spin_lock_init(&priv->lock); 1843d4a17304SKalle Valo 1844d4a17304SKalle Valo SET_IEEE80211_DEV(dev, &pdev->dev); 1845d4a17304SKalle Valo 1846d4a17304SKalle Valo pci_set_drvdata(pdev, dev); 1847d4a17304SKalle Valo 1848d4a17304SKalle Valo priv->map = pci_iomap(pdev, 1, mem_len); 1849d4a17304SKalle Valo if (!priv->map) 1850d4a17304SKalle Valo priv->map = pci_iomap(pdev, 0, io_len); 1851d4a17304SKalle Valo 1852d4a17304SKalle Valo if (!priv->map) { 1853d4a17304SKalle Valo printk(KERN_ERR "%s (adm8211): Cannot map device memory\n", 1854d4a17304SKalle Valo pci_name(pdev)); 1855d4a17304SKalle Valo err = -ENOMEM; 1856d4a17304SKalle Valo goto err_free_dev; 1857d4a17304SKalle Valo } 1858d4a17304SKalle Valo 1859d4a17304SKalle Valo priv->rx_ring_size = rx_ring_size; 1860d4a17304SKalle Valo priv->tx_ring_size = tx_ring_size; 1861d4a17304SKalle Valo 1862c705a6b3SDan Carpenter err = adm8211_alloc_rings(dev); 1863c705a6b3SDan Carpenter if (err) { 1864d4a17304SKalle Valo printk(KERN_ERR "%s (adm8211): Cannot allocate TX/RX ring\n", 1865d4a17304SKalle Valo pci_name(pdev)); 1866d4a17304SKalle Valo goto err_iounmap; 1867d4a17304SKalle Valo } 1868d4a17304SKalle Valo 1869d4a17304SKalle Valo *(__le32 *)perm_addr = cpu_to_le32(ADM8211_CSR_READ(PAR0)); 1870d4a17304SKalle Valo *(__le16 *)&perm_addr[4] = 1871d4a17304SKalle Valo cpu_to_le16(ADM8211_CSR_READ(PAR1) & 0xFFFF); 1872d4a17304SKalle Valo 1873d4a17304SKalle Valo if (!is_valid_ether_addr(perm_addr)) { 1874d4a17304SKalle Valo printk(KERN_WARNING "%s (adm8211): Invalid hwaddr in EEPROM!\n", 1875d4a17304SKalle Valo pci_name(pdev)); 1876d4a17304SKalle Valo eth_random_addr(perm_addr); 1877d4a17304SKalle Valo } 1878d4a17304SKalle Valo SET_IEEE80211_PERM_ADDR(dev, perm_addr); 1879d4a17304SKalle Valo 1880d4a17304SKalle Valo dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr); 1881d4a17304SKalle Valo /* dev->flags = RX_INCLUDES_FCS in promisc mode */ 1882d4a17304SKalle Valo ieee80211_hw_set(dev, SIGNAL_UNSPEC); 1883d4a17304SKalle Valo dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); 1884d4a17304SKalle Valo 1885d4a17304SKalle Valo dev->max_signal = 100; /* FIXME: find better value */ 1886d4a17304SKalle Valo 1887d4a17304SKalle Valo dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */ 1888d4a17304SKalle Valo 1889d4a17304SKalle Valo priv->retry_limit = 3; 1890d4a17304SKalle Valo priv->ant_power = 0x40; 1891d4a17304SKalle Valo priv->tx_power = 0x40; 1892d4a17304SKalle Valo priv->lpf_cutoff = 0xFF; 1893d4a17304SKalle Valo priv->lnags_threshold = 0xFF; 1894d4a17304SKalle Valo priv->mode = NL80211_IFTYPE_UNSPECIFIED; 1895d4a17304SKalle Valo 1896d4a17304SKalle Valo /* Power-on issue. EEPROM won't read correctly without */ 1897d4a17304SKalle Valo if (pdev->revision >= ADM8211_REV_BA) { 1898d4a17304SKalle Valo ADM8211_CSR_WRITE(FRCTL, 0); 1899d4a17304SKalle Valo ADM8211_CSR_READ(FRCTL); 1900d4a17304SKalle Valo ADM8211_CSR_WRITE(FRCTL, 1); 1901d4a17304SKalle Valo ADM8211_CSR_READ(FRCTL); 1902d4a17304SKalle Valo msleep(100); 1903d4a17304SKalle Valo } 1904d4a17304SKalle Valo 1905d4a17304SKalle Valo err = adm8211_read_eeprom(dev); 1906d4a17304SKalle Valo if (err) { 1907d4a17304SKalle Valo printk(KERN_ERR "%s (adm8211): Can't alloc eeprom buffer\n", 1908d4a17304SKalle Valo pci_name(pdev)); 1909d4a17304SKalle Valo goto err_free_desc; 1910d4a17304SKalle Valo } 1911d4a17304SKalle Valo 1912d4a17304SKalle Valo priv->channel = 1; 1913d4a17304SKalle Valo 191457fbcce3SJohannes Berg dev->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; 1915d4a17304SKalle Valo 1916ae44b502SAndrew Zaborowski wiphy_ext_feature_set(dev->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); 1917ae44b502SAndrew Zaborowski 1918d4a17304SKalle Valo err = ieee80211_register_hw(dev); 1919d4a17304SKalle Valo if (err) { 1920d4a17304SKalle Valo printk(KERN_ERR "%s (adm8211): Cannot register device\n", 1921d4a17304SKalle Valo pci_name(pdev)); 1922d4a17304SKalle Valo goto err_free_eeprom; 1923d4a17304SKalle Valo } 1924d4a17304SKalle Valo 1925d4a17304SKalle Valo wiphy_info(dev->wiphy, "hwaddr %pM, Rev 0x%02x\n", 1926d4a17304SKalle Valo dev->wiphy->perm_addr, pdev->revision); 1927d4a17304SKalle Valo 1928d4a17304SKalle Valo return 0; 1929d4a17304SKalle Valo 1930d4a17304SKalle Valo err_free_eeprom: 1931d4a17304SKalle Valo kfree(priv->eeprom); 1932d4a17304SKalle Valo 1933d4a17304SKalle Valo err_free_desc: 1934d4a17304SKalle Valo pci_free_consistent(pdev, 1935d4a17304SKalle Valo sizeof(struct adm8211_desc) * priv->rx_ring_size + 1936d4a17304SKalle Valo sizeof(struct adm8211_desc) * priv->tx_ring_size, 1937d4a17304SKalle Valo priv->rx_ring, priv->rx_ring_dma); 1938d4a17304SKalle Valo kfree(priv->rx_buffers); 1939d4a17304SKalle Valo 1940d4a17304SKalle Valo err_iounmap: 1941d4a17304SKalle Valo pci_iounmap(pdev, priv->map); 1942d4a17304SKalle Valo 1943d4a17304SKalle Valo err_free_dev: 1944d4a17304SKalle Valo ieee80211_free_hw(dev); 1945d4a17304SKalle Valo 1946d4a17304SKalle Valo err_free_reg: 1947d4a17304SKalle Valo pci_release_regions(pdev); 1948d4a17304SKalle Valo 1949d4a17304SKalle Valo err_disable_pdev: 1950d4a17304SKalle Valo pci_disable_device(pdev); 1951d4a17304SKalle Valo return err; 1952d4a17304SKalle Valo } 1953d4a17304SKalle Valo 1954d4a17304SKalle Valo 1955d4a17304SKalle Valo static void adm8211_remove(struct pci_dev *pdev) 1956d4a17304SKalle Valo { 1957d4a17304SKalle Valo struct ieee80211_hw *dev = pci_get_drvdata(pdev); 1958d4a17304SKalle Valo struct adm8211_priv *priv; 1959d4a17304SKalle Valo 1960d4a17304SKalle Valo if (!dev) 1961d4a17304SKalle Valo return; 1962d4a17304SKalle Valo 1963d4a17304SKalle Valo ieee80211_unregister_hw(dev); 1964d4a17304SKalle Valo 1965d4a17304SKalle Valo priv = dev->priv; 1966d4a17304SKalle Valo 1967d4a17304SKalle Valo pci_free_consistent(pdev, 1968d4a17304SKalle Valo sizeof(struct adm8211_desc) * priv->rx_ring_size + 1969d4a17304SKalle Valo sizeof(struct adm8211_desc) * priv->tx_ring_size, 1970d4a17304SKalle Valo priv->rx_ring, priv->rx_ring_dma); 1971d4a17304SKalle Valo 1972d4a17304SKalle Valo kfree(priv->rx_buffers); 1973d4a17304SKalle Valo kfree(priv->eeprom); 1974d4a17304SKalle Valo pci_iounmap(pdev, priv->map); 1975d4a17304SKalle Valo pci_release_regions(pdev); 1976d4a17304SKalle Valo pci_disable_device(pdev); 1977d4a17304SKalle Valo ieee80211_free_hw(dev); 1978d4a17304SKalle Valo } 1979d4a17304SKalle Valo 1980d4a17304SKalle Valo 1981d4a17304SKalle Valo #ifdef CONFIG_PM 1982d4a17304SKalle Valo static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state) 1983d4a17304SKalle Valo { 1984d4a17304SKalle Valo pci_save_state(pdev); 1985d4a17304SKalle Valo pci_set_power_state(pdev, pci_choose_state(pdev, state)); 1986d4a17304SKalle Valo return 0; 1987d4a17304SKalle Valo } 1988d4a17304SKalle Valo 1989d4a17304SKalle Valo static int adm8211_resume(struct pci_dev *pdev) 1990d4a17304SKalle Valo { 1991d4a17304SKalle Valo pci_set_power_state(pdev, PCI_D0); 1992d4a17304SKalle Valo pci_restore_state(pdev); 1993d4a17304SKalle Valo return 0; 1994d4a17304SKalle Valo } 1995d4a17304SKalle Valo #endif /* CONFIG_PM */ 1996d4a17304SKalle Valo 1997d4a17304SKalle Valo 1998d4a17304SKalle Valo MODULE_DEVICE_TABLE(pci, adm8211_pci_id_table); 1999d4a17304SKalle Valo 2000d4a17304SKalle Valo /* TODO: implement enable_wake */ 2001d4a17304SKalle Valo static struct pci_driver adm8211_driver = { 2002d4a17304SKalle Valo .name = "adm8211", 2003d4a17304SKalle Valo .id_table = adm8211_pci_id_table, 2004d4a17304SKalle Valo .probe = adm8211_probe, 2005d4a17304SKalle Valo .remove = adm8211_remove, 2006d4a17304SKalle Valo #ifdef CONFIG_PM 2007d4a17304SKalle Valo .suspend = adm8211_suspend, 2008d4a17304SKalle Valo .resume = adm8211_resume, 2009d4a17304SKalle Valo #endif /* CONFIG_PM */ 2010d4a17304SKalle Valo }; 2011d4a17304SKalle Valo 2012d4a17304SKalle Valo module_pci_driver(adm8211_driver); 2013