1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 
4   Broadcom B43 wireless driver
5   IEEE 802.11n LCN-PHY data tables
6 
7   Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
8 
9 
10 */
11 
12 #include "b43.h"
13 #include "tables_phy_lcn.h"
14 #include "phy_common.h"
15 #include "phy_lcn.h"
16 
17 struct b43_lcntab_tx_gain_tbl_entry {
18 	u8 gm;
19 	u8 pga;
20 	u8 pad;
21 	u8 dac;
22 	u8 bb_mult;
23 };
24 
25 /**************************************************
26  * Static tables.
27  **************************************************/
28 
29 static const u16 b43_lcntab_0x02[] = {
30 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
31 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
32 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
33 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
34 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
35 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
36 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
37 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
38 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
39 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
40 	0x014d, 0x014d, 0x014d, 0x014d,
41 };
42 
43 static const u16 b43_lcntab_0x01[] = {
44 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
45 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
46 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
47 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
48 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
49 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
50 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
51 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
52 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
53 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
54 	0x0000, 0x0000, 0x0000, 0x0000,
55 };
56 
57 static const u32 b43_lcntab_0x0b[] = {
58 	0x000141f8, 0x000021f8, 0x000021fb, 0x000041fb,
59 	0x0001fedb, 0x0000217b, 0x00002133, 0x000040eb,
60 	0x0001fea3, 0x0000024b,
61 };
62 
63 static const u32 b43_lcntab_0x0c[] = {
64 	0x00100001, 0x00200010, 0x00300001, 0x00400010,
65 	0x00500022, 0x00600122, 0x00700222, 0x00800322,
66 	0x00900422, 0x00a00522, 0x00b00622, 0x00c00722,
67 	0x00d00822, 0x00f00922, 0x00100a22, 0x00200b22,
68 	0x00300c22, 0x00400d22, 0x00500e22, 0x00600f22,
69 };
70 
71 static const u32 b43_lcntab_0x0d[] = {
72 	0x00000000, 0x00000000, 0x10000000, 0x00000000,
73 	0x20000000, 0x00000000, 0x30000000, 0x00000000,
74 	0x40000000, 0x00000000, 0x50000000, 0x00000000,
75 	0x60000000, 0x00000000, 0x70000000, 0x00000000,
76 	0x80000000, 0x00000000, 0x90000000, 0x00000008,
77 	0xa0000000, 0x00000008, 0xb0000000, 0x00000008,
78 	0xc0000000, 0x00000008, 0xd0000000, 0x00000008,
79 	0xe0000000, 0x00000008, 0xf0000000, 0x00000008,
80 	0x00000000, 0x00000009, 0x10000000, 0x00000009,
81 	0x20000000, 0x00000019, 0x30000000, 0x00000019,
82 	0x40000000, 0x00000019, 0x50000000, 0x00000019,
83 	0x60000000, 0x00000019, 0x70000000, 0x00000019,
84 	0x80000000, 0x00000019, 0x90000000, 0x00000019,
85 	0xa0000000, 0x00000019, 0xb0000000, 0x00000019,
86 	0xc0000000, 0x00000019, 0xd0000000, 0x00000019,
87 	0xe0000000, 0x00000019, 0xf0000000, 0x00000019,
88 	0x00000000, 0x0000001a, 0x10000000, 0x0000001a,
89 	0x20000000, 0x0000001a, 0x30000000, 0x0000001a,
90 	0x40000000, 0x0000001a, 0x50000000, 0x00000002,
91 	0x60000000, 0x00000002, 0x70000000, 0x00000002,
92 	0x80000000, 0x00000002, 0x90000000, 0x00000002,
93 	0xa0000000, 0x00000002, 0xb0000000, 0x00000002,
94 	0xc0000000, 0x0000000a, 0xd0000000, 0x0000000a,
95 	0xe0000000, 0x0000000a, 0xf0000000, 0x0000000a,
96 	0x00000000, 0x0000000b, 0x10000000, 0x0000000b,
97 	0x20000000, 0x0000000b, 0x30000000, 0x0000000b,
98 	0x40000000, 0x0000000b, 0x50000000, 0x0000001b,
99 	0x60000000, 0x0000001b, 0x70000000, 0x0000001b,
100 	0x80000000, 0x0000001b, 0x90000000, 0x0000001b,
101 	0xa0000000, 0x0000001b, 0xb0000000, 0x0000001b,
102 	0xc0000000, 0x0000001b, 0xd0000000, 0x0000001b,
103 	0xe0000000, 0x0000001b, 0xf0000000, 0x0000001b,
104 	0x00000000, 0x0000001c, 0x10000000, 0x0000001c,
105 	0x20000000, 0x0000001c, 0x30000000, 0x0000001c,
106 	0x40000000, 0x0000001c, 0x50000000, 0x0000001c,
107 	0x60000000, 0x0000001c, 0x70000000, 0x0000001c,
108 	0x80000000, 0x0000001c, 0x90000000, 0x0000001c,
109 };
110 
111 static const u16 b43_lcntab_0x0e[] = {
112 	0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406,
113 	0x0407, 0x0408, 0x0409, 0x040a, 0x058b, 0x058c,
114 	0x058d, 0x058e, 0x058f, 0x0090, 0x0091, 0x0092,
115 	0x0193, 0x0194, 0x0195, 0x0196, 0x0197, 0x0198,
116 	0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e,
117 	0x019f, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 0x01a4,
118 	0x01a5, 0x0000,
119 };
120 
121 static const u16 b43_lcntab_0x0f[] = {
122 	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
123 	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
124 	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
125 	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
126 	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
127 	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
128 	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
129 	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
130 	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
131 	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
132 	0x000a, 0x0009, 0x0006, 0x0005,
133 };
134 
135 static const u16 b43_lcntab_0x10[] = {
136 	0x005f, 0x0036, 0x0029, 0x001f, 0x005f, 0x0036,
137 	0x0029, 0x001f, 0x005f, 0x0036, 0x0029, 0x001f,
138 	0x005f, 0x0036, 0x0029, 0x001f,
139 };
140 
141 static const u16 b43_lcntab_0x11[] = {
142 	0x0009, 0x000f, 0x0014, 0x0018, 0x00fe, 0x0007,
143 	0x000b, 0x000f, 0x00fb, 0x00fe, 0x0001, 0x0005,
144 	0x0008, 0x000b, 0x000e, 0x0011, 0x0014, 0x0017,
145 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
146 	0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f,
147 	0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
148 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003,
149 	0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015,
150 	0x0018, 0x001b, 0x0000, 0x0000, 0x0000, 0x0000,
151 	0x0000, 0x0000, 0x0003, 0x00eb, 0x0000, 0x0000,
152 };
153 
154 static const u32 b43_lcntab_0x12[] = {
155 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
156 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
157 	0x00000004, 0x00000000, 0x00000004, 0x00000008,
158 	0x00000001, 0x00000005, 0x00000009, 0x0000000d,
159 	0x0000004d, 0x0000008d, 0x0000000d, 0x0000004d,
160 	0x0000008d, 0x000000cd, 0x0000004f, 0x0000008f,
161 	0x000000cf, 0x000000d3, 0x00000113, 0x00000513,
162 	0x00000913, 0x00000953, 0x00000d53, 0x00001153,
163 	0x00001193, 0x00005193, 0x00009193, 0x0000d193,
164 	0x00011193, 0x00000000, 0x00000000, 0x00000000,
165 	0x00000000, 0x00000000, 0x00000000, 0x00000004,
166 	0x00000000, 0x00000004, 0x00000008, 0x00000001,
167 	0x00000005, 0x00000009, 0x0000000d, 0x0000004d,
168 	0x0000008d, 0x0000000d, 0x0000004d, 0x0000008d,
169 	0x000000cd, 0x0000004f, 0x0000008f, 0x000000cf,
170 	0x000000d3, 0x00000113, 0x00000513, 0x00000913,
171 	0x00000953, 0x00000d53, 0x00001153, 0x00005153,
172 	0x00009153, 0x0000d153, 0x00011153, 0x00015153,
173 	0x00019153, 0x0001d153, 0x00000000, 0x00000000,
174 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
175 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
176 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
177 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
178 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
179 };
180 
181 static const u16 b43_lcntab_0x14[] = {
182 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
183 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
184 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
185 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
186 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
187 	0x0002, 0x0003, 0x0001, 0x0003, 0x0002, 0x0001,
188 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
189 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
190 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
191 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
192 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
193 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
194 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
195 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
196 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
197 	0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0003,
198 	0x0001, 0x0003, 0x0002, 0x0001, 0x0001, 0x0001,
199 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
200 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
201 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
202 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
203 	0x0001, 0x0001,
204 };
205 
206 static const u16 b43_lcntab_0x17[] = {
207 	0x001a, 0x0034, 0x004e, 0x0068, 0x009c, 0x00d0,
208 	0x00ea, 0x0104, 0x0034, 0x0068, 0x009c, 0x00d0,
209 	0x0138, 0x01a0, 0x01d4, 0x0208, 0x004e, 0x009c,
210 	0x00ea, 0x0138, 0x01d4, 0x0270, 0x02be, 0x030c,
211 	0x0068, 0x00d0, 0x0138, 0x01a0, 0x0270, 0x0340,
212 	0x03a8, 0x0410, 0x0018, 0x009c, 0x00d0, 0x0104,
213 	0x00ea, 0x0138, 0x0186, 0x00d0, 0x0104, 0x0104,
214 	0x0138, 0x016c, 0x016c, 0x01a0, 0x0138, 0x0186,
215 	0x0186, 0x01d4, 0x0222, 0x0222, 0x0270, 0x0104,
216 	0x0138, 0x016c, 0x0138, 0x016c, 0x01a0, 0x01d4,
217 	0x01a0, 0x01d4, 0x0208, 0x0208, 0x023c, 0x0186,
218 	0x01d4, 0x0222, 0x01d4, 0x0222, 0x0270, 0x02be,
219 	0x0270, 0x02be, 0x030c, 0x030c, 0x035a, 0x0036,
220 	0x006c, 0x00a2, 0x00d8, 0x0144, 0x01b0, 0x01e6,
221 	0x021c, 0x006c, 0x00d8, 0x0144, 0x01b0, 0x0288,
222 	0x0360, 0x03cc, 0x0438, 0x00a2, 0x0144, 0x01e6,
223 	0x0288, 0x03cc, 0x0510, 0x05b2, 0x0654, 0x00d8,
224 	0x01b0, 0x0288, 0x0360, 0x0510, 0x06c0, 0x0798,
225 	0x0870, 0x0018, 0x0144, 0x01b0, 0x021c, 0x01e6,
226 	0x0288, 0x032a, 0x01b0, 0x021c, 0x021c, 0x0288,
227 	0x02f4, 0x02f4, 0x0360, 0x0288, 0x032a, 0x032a,
228 	0x03cc, 0x046e, 0x046e, 0x0510, 0x021c, 0x0288,
229 	0x02f4, 0x0288, 0x02f4, 0x0360, 0x03cc, 0x0360,
230 	0x03cc, 0x0438, 0x0438, 0x04a4, 0x032a, 0x03cc,
231 	0x046e, 0x03cc, 0x046e, 0x0510, 0x05b2, 0x0510,
232 	0x05b2, 0x0654, 0x0654, 0x06f6,
233 };
234 
235 static const u16 b43_lcntab_0x00[] = {
236 	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00,
237 	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005,
238 	0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
239 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
240 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
241 	0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
242 	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003,
243 	0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007,
244 	0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
245 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
246 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
247 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
248 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
249 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
250 	0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
251 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
252 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
253 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
254 };
255 
256 static const u32 b43_lcntab_0x18[] = {
257 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
258 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
259 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
260 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
261 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
262 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
263 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
264 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
265 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
266 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
267 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
268 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
269 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
270 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
271 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
272 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
273 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
274 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
275 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
276 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
277 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
278 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
279 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
280 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
281 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
282 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
283 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
284 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
285 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
286 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
287 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
288 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
289 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
290 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
291 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
292 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
293 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
294 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
295 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
296 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
297 };
298 
299 /**************************************************
300  * TX gain.
301  **************************************************/
302 
303 static const struct b43_lcntab_tx_gain_tbl_entry
304 	b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = {
305 	{ 0x03, 0x00, 0x1f, 0x0, 0x48 },
306 	{ 0x03, 0x00, 0x1f, 0x0, 0x46 },
307 	{ 0x03, 0x00, 0x1f, 0x0, 0x44 },
308 	{ 0x03, 0x00, 0x1e, 0x0, 0x43 },
309 	{ 0x03, 0x00, 0x1d, 0x0, 0x44 },
310 	{ 0x03, 0x00, 0x1c, 0x0, 0x44 },
311 	{ 0x03, 0x00, 0x1b, 0x0, 0x45 },
312 	{ 0x03, 0x00, 0x1a, 0x0, 0x46 },
313 	{ 0x03, 0x00, 0x19, 0x0, 0x46 },
314 	{ 0x03, 0x00, 0x18, 0x0, 0x47 },
315 	{ 0x03, 0x00, 0x17, 0x0, 0x48 },
316 	{ 0x03, 0x00, 0x17, 0x0, 0x46 },
317 	{ 0x03, 0x00, 0x16, 0x0, 0x47 },
318 	{ 0x03, 0x00, 0x15, 0x0, 0x48 },
319 	{ 0x03, 0x00, 0x15, 0x0, 0x46 },
320 	{ 0x03, 0x00, 0x15, 0x0, 0x44 },
321 	{ 0x03, 0x00, 0x15, 0x0, 0x42 },
322 	{ 0x03, 0x00, 0x15, 0x0, 0x40 },
323 	{ 0x03, 0x00, 0x15, 0x0, 0x3f },
324 	{ 0x03, 0x00, 0x14, 0x0, 0x40 },
325 	{ 0x03, 0x00, 0x13, 0x0, 0x41 },
326 	{ 0x03, 0x00, 0x13, 0x0, 0x40 },
327 	{ 0x03, 0x00, 0x12, 0x0, 0x41 },
328 	{ 0x03, 0x00, 0x12, 0x0, 0x40 },
329 	{ 0x03, 0x00, 0x11, 0x0, 0x41 },
330 	{ 0x03, 0x00, 0x11, 0x0, 0x40 },
331 	{ 0x03, 0x00, 0x10, 0x0, 0x41 },
332 	{ 0x03, 0x00, 0x10, 0x0, 0x40 },
333 	{ 0x03, 0x00, 0x10, 0x0, 0x3e },
334 	{ 0x03, 0x00, 0x10, 0x0, 0x3c },
335 	{ 0x03, 0x00, 0x10, 0x0, 0x3a },
336 	{ 0x03, 0x00, 0x0f, 0x0, 0x3d },
337 	{ 0x03, 0x00, 0x0f, 0x0, 0x3b },
338 	{ 0x03, 0x00, 0x0e, 0x0, 0x3d },
339 	{ 0x03, 0x00, 0x0e, 0x0, 0x3c },
340 	{ 0x03, 0x00, 0x0e, 0x0, 0x3a },
341 	{ 0x03, 0x00, 0x0d, 0x0, 0x3c },
342 	{ 0x03, 0x00, 0x0d, 0x0, 0x3b },
343 	{ 0x03, 0x00, 0x0c, 0x0, 0x3e },
344 	{ 0x03, 0x00, 0x0c, 0x0, 0x3c },
345 	{ 0x03, 0x00, 0x0c, 0x0, 0x3a },
346 	{ 0x03, 0x00, 0x0b, 0x0, 0x3e },
347 	{ 0x03, 0x00, 0x0b, 0x0, 0x3c },
348 	{ 0x03, 0x00, 0x0b, 0x0, 0x3b },
349 	{ 0x03, 0x00, 0x0b, 0x0, 0x39 },
350 	{ 0x03, 0x00, 0x0a, 0x0, 0x3d },
351 	{ 0x03, 0x00, 0x0a, 0x0, 0x3b },
352 	{ 0x03, 0x00, 0x0a, 0x0, 0x39 },
353 	{ 0x03, 0x00, 0x09, 0x0, 0x3e },
354 	{ 0x03, 0x00, 0x09, 0x0, 0x3c },
355 	{ 0x03, 0x00, 0x09, 0x0, 0x3a },
356 	{ 0x03, 0x00, 0x09, 0x0, 0x39 },
357 	{ 0x03, 0x00, 0x08, 0x0, 0x3e },
358 	{ 0x03, 0x00, 0x08, 0x0, 0x3c },
359 	{ 0x03, 0x00, 0x08, 0x0, 0x3a },
360 	{ 0x03, 0x00, 0x08, 0x0, 0x39 },
361 	{ 0x03, 0x00, 0x08, 0x0, 0x37 },
362 	{ 0x03, 0x00, 0x07, 0x0, 0x3d },
363 	{ 0x03, 0x00, 0x07, 0x0, 0x3c },
364 	{ 0x03, 0x00, 0x07, 0x0, 0x3a },
365 	{ 0x03, 0x00, 0x07, 0x0, 0x38 },
366 	{ 0x03, 0x00, 0x07, 0x0, 0x37 },
367 	{ 0x03, 0x00, 0x06, 0x0, 0x3e },
368 	{ 0x03, 0x00, 0x06, 0x0, 0x3c },
369 	{ 0x03, 0x00, 0x06, 0x0, 0x3a },
370 	{ 0x03, 0x00, 0x06, 0x0, 0x39 },
371 	{ 0x03, 0x00, 0x06, 0x0, 0x37 },
372 	{ 0x03, 0x00, 0x06, 0x0, 0x36 },
373 	{ 0x03, 0x00, 0x06, 0x0, 0x34 },
374 	{ 0x03, 0x00, 0x05, 0x0, 0x3d },
375 	{ 0x03, 0x00, 0x05, 0x0, 0x3b },
376 	{ 0x03, 0x00, 0x05, 0x0, 0x39 },
377 	{ 0x03, 0x00, 0x05, 0x0, 0x38 },
378 	{ 0x03, 0x00, 0x05, 0x0, 0x36 },
379 	{ 0x03, 0x00, 0x05, 0x0, 0x35 },
380 	{ 0x03, 0x00, 0x05, 0x0, 0x33 },
381 	{ 0x03, 0x00, 0x04, 0x0, 0x3e },
382 	{ 0x03, 0x00, 0x04, 0x0, 0x3c },
383 	{ 0x03, 0x00, 0x04, 0x0, 0x3a },
384 	{ 0x03, 0x00, 0x04, 0x0, 0x39 },
385 	{ 0x03, 0x00, 0x04, 0x0, 0x37 },
386 	{ 0x03, 0x00, 0x04, 0x0, 0x36 },
387 	{ 0x03, 0x00, 0x04, 0x0, 0x34 },
388 	{ 0x03, 0x00, 0x04, 0x0, 0x33 },
389 	{ 0x03, 0x00, 0x04, 0x0, 0x31 },
390 	{ 0x03, 0x00, 0x04, 0x0, 0x30 },
391 	{ 0x03, 0x00, 0x04, 0x0, 0x2e },
392 	{ 0x03, 0x00, 0x03, 0x0, 0x3c },
393 	{ 0x03, 0x00, 0x03, 0x0, 0x3a },
394 	{ 0x03, 0x00, 0x03, 0x0, 0x39 },
395 	{ 0x03, 0x00, 0x03, 0x0, 0x37 },
396 	{ 0x03, 0x00, 0x03, 0x0, 0x36 },
397 	{ 0x03, 0x00, 0x03, 0x0, 0x34 },
398 	{ 0x03, 0x00, 0x03, 0x0, 0x33 },
399 	{ 0x03, 0x00, 0x03, 0x0, 0x31 },
400 	{ 0x03, 0x00, 0x03, 0x0, 0x30 },
401 	{ 0x03, 0x00, 0x03, 0x0, 0x2e },
402 	{ 0x03, 0x00, 0x03, 0x0, 0x2d },
403 	{ 0x03, 0x00, 0x03, 0x0, 0x2c },
404 	{ 0x03, 0x00, 0x03, 0x0, 0x2b },
405 	{ 0x03, 0x00, 0x03, 0x0, 0x29 },
406 	{ 0x03, 0x00, 0x02, 0x0, 0x3d },
407 	{ 0x03, 0x00, 0x02, 0x0, 0x3b },
408 	{ 0x03, 0x00, 0x02, 0x0, 0x39 },
409 	{ 0x03, 0x00, 0x02, 0x0, 0x38 },
410 	{ 0x03, 0x00, 0x02, 0x0, 0x36 },
411 	{ 0x03, 0x00, 0x02, 0x0, 0x35 },
412 	{ 0x03, 0x00, 0x02, 0x0, 0x33 },
413 	{ 0x03, 0x00, 0x02, 0x0, 0x32 },
414 	{ 0x03, 0x00, 0x02, 0x0, 0x30 },
415 	{ 0x03, 0x00, 0x02, 0x0, 0x2f },
416 	{ 0x03, 0x00, 0x02, 0x0, 0x2e },
417 	{ 0x03, 0x00, 0x02, 0x0, 0x2c },
418 	{ 0x03, 0x00, 0x02, 0x0, 0x2b },
419 	{ 0x03, 0x00, 0x02, 0x0, 0x2a },
420 	{ 0x03, 0x00, 0x02, 0x0, 0x29 },
421 	{ 0x03, 0x00, 0x02, 0x0, 0x27 },
422 	{ 0x03, 0x00, 0x02, 0x0, 0x26 },
423 	{ 0x03, 0x00, 0x02, 0x0, 0x25 },
424 	{ 0x03, 0x00, 0x02, 0x0, 0x24 },
425 	{ 0x03, 0x00, 0x02, 0x0, 0x23 },
426 	{ 0x03, 0x00, 0x02, 0x0, 0x22 },
427 	{ 0x03, 0x00, 0x02, 0x0, 0x21 },
428 	{ 0x03, 0x00, 0x02, 0x0, 0x20 },
429 	{ 0x03, 0x00, 0x01, 0x0, 0x3f },
430 	{ 0x03, 0x00, 0x01, 0x0, 0x3d },
431 	{ 0x03, 0x00, 0x01, 0x0, 0x3b },
432 	{ 0x03, 0x00, 0x01, 0x0, 0x39 },
433 };
434 
435 /**************************************************
436  * SW control.
437  **************************************************/
438 
439 static const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
440 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
441 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
442 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
443 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
444 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
445 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
446 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
447 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
448 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
449 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
450 	0x0002, 0x0008, 0x0004, 0x0001,
451 };
452 
453 /**************************************************
454  * R/W ops.
455  **************************************************/
456 
457 u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset)
458 {
459 	u32 type, value;
460 
461 	type = offset & B43_LCNTAB_TYPEMASK;
462 	offset &= ~B43_LCNTAB_TYPEMASK;
463 	B43_WARN_ON(offset > 0xFFFF);
464 
465 	switch (type) {
466 	case B43_LCNTAB_8BIT:
467 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
468 		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO) & 0xFF;
469 		break;
470 	case B43_LCNTAB_16BIT:
471 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
472 		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
473 		break;
474 	case B43_LCNTAB_32BIT:
475 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
476 		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
477 		value |= (b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI) << 16);
478 		break;
479 	default:
480 		B43_WARN_ON(1);
481 		value = 0;
482 	}
483 
484 	return value;
485 }
486 
487 void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
488 			  unsigned int nr_elements, void *_data)
489 {
490 	u32 type;
491 	u8 *data = _data;
492 	unsigned int i;
493 
494 	type = offset & B43_LCNTAB_TYPEMASK;
495 	offset &= ~B43_LCNTAB_TYPEMASK;
496 	B43_WARN_ON(offset > 0xFFFF);
497 
498 	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
499 
500 	for (i = 0; i < nr_elements; i++) {
501 		switch (type) {
502 		case B43_LCNTAB_8BIT:
503 			*data = b43_phy_read(dev,
504 					     B43_PHY_LCN_TABLE_DATALO) & 0xFF;
505 			data++;
506 			break;
507 		case B43_LCNTAB_16BIT:
508 			*((u16 *)data) = b43_phy_read(dev,
509 						      B43_PHY_LCN_TABLE_DATALO);
510 			data += 2;
511 			break;
512 		case B43_LCNTAB_32BIT:
513 			*((u32 *)data) = b43_phy_read(dev,
514 						B43_PHY_LCN_TABLE_DATALO);
515 			*((u32 *)data) |= (b43_phy_read(dev,
516 					   B43_PHY_LCN_TABLE_DATAHI) << 16);
517 			data += 4;
518 			break;
519 		default:
520 			B43_WARN_ON(1);
521 		}
522 	}
523 }
524 
525 void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value)
526 {
527 	u32 type;
528 
529 	type = offset & B43_LCNTAB_TYPEMASK;
530 	offset &= 0xFFFF;
531 
532 	switch (type) {
533 	case B43_LCNTAB_8BIT:
534 		B43_WARN_ON(value & ~0xFF);
535 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
536 		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
537 		break;
538 	case B43_LCNTAB_16BIT:
539 		B43_WARN_ON(value & ~0xFFFF);
540 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
541 		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
542 		break;
543 	case B43_LCNTAB_32BIT:
544 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
545 		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, value >> 16);
546 		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value & 0xFFFF);
547 		break;
548 	default:
549 		B43_WARN_ON(1);
550 	}
551 
552 	return;
553 }
554 
555 void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset,
556 			   unsigned int nr_elements, const void *_data)
557 {
558 	u32 type, value;
559 	const u8 *data = _data;
560 	unsigned int i;
561 
562 	type = offset & B43_LCNTAB_TYPEMASK;
563 	offset &= ~B43_LCNTAB_TYPEMASK;
564 	B43_WARN_ON(offset > 0xFFFF);
565 
566 	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
567 
568 	for (i = 0; i < nr_elements; i++) {
569 		switch (type) {
570 		case B43_LCNTAB_8BIT:
571 			value = *data;
572 			data++;
573 			B43_WARN_ON(value & ~0xFF);
574 			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
575 			break;
576 		case B43_LCNTAB_16BIT:
577 			value = *((u16 *)data);
578 			data += 2;
579 			B43_WARN_ON(value & ~0xFFFF);
580 			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
581 			break;
582 		case B43_LCNTAB_32BIT:
583 			value = *((u32 *)data);
584 			data += 4;
585 			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI,
586 				      value >> 16);
587 			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO,
588 				      value & 0xFFFF);
589 			break;
590 		default:
591 			B43_WARN_ON(1);
592 		}
593 	}
594 }
595 
596 /**************************************************
597  * Tables ops.
598  **************************************************/
599 
600 #define lcntab_upload(dev, offset, data) do { \
601 		b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
602 	} while (0)
603 static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev)
604 {
605 	lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02);
606 	lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01);
607 	lcntab_upload(dev, B43_LCNTAB32(0x0b, 0), b43_lcntab_0x0b);
608 	lcntab_upload(dev, B43_LCNTAB32(0x0c, 0), b43_lcntab_0x0c);
609 	lcntab_upload(dev, B43_LCNTAB32(0x0d, 0), b43_lcntab_0x0d);
610 	lcntab_upload(dev, B43_LCNTAB16(0x0e, 0), b43_lcntab_0x0e);
611 	lcntab_upload(dev, B43_LCNTAB16(0x0f, 0), b43_lcntab_0x0f);
612 	lcntab_upload(dev, B43_LCNTAB16(0x10, 0), b43_lcntab_0x10);
613 	lcntab_upload(dev, B43_LCNTAB16(0x11, 0), b43_lcntab_0x11);
614 	lcntab_upload(dev, B43_LCNTAB32(0x12, 0), b43_lcntab_0x12);
615 	lcntab_upload(dev, B43_LCNTAB16(0x14, 0), b43_lcntab_0x14);
616 	lcntab_upload(dev, B43_LCNTAB16(0x17, 0), b43_lcntab_0x17);
617 	lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00);
618 	lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18);
619 }
620 
621 static void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
622 			const struct b43_lcntab_tx_gain_tbl_entry *gain_table)
623 {
624 	u32 i;
625 	u32 val;
626 
627 	u16 pa_gain = 0x70;
628 	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM)
629 		pa_gain = 0x10;
630 
631 	for (i = 0; i < B43_LCNTAB_TX_GAIN_SIZE; i++) {
632 		val = ((pa_gain << 24) |
633 		       (gain_table[i].pad << 16) |
634 		       (gain_table[i].pga << 8) |
635 			gain_table[i].gm);
636 		b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0xc0 + i), val);
637 
638 		/* brcmsmac doesn't maskset, we follow newer wl here */
639 		val = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
640 		val &= 0x000fffff;
641 		val |= ((gain_table[i].dac << 28) |
642 			(gain_table[i].bb_mult << 20));
643 		b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x140 + i), val);
644 	}
645 }
646 
647 /* wlc_lcnphy_load_rfpower */
648 static void b43_phy_lcn_load_rfpower(struct b43_wldev *dev)
649 {
650 	u32 bbmult, rfgain;
651 	u8 i;
652 
653 	for (i = 0; i < 128; i++) {
654 		bbmult = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
655 		bbmult >>= 20;
656 		rfgain = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0xc0 + i));
657 
658 		/* TODO: calculate value for 0x240 + i table offset
659 		 * b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), val);
660 		 */
661 	}
662 }
663 
664 /* Not implemented in brcmsmac, noticed in wl in MMIO dump */
665 static void b43_phy_lcn_rewrite_rfpower_table(struct b43_wldev *dev)
666 {
667 	int i;
668 	u32 tmp;
669 	for (i = 0; i < 128; i++) {
670 		tmp = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x240 + i));
671 		b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), tmp);
672 	}
673 }
674 
675 /* wlc_lcnphy_clear_papd_comptable */
676 static void b43_phy_lcn_clean_papd_comp_table(struct b43_wldev *dev)
677 {
678 	u8 i;
679 
680 	for (i = 0; i < 0x80; i++)
681 		b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000);
682 }
683 
684 /* wlc_lcnphy_tbl_init */
685 void b43_phy_lcn_tables_init(struct b43_wldev *dev)
686 {
687 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
688 
689 	b43_phy_lcn_upload_static_tables(dev);
690 
691 	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
692 		if (sprom->boardflags_lo & B43_BFL_FEM)
693 			b43_phy_lcn_load_tx_gain_tab(dev,
694 				b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0);
695 		else
696 			b43err(dev->wl,
697 			       "TX gain table unknown for this card\n");
698 	}
699 
700 	if (sprom->boardflags_lo & B43_BFL_FEM &&
701 	    !(sprom->boardflags_hi & B43_BFH_FEM_BT))
702 		b43_lcntab_write_bulk(dev, B43_LCNTAB16(0xf, 0),
703 			ARRAY_SIZE(b43_lcntab_sw_ctl_4313_epa_rev0),
704 			b43_lcntab_sw_ctl_4313_epa_rev0);
705 	else
706 		b43err(dev->wl, "SW ctl table is unknown for this card\n");
707 
708 	b43_phy_lcn_load_rfpower(dev);
709 	b43_phy_lcn_rewrite_rfpower_table(dev);
710 	b43_phy_lcn_clean_papd_comp_table(dev);
711 }
712