2 * Airgo MIMO wireless driver
4 * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
6 * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
7 * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
14 #include <linux/init.h>
15 #include <linux/etherdevice.h>
16 #include <linux/pci.h>
17 #include <linux/delay.h>
25 u8
read_from_eeprom(struct agnx_priv
*priv
, u16 address
)
27 void __iomem
*ctl
= priv
->ctl
;
28 struct agnx_eeprom cmd
;
31 memset(&cmd
, 0, sizeof(cmd
));
32 cmd
.cmd
= EEPROM_CMD_READ
<< AGNX_EEPROM_COMMAND_SHIFT
;
33 cmd
.address
= address
;
34 /* Verify that the Status bit is clear */
35 /* Read Command and Address are written to the Serial Interface */
36 iowrite32(*(__le32
*)&cmd
, ctl
+ AGNX_CIR_SERIALITF
);
37 /* Wait for the Status bit to clear again */
40 reg
= ioread32(ctl
+ AGNX_CIR_SERIALITF
);
42 cmd
= *(struct agnx_eeprom
*)®
;
47 static int card_full_reset(struct agnx_priv
*priv
)
49 void __iomem
*ctl
= priv
->ctl
;
53 reg
= agnx_read32(ctl
, AGNX_CIR_BLKCTL
);
54 agnx_write32(ctl
, AGNX_CIR_BLKCTL
, 0x80);
55 reg
= agnx_read32(ctl
, AGNX_CIR_BLKCTL
);
59 inline void enable_power_saving(struct agnx_priv
*priv
)
61 void __iomem
*ctl
= priv
->ctl
;
64 reg
= agnx_read32(ctl
, AGNX_PM_PMCTL
);
66 agnx_write32(ctl
, AGNX_PM_PMCTL
, reg
);
69 inline void disable_power_saving(struct agnx_priv
*priv
)
71 void __iomem
*ctl
= priv
->ctl
;
74 reg
= agnx_read32(ctl
, AGNX_PM_PMCTL
);
76 agnx_write32(ctl
, AGNX_PM_PMCTL
, reg
);
80 void disable_receiver(struct agnx_priv
*priv
)
82 void __iomem
*ctl
= priv
->ctl
;
85 /* FIXME Disable the receiver */
86 agnx_write32(ctl
, AGNX_GCR_DISCOVMOD
, 0x0);
87 /* Set gain control reset */
88 agnx_write32(ctl
, AGNX_GCR_RSTGCTL
, 0x1);
89 /* Reset gain control reset */
90 agnx_write32(ctl
, AGNX_GCR_RSTGCTL
, 0x0);
94 /* Fixme this shoule be disable RX, above is enable RX */
95 void enable_receiver(struct agnx_priv
*priv
)
97 void __iomem
*ctl
= priv
->ctl
;
100 /* Set adaptive gain control discovery mode */
101 agnx_write32(ctl
, AGNX_GCR_DISCOVMOD
, 0x3);
102 /* Set gain control reset */
103 agnx_write32(ctl
, AGNX_GCR_RSTGCTL
, 0x1);
104 /* Clear gain control reset */
105 agnx_write32(ctl
, AGNX_GCR_RSTGCTL
, 0x0);
108 static void mac_address_set(struct agnx_priv
*priv
)
110 void __iomem
*ctl
= priv
->ctl
;
111 u8
*mac_addr
= priv
->mac_addr
;
115 reg
= (mac_addr
[0] << 24) | (mac_addr
[1] << 16) | mac_addr
[2] << 8 | mac_addr
[3];
116 iowrite32(reg
, ctl
+ AGNX_RXM_MACHI
);
117 reg
= (mac_addr
[4] << 8) | mac_addr
[5];
118 iowrite32(reg
, ctl
+ AGNX_RXM_MACLO
);
121 static void receiver_bssid_set(struct agnx_priv
*priv
, const u8
*bssid
)
123 void __iomem
*ctl
= priv
->ctl
;
126 disable_receiver(priv
);
128 reg
= bssid
[0] << 24 | (bssid
[1] << 16) | (bssid
[2] << 8) | bssid
[3];
129 iowrite32(reg
, ctl
+ AGNX_RXM_BSSIDHI
);
130 reg
= (bssid
[4] << 8) | bssid
[5];
131 iowrite32(reg
, ctl
+ AGNX_RXM_BSSIDLO
);
133 /* Enable the receiver */
134 enable_receiver(priv
);
137 /* agnx_write32(ctl, AGNX_TXM_TSFLO, 0x0); */
138 /* agnx_write32(ctl, AGNX_TXM_TSFHI, 0x0); */
140 agnx_write32(ctl
, AGNX_TXM_TBTTLO
, 0x0);
141 agnx_write32(ctl
, AGNX_TXM_TBTTHI
, 0x0);
142 disable_receiver(priv
);
143 } /* receiver_bssid_set */
145 static void band_management_init(struct agnx_priv
*priv
)
147 void __iomem
*ctl
= priv
->ctl
;
148 void __iomem
*data
= priv
->data
;
153 agnx_write32(ctl
, AGNX_BM_TXWADDR
, AGNX_PDU_TX_WQ
);
154 agnx_write32(ctl
, AGNX_CIR_ADDRWIN
, 0x0);
155 memset_io(data
+ AGNX_PDUPOOL
, 0x0, AGNX_PDUPOOL_SIZE
);
156 agnx_write32(ctl
, AGNX_BM_BMCTL
, 0x200);
158 agnx_write32(ctl
, AGNX_BM_CIPDUWCNT
, 0x40);
159 agnx_write32(ctl
, AGNX_BM_SPPDUWCNT
, 0x2);
160 agnx_write32(ctl
, AGNX_BM_RFPPDUWCNT
, 0x0);
161 agnx_write32(ctl
, AGNX_BM_RHPPDUWCNT
, 0x22);
163 /* FIXME Initialize the Free Pool Linked List */
164 /* 1. Write the Address of the Next Node ((0x41800 + node*size)/size)
165 to the first word of each node. */
166 for (i
= 0; i
< PDU_FREE_CNT
; i
++) {
167 iowrite32((AGNX_PDU_FREE
+ (i
+1)*PDU_SIZE
)/PDU_SIZE
,
168 data
+ AGNX_PDU_FREE
+ (PDU_SIZE
* i
));
169 /* The last node should be set to 0x0 */
170 if ((i
+ 1) == PDU_FREE_CNT
)
171 memset_io(data
+ AGNX_PDU_FREE
+ (PDU_SIZE
* i
),
175 /* Head is First Pool address (0x41800) / size (0x80) */
176 agnx_write32(ctl
, AGNX_BM_FPLHP
, AGNX_PDU_FREE
/PDU_SIZE
);
177 /* Tail is Last Pool Address (0x47f80) / size (0x80) */
178 agnx_write32(ctl
, AGNX_BM_FPLTP
, 0x47f80/PDU_SIZE
);
179 /* Count is Number of Nodes in the Pool (0xd0) */
180 agnx_write32(ctl
, AGNX_BM_FPCNT
, PDU_FREE_CNT
);
182 /* Start all workqueue */
183 agnx_write32(ctl
, AGNX_BM_CIWQCTL
, 0x80000);
184 agnx_write32(ctl
, AGNX_BM_CPULWCTL
, 0x80000);
185 agnx_write32(ctl
, AGNX_BM_CPUHWCTL
, 0x80000);
186 agnx_write32(ctl
, AGNX_BM_CPUTXWCTL
, 0x80000);
187 agnx_write32(ctl
, AGNX_BM_CPURXWCTL
, 0x80000);
188 agnx_write32(ctl
, AGNX_BM_SPRXWCTL
, 0x80000);
189 agnx_write32(ctl
, AGNX_BM_SPTXWCTL
, 0x80000);
190 agnx_write32(ctl
, AGNX_BM_RFPWCTL
, 0x80000);
192 /* Enable the Band Management */
193 reg
= agnx_read32(ctl
, AGNX_BM_BMCTL
);
195 agnx_write32(ctl
, AGNX_BM_BMCTL
, reg
);
196 } /* band_managment_init */
199 static void system_itf_init(struct agnx_priv
*priv
)
201 void __iomem
*ctl
= priv
->ctl
;
205 agnx_write32(ctl
, AGNX_SYSITF_GPIOUT
, 0x0);
206 agnx_write32(ctl
, AGNX_PM_TESTPHY
, 0x11e143a);
208 if (priv
->revid
== 0) {
209 reg
= agnx_read32(ctl
, AGNX_SYSITF_SYSMODE
);
211 agnx_write32(ctl
, AGNX_SYSITF_SYSMODE
, reg
);
213 /* ??? What is that means? it should difference for differice type
215 agnx_write32(ctl
, AGNX_CIR_SERIALITF
, 0xfff81006);
217 agnx_write32(ctl
, AGNX_SYSITF_GPIOIN
, 0x1f0000);
218 agnx_write32(ctl
, AGNX_SYSITF_GPIOUT
, 0x5);
219 reg
= agnx_read32(ctl
, AGNX_SYSITF_GPIOIN
);
222 static void encryption_init(struct agnx_priv
*priv
)
224 void __iomem
*ctl
= priv
->ctl
;
227 agnx_write32(ctl
, AGNX_ENCRY_WEPKEY0
, 0x0);
228 agnx_write32(ctl
, AGNX_ENCRY_WEPKEY1
, 0x0);
229 agnx_write32(ctl
, AGNX_ENCRY_WEPKEY2
, 0x0);
230 agnx_write32(ctl
, AGNX_ENCRY_WEPKEY3
, 0x0);
231 agnx_write32(ctl
, AGNX_ENCRY_CCMRECTL
, 0x8);
234 static void tx_management_init(struct agnx_priv
*priv
)
236 void __iomem
*ctl
= priv
->ctl
;
237 void __iomem
*data
= priv
->data
;
241 /* Fill out the ComputationalEngineLookupTable
242 * starting at memory #2 offset 0x800
244 tx_engine_lookup_tbl_init(priv
);
245 memset_io(data
+ 0x1000, 0, 0xfe0);
246 /* Enable Transmission Management Functions */
247 agnx_write32(ctl
, AGNX_TXM_ETMF
, 0x3ff);
248 /* Write 0x3f to Transmission Template */
249 agnx_write32(ctl
, AGNX_TXM_TXTEMP
, 0x3f);
251 if (priv
->revid
>= 2)
252 agnx_write32(ctl
, AGNX_TXM_SIFSPIFS
, 0x1e140a0b);
254 agnx_write32(ctl
, AGNX_TXM_SIFSPIFS
, 0x1e190a0b);
256 reg
= agnx_read32(ctl
, AGNX_TXM_TIFSEIFS
);
259 agnx_write32(ctl
, AGNX_TXM_TIFSEIFS
, reg
);
260 reg
= agnx_read32(ctl
, AGNX_TXM_TIFSEIFS
);
263 agnx_write32(ctl
, AGNX_TXM_TIFSEIFS
, reg
);
265 agnx_write32(ctl
, AGNX_TXM_CTL
, 0x40000);
267 reg
= agnx_read32(ctl
, AGNX_TXM_TIFSEIFS
);
270 agnx_write32(ctl
, AGNX_TXM_TIFSEIFS
, reg
);
271 reg
= agnx_read32(ctl
, AGNX_TXM_PROBDELAY
);
273 agnx_write32(ctl
, AGNX_TXM_PROBDELAY
, reg
);
274 reg
= agnx_read32(ctl
, AGNX_TXM_TIFSEIFS
);
277 agnx_write32(ctl
, AGNX_TXM_TIFSEIFS
, reg
);
278 reg
= agnx_read32(ctl
, AGNX_TXM_PROBDELAY
);
281 agnx_write32(ctl
, AGNX_TXM_PROBDELAY
, reg
);
283 /* # Set DIF 0-1,2-3,4-5,6-7 to defaults */
284 agnx_write32(ctl
, AGNX_TXM_DIF01
, 0x321d321d);
285 agnx_write32(ctl
, AGNX_TXM_DIF23
, 0x321d321d);
286 agnx_write32(ctl
, AGNX_TXM_DIF45
, 0x321d321d);
287 agnx_write32(ctl
, AGNX_TXM_DIF67
, 0x321d321d);
289 /* Max Ack timeout limit */
290 agnx_write32(ctl
, AGNX_TXM_MAXACKTIM
, 0x1e19);
291 /* Max RX Data Timeout count, */
292 reg
= agnx_read32(ctl
, AGNX_TXM_MAXRXTIME
);
295 agnx_write32(ctl
, AGNX_TXM_MAXRXTIME
, reg
);
297 /* CF poll RX Timeout count */
298 reg
= agnx_read32(ctl
, AGNX_TXM_CFPOLLRXTIM
);
301 agnx_write32(ctl
, AGNX_TXM_CFPOLLRXTIM
, reg
);
303 /* Max Timeout Exceeded count, */
304 reg
= agnx_read32(ctl
, AGNX_TXM_MAXTIMOUT
);
307 agnx_write32(ctl
, AGNX_TXM_MAXTIMOUT
, reg
);
309 /* CF ack timeout limit for 11b */
310 reg
= agnx_read32(ctl
, AGNX_TXM_CFACKT11B
);
313 agnx_write32(ctl
, AGNX_TXM_CFACKT11B
, reg
);
315 /* Max CF Poll Timeout Count */
316 reg
= agnx_read32(ctl
, AGNX_TXM_CFPOLLRXTIM
);
319 agnx_write32(ctl
, AGNX_TXM_CFPOLLRXTIM
, reg
);
320 /* CF Poll RX Timeout Count */
321 reg
= agnx_read32(ctl
, AGNX_TXM_CFPOLLRXTIM
);
324 agnx_write32(ctl
, AGNX_TXM_CFPOLLRXTIM
, reg
);
326 /* # write default to */
327 /* 1. Schedule Empty Count */
328 agnx_write32(ctl
, AGNX_TXM_SCHEMPCNT
, 0x5);
329 /* 2. CFP Period Count */
330 agnx_write32(ctl
, AGNX_TXM_CFPERCNT
, 0x1);
332 agnx_write32(ctl
, AGNX_TXM_CFPMDV
, 0x10000);
335 reg
= agnx_read32(ctl
, AGNX_TXM_PROBDELAY
);
338 agnx_write32(ctl
, AGNX_TXM_PROBDELAY
, reg
);
340 /* Max CCA count Slot */
341 reg
= agnx_read32(ctl
, AGNX_TXM_MAXCCACNTSLOT
);
344 agnx_write32(ctl
, AGNX_TXM_MAXCCACNTSLOT
, reg
);
346 /* Slot limit/1 msec Limit */
347 reg
= agnx_read32(ctl
, AGNX_TXM_SLOTLIMIT
);
350 agnx_write32(ctl
, AGNX_TXM_SLOTLIMIT
, reg
);
352 /* # Set CW #(0-7) to default */
353 agnx_write32(ctl
, AGNX_TXM_CW0
, 0xff0007);
354 agnx_write32(ctl
, AGNX_TXM_CW1
, 0xff0007);
355 agnx_write32(ctl
, AGNX_TXM_CW2
, 0xff0007);
356 agnx_write32(ctl
, AGNX_TXM_CW3
, 0xff0007);
357 agnx_write32(ctl
, AGNX_TXM_CW4
, 0xff0007);
358 agnx_write32(ctl
, AGNX_TXM_CW5
, 0xff0007);
359 agnx_write32(ctl
, AGNX_TXM_CW6
, 0xff0007);
360 agnx_write32(ctl
, AGNX_TXM_CW7
, 0xff0007);
362 /* # Set Short/Long limit #(0-7) to default */
363 agnx_write32(ctl
, AGNX_TXM_SLBEALIM0
, 0xa000a);
364 agnx_write32(ctl
, AGNX_TXM_SLBEALIM1
, 0xa000a);
365 agnx_write32(ctl
, AGNX_TXM_SLBEALIM2
, 0xa000a);
366 agnx_write32(ctl
, AGNX_TXM_SLBEALIM3
, 0xa000a);
367 agnx_write32(ctl
, AGNX_TXM_SLBEALIM4
, 0xa000a);
368 agnx_write32(ctl
, AGNX_TXM_SLBEALIM5
, 0xa000a);
369 agnx_write32(ctl
, AGNX_TXM_SLBEALIM6
, 0xa000a);
370 agnx_write32(ctl
, AGNX_TXM_SLBEALIM7
, 0xa000a);
372 reg
= agnx_read32(ctl
, AGNX_TXM_CTL
);
374 agnx_write32(ctl
, AGNX_TXM_CTL
, reg
);
375 /* Wait for bit 0 in Control Reg to clear */
377 reg
= agnx_read32(ctl
, AGNX_TXM_CTL
);
378 /* Or 0x18000 to Control reg */
379 reg
= agnx_read32(ctl
, AGNX_TXM_CTL
);
381 agnx_write32(ctl
, AGNX_TXM_CTL
, reg
);
382 /* Wait for bit 0 in Control Reg to clear */
384 reg
= agnx_read32(ctl
, AGNX_TXM_CTL
);
386 /* Set Listen Interval Count to default */
387 agnx_write32(ctl
, AGNX_TXM_LISINTERCNT
, 0x1);
388 /* Set DTIM period count to default */
389 agnx_write32(ctl
, AGNX_TXM_DTIMPERICNT
, 0x2000);
390 } /* tx_management_init */
392 static void rx_management_init(struct agnx_priv
*priv
)
394 void __iomem
*ctl
= priv
->ctl
;
397 /* Initialize the Routing Table */
398 routing_table_init(priv
);
400 if (priv
->revid
>= 3) {
401 agnx_write32(ctl
, 0x2074, 0x1f171710);
402 agnx_write32(ctl
, 0x2078, 0x10100d0d);
403 agnx_write32(ctl
, 0x207c, 0x11111010);
405 agnx_write32(ctl
, AGNX_RXM_DELAY11
, 0x0);
407 agnx_write32(ctl
, AGNX_RXM_REQRATE
, 0x8195e00);
411 static void agnx_timer_init(struct agnx_priv
*priv
)
413 void __iomem
*ctl
= priv
->ctl
;
416 /* /\* Write 0x249f00 (tick duration?) to Timer 1 *\/ */
417 /* agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x249f00); */
418 /* /\* Write 0xe2 to Timer 1 Control *\/ */
419 /* agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0xe2); */
421 /* Write 0x249f00 (tick duration?) to Timer 1 */
422 agnx_write32(ctl
, AGNX_TIMCTL_TIMER1
, 0x0);
423 /* Write 0xe2 to Timer 1 Control */
424 agnx_write32(ctl
, AGNX_TIMCTL_TIM1CTL
, 0x0);
426 iowrite32(0xFFFFFFFF, priv
->ctl
+ AGNX_TXM_BEACON_CTL
);
429 static void power_manage_init(struct agnx_priv
*priv
)
431 void __iomem
*ctl
= priv
->ctl
;
435 agnx_write32(ctl
, AGNX_PM_MACMSW
, 0x1f);
436 agnx_write32(ctl
, AGNX_PM_RFCTL
, 0x1f);
438 reg
= agnx_read32(ctl
, AGNX_PM_PMCTL
);
441 agnx_write32(ctl
, AGNX_PM_PMCTL
, reg
);
443 if (priv
->revid
>= 3) {
444 reg
= agnx_read32(ctl
, AGNX_PM_SOFTRST
);
446 agnx_write32(ctl
, AGNX_PM_SOFTRST
, reg
);
448 } /* power_manage_init */
451 static void gain_ctlcnt_init(struct agnx_priv
*priv
)
453 void __iomem
*ctl
= priv
->ctl
;
457 agnx_write32(ctl
, AGNX_GCR_TRACNT5
, 0x119);
458 agnx_write32(ctl
, AGNX_GCR_TRACNT6
, 0x118);
459 agnx_write32(ctl
, AGNX_GCR_TRACNT7
, 0x117);
461 reg
= agnx_read32(ctl
, AGNX_PM_PMCTL
);
463 agnx_write32(ctl
, AGNX_PM_PMCTL
, reg
);
465 reg
= agnx_read32(ctl
, AGNX_PM_PMCTL
);
467 agnx_write32(ctl
, AGNX_PM_PMCTL
, reg
);
469 agnx_write32(ctl
, AGNX_CIR_ADDRWIN
, 0x0);
471 /* FIXME Write the initial Station Descriptor for the card */
472 sta_init(priv
, LOCAL_STAID
);
473 sta_init(priv
, BSSID_STAID
);
475 /* Enable staion 0 and 1 can do TX */
476 /* It seemed if we set other bit to 1 the bit 0 will
477 be auto change to 0 */
478 agnx_write32(ctl
, AGNX_BM_TXTOPEER
, 0x2 | 0x1);
479 /* agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1); */
480 } /* gain_ctlcnt_init */
483 static void phy_init(struct agnx_priv
*priv
)
485 void __iomem
*ctl
= priv
->ctl
;
486 void __iomem
*data
= priv
->data
;
490 /* Load InitialGainTable */
491 gain_table_init(priv
);
493 agnx_write32(ctl
, AGNX_CIR_ADDRWIN
, 0x2000000);
495 /* Clear the following offsets in Memory Range #2: */
496 memset_io(data
+ 0x5040, 0, 0xa * 4);
497 memset_io(data
+ 0x5080, 0, 0xa * 4);
498 memset_io(data
+ 0x50c0, 0, 0xa * 4);
499 memset_io(data
+ 0x5400, 0, 0x80 * 4);
500 memset_io(data
+ 0x6000, 0, 0x280 * 4);
501 memset_io(data
+ 0x7000, 0, 0x280 * 4);
502 memset_io(data
+ 0x8000, 0, 0x280 * 4);
504 /* Initialize the Following Registers According to PCI Revision ID */
505 if (priv
->revid
== 0) {
506 /* fixme the part hasn't been update but below has been update
508 agnx_write32(ctl
, AGNX_ACI_LEN
, 0xf);
509 agnx_write32(ctl
, AGNX_ACI_TIMER1
, 0x1d);
510 agnx_write32(ctl
, AGNX_ACI_TIMER2
, 0x3);
511 agnx_write32(ctl
, AGNX_ACI_AICCHA0OVE
, 0x11);
512 agnx_write32(ctl
, AGNX_ACI_AICCHA1OVE
, 0x0);
513 agnx_write32(ctl
, AGNX_GCR_THD0A
, 0x64);
514 agnx_write32(ctl
, AGNX_GCR_THD0AL
, 0x4b);
515 agnx_write32(ctl
, AGNX_GCR_THD0B
, 0x4b);
516 agnx_write32(ctl
, AGNX_GCR_DUNSAT
, 0x14);
517 agnx_write32(ctl
, AGNX_GCR_DSAT
, 0x24);
518 agnx_write32(ctl
, AGNX_GCR_DFIRCAL
, 0x8);
519 agnx_write32(ctl
, AGNX_GCR_DGCTL11A
, 0x1a);
520 agnx_write32(ctl
, AGNX_GCR_DGCTL11B
, 0x3);
521 agnx_write32(ctl
, AGNX_GCR_GAININIT
, 0xd);
522 agnx_write32(ctl
, AGNX_GCR_THNOSIG
, 0x1);
523 agnx_write32(ctl
, AGNX_GCR_COARSTEP
, 0x7);
524 agnx_write32(ctl
, AGNX_GCR_SIFST11A
, 0x28);
525 agnx_write32(ctl
, AGNX_GCR_SIFST11B
, 0x28);
526 reg
= agnx_read32(ctl
, AGNX_GCR_CWDETEC
);
528 agnx_write32(ctl
, AGNX_GCR_CWDETEC
, reg
);
529 agnx_write32(ctl
, AGNX_GCR_0X38
, 0x1e);
530 agnx_write32(ctl
, AGNX_GCR_BOACT
, 0x26);
531 agnx_write32(ctl
, AGNX_GCR_DISCOVMOD
, 0x3);
532 agnx_write32(ctl
, AGNX_GCR_NLISTANT
, 0x3);
533 agnx_write32(ctl
, AGNX_GCR_NACTIANT
, 0x3);
534 agnx_write32(ctl
, AGNX_GCR_NMEASANT
, 0x3);
535 agnx_write32(ctl
, AGNX_GCR_NCAPTANT
, 0x3);
536 agnx_write32(ctl
, AGNX_GCR_THCAP11A
, 0x0);
537 agnx_write32(ctl
, AGNX_GCR_THCAP11B
, 0x0);
538 agnx_write32(ctl
, AGNX_GCR_THCAPRX11A
, 0x0);
539 agnx_write32(ctl
, AGNX_GCR_THCAPRX11B
, 0x0);
540 agnx_write32(ctl
, AGNX_GCR_THLEVDRO
, 0x10);
541 agnx_write32(ctl
, AGNX_GCR_MAXRXTIME11A
, 0x1);
542 agnx_write32(ctl
, AGNX_GCR_MAXRXTIME11B
, 0x1);
543 agnx_write32(ctl
, AGNX_GCR_CORRTIME
, 0x190);
544 agnx_write32(ctl
, AGNX_GCR_SIGHTH
, 0x78);
545 agnx_write32(ctl
, AGNX_GCR_SIGLTH
, 0x1c);
546 agnx_write32(ctl
, AGNX_GCR_CORRDROP
, 0x0);
547 agnx_write32(ctl
, AGNX_GCR_THCD
, 0x0);
548 agnx_write32(ctl
, AGNX_GCR_MAXPOWDIFF
, 0x1);
549 agnx_write32(ctl
, AGNX_GCR_TESTBUS
, 0x0);
550 agnx_write32(ctl
, AGNX_GCR_ANTCFG
, 0x1f);
551 agnx_write32(ctl
, AGNX_GCR_THJUMP
, 0x14);
552 agnx_write32(ctl
, AGNX_GCR_THPOWER
, 0x0);
553 agnx_write32(ctl
, AGNX_GCR_THPOWCLIP
, 0x30);
554 agnx_write32(ctl
, AGNX_GCR_THD0BTFEST
, 0x32);
555 agnx_write32(ctl
, AGNX_GCR_THRX11BPOWMIN
, 0x19);
556 agnx_write32(ctl
, AGNX_GCR_0X14c
, 0x0);
557 agnx_write32(ctl
, AGNX_GCR_0X150
, 0x0);
558 agnx_write32(ctl
, 0x9400, 0x0);
559 agnx_write32(ctl
, 0x940c, 0x6ff);
560 agnx_write32(ctl
, 0x9428, 0xa0);
561 agnx_write32(ctl
, 0x9434, 0x0);
562 agnx_write32(ctl
, 0x9c04, 0x15);
563 agnx_write32(ctl
, 0x9c0c, 0x7f);
564 agnx_write32(ctl
, 0x9c34, 0x0);
565 agnx_write32(ctl
, 0xc000, 0x38d);
566 agnx_write32(ctl
, 0x14018, 0x0);
567 agnx_write32(ctl
, 0x16000, 0x1);
568 agnx_write32(ctl
, 0x11004, 0x0);
569 agnx_write32(ctl
, 0xec54, 0xa);
570 agnx_write32(ctl
, 0xec1c, 0x5);
571 } else if (priv
->revid
> 0) {
572 agnx_write32(ctl
, AGNX_ACI_LEN
, 0xf);
573 agnx_write32(ctl
, AGNX_ACI_TIMER1
, 0x21);
574 agnx_write32(ctl
, AGNX_ACI_TIMER2
, 0x27);
575 agnx_write32(ctl
, AGNX_ACI_AICCHA0OVE
, 0x11);
576 agnx_write32(ctl
, AGNX_ACI_AICCHA1OVE
, 0x0);
577 agnx_write32(ctl
, AGNX_GCR_DUNSAT
, 0x14);
578 agnx_write32(ctl
, AGNX_GCR_DSAT
, 0x24);
579 agnx_write32(ctl
, AGNX_GCR_DFIRCAL
, 0x8);
580 agnx_write32(ctl
, AGNX_GCR_DGCTL11A
, 0x1a);
581 agnx_write32(ctl
, AGNX_GCR_DGCTL11B
, 0x3);
582 agnx_write32(ctl
, AGNX_GCR_GAININIT
, 0xd);
583 agnx_write32(ctl
, AGNX_GCR_THNOSIG
, 0x1);
584 agnx_write32(ctl
, AGNX_GCR_COARSTEP
, 0x7);
585 agnx_write32(ctl
, AGNX_GCR_SIFST11A
, 0x28);
586 agnx_write32(ctl
, AGNX_GCR_SIFST11B
, 0x28);
587 agnx_write32(ctl
, AGNX_GCR_CWDETEC
, 0x0);
588 agnx_write32(ctl
, AGNX_GCR_0X38
, 0x1e);
589 /* agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);*/
590 agnx_write32(ctl
, AGNX_GCR_DISCOVMOD
, 0x3);
592 agnx_write32(ctl
, AGNX_GCR_THCAP11A
, 0x32);
593 agnx_write32(ctl
, AGNX_GCR_THCAP11B
, 0x32);
594 agnx_write32(ctl
, AGNX_GCR_THCAPRX11A
, 0x32);
595 agnx_write32(ctl
, AGNX_GCR_THCAPRX11B
, 0x32);
596 agnx_write32(ctl
, AGNX_GCR_THLEVDRO
, 0x10);
597 agnx_write32(ctl
, AGNX_GCR_MAXRXTIME11A
, 0x1ad);
598 agnx_write32(ctl
, AGNX_GCR_MAXRXTIME11B
, 0xa10);
599 agnx_write32(ctl
, AGNX_GCR_CORRTIME
, 0x190);
600 agnx_write32(ctl
, AGNX_GCR_CORRDROP
, 0x0);
601 agnx_write32(ctl
, AGNX_GCR_THCD
, 0x0);
602 agnx_write32(ctl
, AGNX_GCR_THCS
, 0x0);
603 agnx_write32(ctl
, AGNX_GCR_MAXPOWDIFF
, 0x4);
604 agnx_write32(ctl
, AGNX_GCR_TESTBUS
, 0x0);
605 agnx_write32(ctl
, AGNX_GCR_THJUMP
, 0x1e);
606 agnx_write32(ctl
, AGNX_GCR_THPOWER
, 0x0);
607 agnx_write32(ctl
, AGNX_GCR_THPOWCLIP
, 0x2a);
608 agnx_write32(ctl
, AGNX_GCR_THD0BTFEST
, 0x3c);
609 agnx_write32(ctl
, AGNX_GCR_THRX11BPOWMIN
, 0x19);
610 agnx_write32(ctl
, AGNX_GCR_0X14c
, 0x0);
611 agnx_write32(ctl
, AGNX_GCR_0X150
, 0x0);
612 agnx_write32(ctl
, AGNX_GCR_RXOVERIDE
, 0x0);
613 agnx_write32(ctl
, AGNX_GCR_WATCHDOG
, 0x37);
614 agnx_write32(ctl
, 0x9400, 0x0);
615 agnx_write32(ctl
, 0x940c, 0x6ff);
616 agnx_write32(ctl
, 0x9428, 0xa0);
617 agnx_write32(ctl
, 0x9434, 0x0);
618 agnx_write32(ctl
, 0x9c04, 0x15);
619 agnx_write32(ctl
, 0x9c0c, 0x7f);
620 agnx_write32(ctl
, 0x9c34, 0x0);
621 agnx_write32(ctl
, 0xc000, 0x38d);
622 agnx_write32(ctl
, 0x14014, 0x1000);
623 agnx_write32(ctl
, 0x14018, 0x0);
624 agnx_write32(ctl
, 0x16000, 0x1);
625 agnx_write32(ctl
, 0x11004, 0x0);
626 agnx_write32(ctl
, 0xec54, 0xa);
627 agnx_write32(ctl
, 0xec1c, 0x50);
628 } else if (priv
->revid
> 1) {
629 reg
= agnx_read32(ctl
, 0xec18);
631 agnx_write32(ctl
, 0xec18, reg
);
634 /* Write the TX Fir Coefficient Table */
635 tx_fir_table_init(priv
);
637 reg
= agnx_read32(ctl
, AGNX_PM_PMCTL
);
639 agnx_write32(ctl
, AGNX_PM_PMCTL
, reg
);
640 reg
= agnx_read32(ctl
, AGNX_PM_PLLCTL
);
642 agnx_write32(ctl
, AGNX_PM_PLLCTL
, reg
);
644 /* reg = agnx_read32(ctl, 0x1a030); */
646 /* agnx_write32(ctl, 0x1a030, reg); */
648 agnx_write32(ctl
, AGNX_GCR_TRACNT4
, 0x113);
651 static void chip_init(struct agnx_priv
*priv
)
653 void __iomem
*ctl
= priv
->ctl
;
657 band_management_init(priv
);
661 reg
= agnx_read32(ctl
, AGNX_PM_PMCTL
);
663 agnx_write32(ctl
, AGNX_PM_PMCTL
, reg
);
665 /* Initialize the PHY */
668 encryption_init(priv
);
670 tx_management_init(priv
);
672 rx_management_init(priv
);
674 power_manage_init(priv
);
676 /* Initialize the Timers */
677 agnx_timer_init(priv
);
679 /* Write 0xc390bf9 to Interrupt Mask (Disable TX) */
680 reg
= 0xc390bf9 & ~IRQ_TX_BEACON
;
681 reg
&= ~IRQ_TX_DISABLE
;
682 agnx_write32(ctl
, AGNX_INT_MASK
, reg
);
684 reg
= agnx_read32(ctl
, AGNX_CIR_BLKCTL
);
686 agnx_write32(ctl
, AGNX_CIR_BLKCTL
, reg
);
688 /* set it when need get multicast enable? */
689 agnx_write32(ctl
, AGNX_BM_MTSM
, 0xff);
693 static inline void set_promis_and_managed(struct agnx_priv
*priv
)
695 void __iomem
*ctl
= priv
->ctl
;
696 agnx_write32(ctl
, AGNX_SYSITF_SYSMODE
, 0x10 | 0x2);
697 agnx_write32(ctl
, AGNX_SYSITF_SYSMODE
, 0x10 | 0x2);
699 static inline void set_learn_mode(struct agnx_priv
*priv
)
701 void __iomem
*ctl
= priv
->ctl
;
702 agnx_write32(ctl
, AGNX_SYSITF_SYSMODE
, 0x8);
704 static inline void set_scan_mode(struct agnx_priv
*priv
)
706 void __iomem
*ctl
= priv
->ctl
;
707 agnx_write32(ctl
, AGNX_SYSITF_SYSMODE
, 0x20);
709 static inline void set_promiscuous_mode(struct agnx_priv
*priv
)
711 void __iomem
*ctl
= priv
->ctl
;
712 /* agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x210);*/
713 agnx_write32(ctl
, AGNX_SYSITF_SYSMODE
, 0x10);
715 static inline void set_managed_mode(struct agnx_priv
*priv
)
717 void __iomem
*ctl
= priv
->ctl
;
718 agnx_write32(ctl
, AGNX_SYSITF_SYSMODE
, 0x2);
720 static inline void set_adhoc_mode(struct agnx_priv
*priv
)
722 void __iomem
*ctl
= priv
->ctl
;
723 agnx_write32(ctl
, AGNX_SYSITF_SYSMODE
, 0x0);
727 static void unknow_register_write(struct agnx_priv
*priv
)
729 void __iomem
*ctl
= priv
->ctl
;
731 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x0, 0x3e);
732 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x4, 0xb2);
733 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x8, 0x140);
734 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0xc, 0x1C0);
735 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x10, 0x1FF);
736 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x14, 0x1DD);
737 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x18, 0x15F);
738 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x1c, 0xA1);
739 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x20, 0x3E7);
740 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x24, 0x36B);
741 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x28, 0x348);
742 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x2c, 0x37D);
743 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x30, 0x3DE);
744 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x34, 0x36);
745 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x38, 0x64);
746 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x3c, 0x57);
747 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x40, 0x23);
748 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x44, 0x3ED);
749 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x48, 0x3C9);
750 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x4c, 0x3CA);
751 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x50, 0x3E7);
752 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x54, 0x8);
753 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x58, 0x1F);
754 agnx_write32(ctl
, AGNX_UNKNOWN_BASE
+ 0x5c, 0x1a);
758 static void card_interface_init(struct agnx_priv
*priv
)
760 void __iomem
*ctl
= priv
->ctl
;
761 u8 bssid
[ETH_ALEN
] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
767 /* Clear RX Control and Enable RX queues */
768 agnx_write32(ctl
, AGNX_CIR_RXCTL
, 0x8);
771 /* Do a full reset of the card */
772 card_full_reset(priv
);
775 /* Check and set Card Endianness */
776 reg
= ioread32(priv
->ctl
+ AGNX_CIR_ENDIAN
);
777 /* TODO If not 0xB3B2B1B0 set to 0xB3B2B1B0 */
778 printk(KERN_INFO PFX
"CIR_ENDIAN is %x\n", reg
);
781 /* Config the eeprom */
782 agnx_write32(ctl
, AGNX_CIR_SERIALITF
, 0x7000086);
784 reg
= agnx_read32(ctl
, AGNX_CIR_SERIALITF
);
787 agnx_write32(ctl
, AGNX_PM_SOFTRST
, 0x80000033);
788 reg
= agnx_read32(ctl
, 0xec50);
790 agnx_write32(ctl
, 0xec50, reg
);
791 agnx_write32(ctl
, AGNX_PM_SOFTRST
, 0x0);
794 reg
= agnx_read32(ctl
, AGNX_SYSITF_GPIOIN
);
796 reg
= agnx_read32(ctl
, AGNX_CIR_SERIALITF
);
798 /* Dump the eeprom */
800 char eeprom
[0x100000/0x100];
802 for (i
= 0; i
< 0x100000; i
+= 0x100) {
803 agnx_write32(ctl
, AGNX_CIR_SERIALITF
, 0x3000000 + i
);
805 reg
= agnx_read32(ctl
, AGNX_CIR_SERIALITF
);
807 reg
= agnx_read32(ctl
, AGNX_CIR_SERIALITF
);
808 eeprom
[i
/0x100] = reg
& 0xFF;
811 print_hex_dump_bytes(PFX
"EEPROM: ", DUMP_PREFIX_NONE
, eeprom
,
815 spi_rc_write(ctl
, RF_CHIP0
, 0x26);
816 reg
= agnx_read32(ctl
, AGNX_SPI_RLSW
);
818 /* Initialize the system interface */
819 system_itf_init(priv
);
822 /* Chip Initialization (Polaris) */
826 /* Calibrate the antennae */
827 antenna_calibrate(priv
);
829 reg
= agnx_read32(ctl
, 0xec50);
831 agnx_write32(ctl
, 0xec50, reg
);
832 agnx_write32(ctl
, AGNX_PM_SOFTRST
, 0x0);
833 agnx_write32(ctl
, AGNX_PM_PLLCTL
, 0x1);
835 reg
= agnx_read32(ctl
, AGNX_BM_BMCTL
);
837 agnx_write32(ctl
, AGNX_BM_BMCTL
, reg
);
838 enable_receiver(priv
);
839 reg
= agnx_read32(ctl
, AGNX_SYSITF_SYSMODE
);
841 agnx_write32(ctl
, AGNX_SYSITF_SYSMODE
, reg
);
842 enable_receiver(priv
);
845 /* Initialize Gain Control Counts */
846 gain_ctlcnt_init(priv
);
848 /* Write Initial Station Power Template for this station(#0) */
849 sta_power_init(priv
, LOCAL_STAID
);
852 /* Initialize the rx,td,tm rings, for each node in the ring */
858 agnx_write32(ctl
, AGNX_PM_SOFTRST
, 0x80000033);
859 agnx_write32(ctl
, 0xec50, 0xc);
860 agnx_write32(ctl
, AGNX_PM_SOFTRST
, 0x0);
862 /* FIXME Initialize the transmit control register */
863 agnx_write32(ctl
, AGNX_TXM_CTL
, 0x194c1);
865 enable_receiver(priv
);
868 /* FIXME Set the Receive Control Mac Address to card address */
869 mac_address_set(priv
);
870 enable_receiver(priv
);
873 /* Set the recieve request rate */
874 /* FIXME Enable the request */
875 /* Check packet length */
876 /* Set maximum packet length */
877 /* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */
878 /* enable_receiver(priv); */
880 /* Set the Receiver BSSID */
881 receiver_bssid_set(priv
, bssid
);
883 /* FIXME Set to managed mode */
884 set_managed_mode(priv
);
885 /* set_promiscuous_mode(priv); */
886 /* set_scan_mode(priv); */
887 /* set_learn_mode(priv); */
888 /* set_promis_and_managed(priv); */
889 /* set_adhoc_mode(priv); */
891 /* Set the recieve request rate */
892 /* Check packet length */
893 agnx_write32(ctl
, AGNX_RXM_REQRATE
, 0x08000000);
894 reg
= agnx_read32(ctl
, AGNX_RXM_REQRATE
);
895 /* Set maximum packet length */
897 agnx_write32(ctl
, AGNX_RXM_REQRATE
, reg
);
899 /* Configure the RX and TX interrupt */
900 reg
= ENABLE_RX_INTERRUPT
| RX_CACHE_LINE
| FRAG_LEN_2048
| FRAG_BE
;
901 agnx_write32(ctl
, AGNX_CIR_RXCFG
, reg
);
903 reg
= ENABLE_TX_INTERRUPT
| TX_CACHE_LINE
| FRAG_LEN_2048
| FRAG_BE
;
904 agnx_write32(ctl
, AGNX_CIR_TXCFG
, reg
);
906 /* Enable RX TX Interrupts */
907 agnx_write32(ctl
, AGNX_CIR_RXCTL
, 0x80);
908 agnx_write32(ctl
, AGNX_CIR_TXMCTL
, 0x80);
909 agnx_write32(ctl
, AGNX_CIR_TXDCTL
, 0x80);
911 /* FIXME Set the master control interrupt in block control */
912 agnx_write32(ctl
, AGNX_CIR_BLKCTL
, 0x800);
914 /* Enable RX and TX queues */
915 reg
= agnx_read32(ctl
, AGNX_CIR_RXCTL
);
917 agnx_write32(ctl
, AGNX_CIR_RXCTL
, reg
);
918 reg
= agnx_read32(ctl
, AGNX_CIR_TXMCTL
);
920 agnx_write32(ctl
, AGNX_CIR_TXMCTL
, reg
);
921 reg
= agnx_read32(ctl
, AGNX_CIR_TXDCTL
);
923 agnx_write32(ctl
, AGNX_CIR_TXDCTL
, reg
);
925 agnx_write32(ctl
, AGNX_SYSITF_GPIOUT
, 0x5);
927 /* unknow_register_write(priv); */
928 /* Update local card hash entry */
929 hash_write(priv
, priv
->mac_addr
, LOCAL_STAID
);
934 agnx_set_channel(priv
, 1);
936 } /* agnx_card_interface_init */
939 void agnx_hw_init(struct agnx_priv
*priv
)
943 card_interface_init(priv
);
946 int agnx_hw_reset(struct agnx_priv
*priv
)
948 return card_full_reset(priv
);
951 int agnx_set_ssid(struct agnx_priv
*priv
, u8
*ssid
, size_t ssid_len
)
957 void agnx_set_bssid(struct agnx_priv
*priv
, const u8
*bssid
)
959 receiver_bssid_set(priv
, bssid
);