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