Recognize and report AR9160 and AR9280
[madwifi/.git] / ath / if_ath_hal_extensions.c
1 /*
2  * Copyright (c) 2008 Bruno Randolf <br1@einfach.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10         without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  * 3. Neither the names of the above-listed copyright holders nor the names
16  *    of any contributors may be used to endorse or promote products derived
17  *    from this software without specific prior written permission.
18  *
19  * Alternatively, this software may be distributed under the terms of the
20  * GNU General Public License ("GPL") version 2 as published by the Free
21  * Software Foundation.
22  *
23  * NO WARRANTY
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
27  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
29  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
32  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34  * THE POSSIBILITY OF SUCH DAMAGES.
35  *
36  * $Id: br1 $
37  */
38
39 #include "ath_hal/ah_devid.h"
40 #include "if_media.h"
41 #include <net80211/ieee80211_var.h>
42 #include "if_athvar.h"
43 #include "if_ath_hal.h"
44 #include "if_ath_hal_macros.h"
45 #include "if_ath_hal_wrappers.h"
46 #include "if_ath_hal_extensions.h"
47
48
49 /* Known SREVs */
50 static struct ath5k_srev_name srev_names[] = {
51         { "5210",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5210 },
52         { "5311",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5311 },
53         { "5311A",      AR5K_VERSION_VER,       AR5K_SREV_VER_AR5311A },
54         { "5311B",      AR5K_VERSION_VER,       AR5K_SREV_VER_AR5311B },
55         { "5211",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5211 },
56         { "5212",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5212 },
57         { "5213",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5213 },
58         { "5213A",      AR5K_VERSION_VER,       AR5K_SREV_VER_AR5213A },
59         { "2413",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR2413 },
60         { "2414",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR2414 },
61         { "2424",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR2424 },
62         { "5424",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5424 },
63         { "5413",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5413 },
64         { "5414",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5414 },
65         { "5416",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5416 },
66         { "5418",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5418 },
67         { "2425",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR2425 },
68         { "9160",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR9160 },
69         { "9280",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR9280 },
70         { "xxxxx",      AR5K_VERSION_VER,       AR5K_SREV_UNKNOWN },
71         { "5110",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5110 },
72         { "5111",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5111 },
73         { "2111",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2111 },
74         { "5112",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5112 },
75         { "5112A",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_5112A },
76         { "2112",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2112 },
77         { "2112A",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_2112A },
78         { "SChip",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_SC0 },
79         { "SChip",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_SC1 },
80         { "SChip",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_SC2 },
81         { "5133",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5133 },
82         { "xxxxx",      AR5K_VERSION_RAD,       AR5K_SREV_UNKNOWN },
83 };
84
85 #define AR5210_MAGIC    0x19980124
86 #define AR5211_MAGIC    0x19570405
87 #define AR5212_MAGIC    0x19541014
88 #define AR5416_MAGIC    0x20065416
89
90 int
91 ar_device(struct ath_softc *sc)
92 {
93         int magic = sc->sc_ah->ah_magic;
94
95         switch (magic) {
96         case AR5210_MAGIC:
97                 return 5210;
98         case AR5211_MAGIC:
99                 return 5211;
100         case AR5212_MAGIC:
101                 return 5212;
102         case AR5416_MAGIC:
103                 return 5416;
104         default:
105                 printk(KERN_WARNING "unknown HAL magic 0x%08x\n", magic);
106                 return 0;
107         }
108 }
109
110 int
111 ath_set_ack_bitrate(struct ath_softc *sc, int high)
112 {
113         if (ar_device(sc) == 5212) {
114                 /* set ack to be sent at low bit-rate */
115                 u_int32_t v = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
116                 if (high)
117                         ath_reg_write(sc, AR5K_STA_ID1,
118                                         ath_reg_read(sc, AR5K_STA_ID1) & ~v);
119                 else
120                         ath_reg_write(sc, AR5K_STA_ID1,
121                                         ath_reg_read(sc, AR5K_STA_ID1) | v);
122                 return 0;
123         }
124         return 1;
125 }
126
127
128 const char *
129 ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
130 {
131         const char *name = "xxxxx";
132         unsigned int i;
133
134         for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
135                 if (srev_names[i].sr_type != type)
136                         continue;
137                 if (val < srev_names[i + 1].sr_val) {
138                         name = srev_names[i].sr_name;
139                         break;
140                 }
141         }
142
143         return name;
144 }
145
146
147 void
148 ath_hw_beacon_stop(struct ath_softc *sc) {
149         HAL_BEACON_TIMERS btimers;
150
151         btimers.bt_intval = 0;
152         btimers.bt_nexttbtt = 0;
153         btimers.bt_nextdba = 0xffffffff;
154         btimers.bt_nextswba = 0xffffffff;
155         btimers.bt_nextatim = 0;
156
157         ath_hal_setbeacontimers(sc->sc_ah, &btimers);
158 }
159
160
161 /*
162  * IBSS mode: check the ATIM window size and fix it if necessary.
163  *
164  * the need for this function arises from the problem that due to unlucky timing
165  * of beacon timer configuration (which we try to avoid) and due to unlucky
166  * timing of local TSF updates (triggered by the reception of a beacon with the
167  * same BSSID - something we can't avoid) the beacon timers can be up updated
168  * seperately, leaving one of them in the past, not beeing updated until the
169  * timers wrap around. due to the fact that the beacon interval does not fit
170  * into the timer period (16 bit) a whole number of times the size of the ATIM
171  * window can get bigger than desired.
172  *
173  * usually we have an ATIM window size of 1 but this function is written to
174  * handle other window sizes as well.
175  */
176 int
177 ath_hw_check_atim(struct ath_softc *sc, int window, int intval)
178 {
179         struct ath_hal *ah = sc->sc_ah;
180         unsigned int nbtt, atim, is5210 = 0;
181
182         if (ATH_SREV_FROM_AH(ah) >= AR5K_SREV_VER_AR5416)
183                 return 0; /* AR5416+ doesn't do ATIM in HW */
184
185         if (ATH_SREV_FROM_AH(ah) == AR5K_SREV_VER_AR5210) {
186                 nbtt = OS_REG_READ(ah, AR5K_TIMER0_5210);
187                 atim = OS_REG_READ(ah, AR5K_TIMER3_5210);
188                 is5210 = 1;
189         }
190         else {
191                 nbtt = OS_REG_READ(ah, AR5K_TIMER0_5211);
192                 atim = OS_REG_READ(ah, AR5K_TIMER3_5211);
193         }
194
195         /*
196          * check if the ATIM window is still correct:
197          *   1.) usually ATIM should be NBTT + window
198          *   2.) nbtt already updated
199          *   3.) nbtt already updated and has wrapped around
200          *   4.) atim has wrapped around
201          */
202         if ((atim - nbtt != window) &&                          /* 1.) */
203             (nbtt - atim != intval - window) &&                 /* 2.) */
204             ((nbtt | 0x10000) - atim != intval - window) &&     /* 3.) */
205             ((atim | 0x10000) - nbtt != window)) {              /* 4.) */
206                 if (is5210)
207                         OS_REG_WRITE(ah, AR5K_TIMER3_5210, nbtt + window );
208                 else
209                         OS_REG_WRITE(ah, AR5K_TIMER3_5211, nbtt + window );
210                 return atim - nbtt;
211         }
212         return 0;
213 }