xref: /linux/drivers/staging/vt6656/card.c (revision 2da68a77)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
4  * All rights reserved.
5  *
6  * Purpose: Provide functions to setup NIC operation mode
7  * Functions:
8  *      vnt_set_rspinf - Set RSPINF
9  *      vnt_update_ifs - Update slotTime,SIFS,DIFS, and EIFS
10  *      vnt_update_top_rates - Update BasicTopRate
11  *      vnt_add_basic_rate - Add to BasicRateSet
12  *      vnt_ofdm_min_rate - Check if any OFDM rate is in BasicRateSet
13  *      vnt_get_tsf_offset - Calculate TSFOffset
14  *      vnt_get_current_tsf - Read Current NIC TSF counter
15  *      vnt_get_next_tbtt - Calculate Next Beacon TSF counter
16  *      vnt_reset_next_tbtt - Set NIC Beacon time
17  *      vnt_update_next_tbtt - Sync. NIC Beacon time
18  *      vnt_radio_power_off - Turn Off NIC Radio Power
19  *      vnt_radio_power_on - Turn On NIC Radio Power
20  *
21  * Revision History:
22  *      06-10-2003 Bryan YC Fan:  Re-write codes to support VT3253 spec.
23  *      08-26-2003 Kyle Hsu:      Modify the definition type of dwIoBase.
24  *      09-01-2003 Bryan YC Fan:  Add vnt_update_ifs().
25  *
26  */
27 
28 #include <linux/bitops.h>
29 #include <linux/errno.h>
30 #include "device.h"
31 #include "card.h"
32 #include "baseband.h"
33 #include "mac.h"
34 #include "desc.h"
35 #include "rf.h"
36 #include "power.h"
37 #include "key.h"
38 #include "usbpipe.h"
39 
40 /* const u16 cw_rxbcntsf_off[MAX_RATE] =
41  *   {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3};
42  */
43 
44 static const u16 cw_rxbcntsf_off[MAX_RATE] = {
45 	192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3
46 };
47 
48 int vnt_set_channel(struct vnt_private *priv, u32 connection_channel)
49 {
50 	int ret;
51 
52 	if (connection_channel > CB_MAX_CHANNEL || !connection_channel)
53 		return -EINVAL;
54 
55 	/* clear NAV */
56 	vnt_mac_reg_bits_on(priv, MAC_REG_MACCR, MACCR_CLRNAV);
57 
58 	/* Set Channel[7] = 0 to tell H/W channel is changing now. */
59 	vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL,
60 			     (BIT(7) | BIT(5) | BIT(4)));
61 
62 	ret = vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL,
63 			      connection_channel, 0, 0, NULL);
64 	if (ret)
65 		return ret;
66 
67 	return vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL,
68 				  (u8)(connection_channel | 0x80));
69 }
70 
71 static const u8 vnt_rspinf_b_short_table[] = {
72 	0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x09, 0x00,
73 	0x15, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0b, 0x80
74 };
75 
76 static const u8 vnt_rspinf_b_long_table[] = {
77 	0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00,
78 	0x15, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x80
79 };
80 
81 static const u8 vnt_rspinf_a_table[] = {
82 	0x9b, 0x18, 0x9f, 0x10, 0x9a, 0x0a, 0x9e, 0x08, 0x99,
83 	0x08, 0x9d, 0x04, 0x98, 0x04, 0x9c, 0x04, 0x9c, 0x04
84 };
85 
86 static const u8 vnt_rspinf_gb_table[] = {
87 	0x8b, 0x1e, 0x8f, 0x16, 0x8a, 0x12, 0x8e, 0x0e, 0x89,
88 	0x0e, 0x8d, 0x0a, 0x88, 0x0a, 0x8c, 0x0a, 0x8c, 0x0a
89 };
90 
91 int vnt_set_rspinf(struct vnt_private *priv, u8 bb_type)
92 {
93 	const u8 *data;
94 	u16 len;
95 	int ret;
96 
97 	if (priv->preamble_type) {
98 		data = vnt_rspinf_b_short_table;
99 		len = ARRAY_SIZE(vnt_rspinf_b_short_table);
100 	} else {
101 		data = vnt_rspinf_b_long_table;
102 		len = ARRAY_SIZE(vnt_rspinf_b_long_table);
103 	}
104 
105 	 /* RSPINF_b_1 to RSPINF_b_11 */
106 	ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_B_1,
107 			      MESSAGE_REQUEST_MACREG, len, data);
108 	if (ret)
109 		return ret;
110 
111 	if (bb_type == BB_TYPE_11A) {
112 		data = vnt_rspinf_a_table;
113 		len = ARRAY_SIZE(vnt_rspinf_a_table);
114 	} else {
115 		data = vnt_rspinf_gb_table;
116 		len = ARRAY_SIZE(vnt_rspinf_gb_table);
117 	}
118 
119 	/* RSPINF_a_6 to RSPINF_a_72 */
120 	return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_A_6,
121 			       MESSAGE_REQUEST_MACREG, len, data);
122 }
123 
124 int vnt_update_ifs(struct vnt_private *priv)
125 {
126 	u8 max_min = 0;
127 	u8 data[4];
128 	int ret;
129 
130 	if (priv->packet_type == PK_TYPE_11A) {
131 		priv->slot = C_SLOT_SHORT;
132 		priv->sifs = C_SIFS_A;
133 		priv->difs = C_SIFS_A + 2 * C_SLOT_SHORT;
134 		max_min = 4;
135 	} else {
136 		priv->sifs = C_SIFS_BG;
137 
138 		if (priv->short_slot_time) {
139 			priv->slot = C_SLOT_SHORT;
140 			max_min = 4;
141 		} else {
142 			priv->slot = C_SLOT_LONG;
143 			max_min = 5;
144 		}
145 
146 		priv->difs = C_SIFS_BG + 2 * priv->slot;
147 	}
148 
149 	priv->eifs = C_EIFS;
150 
151 	data[0] = (u8)priv->sifs;
152 	data[1] = (u8)priv->difs;
153 	data[2] = (u8)priv->eifs;
154 	data[3] = (u8)priv->slot;
155 
156 	ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_SIFS,
157 			      MESSAGE_REQUEST_MACREG, 4, &data[0]);
158 	if (ret)
159 		return ret;
160 
161 	max_min |= 0xa0;
162 
163 	return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_CWMAXMIN0,
164 			       MESSAGE_REQUEST_MACREG, 1, &max_min);
165 }
166 
167 void vnt_update_top_rates(struct vnt_private *priv)
168 {
169 	int pos;
170 
171 	pos = fls(priv->basic_rates & GENMASK(RATE_54M, RATE_6M));
172 	priv->top_ofdm_basic_rate = pos ? (pos - 1) : RATE_24M;
173 
174 	pos = fls(priv->basic_rates & GENMASK(RATE_11M, RATE_1M));
175 	priv->top_cck_basic_rate = pos ? (pos - 1) : RATE_1M;
176 }
177 
178 bool vnt_ofdm_min_rate(struct vnt_private *priv)
179 {
180 	return priv->basic_rates & GENMASK(RATE_54M, RATE_6M) ? true : false;
181 }
182 
183 u8 vnt_get_pkt_type(struct vnt_private *priv)
184 {
185 	if (priv->bb_type == BB_TYPE_11A || priv->bb_type == BB_TYPE_11B)
186 		return (u8)priv->bb_type;
187 	else if (vnt_ofdm_min_rate(priv))
188 		return PK_TYPE_11GA;
189 	return PK_TYPE_11GB;
190 }
191 
192 /*
193  * Description: Calculate TSF offset of two TSF input
194  *              Get TSF Offset from RxBCN's TSF and local TSF
195  *
196  * Parameters:
197  *  In:
198  *      rx_rate	- rx rate.
199  *      tsf1	- Rx BCN's TSF
200  *      tsf2	- Local TSF
201  *  Out:
202  *      none
203  *
204  * Return Value: TSF Offset value
205  *
206  */
207 u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2)
208 {
209 	return tsf1 - tsf2 - (u64)cw_rxbcntsf_off[rx_rate % MAX_RATE];
210 }
211 
212 int vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate,
213 		   u64 time_stamp, u64 local_tsf)
214 {
215 	u64 tsf_offset = 0;
216 	u8 data[8];
217 
218 	tsf_offset = vnt_get_tsf_offset(rx_rate, time_stamp, local_tsf);
219 
220 	data[0] = (u8)tsf_offset;
221 	data[1] = (u8)(tsf_offset >> 8);
222 	data[2] = (u8)(tsf_offset >> 16);
223 	data[3] = (u8)(tsf_offset >> 24);
224 	data[4] = (u8)(tsf_offset >> 32);
225 	data[5] = (u8)(tsf_offset >> 40);
226 	data[6] = (u8)(tsf_offset >> 48);
227 	data[7] = (u8)(tsf_offset >> 56);
228 
229 	return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT,
230 			       MESSAGE_REQUEST_TSF, 0, 8, data);
231 }
232 
233 /*
234  * Description: Read NIC TSF counter
235  *              Get local TSF counter
236  *
237  * Parameters:
238  *  In:
239  *	priv		- The adapter to be read
240  *  Out:
241  *	current_tsf	- Current TSF counter
242  *
243  * Return Value: true if success; otherwise false
244  *
245  */
246 bool vnt_get_current_tsf(struct vnt_private *priv, u64 *current_tsf)
247 {
248 	*current_tsf = priv->current_tsf;
249 
250 	return true;
251 }
252 
253 /*
254  * Description: Clear NIC TSF counter
255  *              Clear local TSF counter
256  *
257  * Parameters:
258  *  In:
259  *      priv	- The adapter to be read
260  *
261  * Return Value: true if success; otherwise false
262  *
263  */
264 bool vnt_clear_current_tsf(struct vnt_private *priv)
265 {
266 	vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
267 
268 	priv->current_tsf = 0;
269 
270 	return true;
271 }
272 
273 /*
274  * Description: Read NIC TSF counter
275  *              Get NEXTTBTT from adjusted TSF and Beacon Interval
276  *
277  * Parameters:
278  *  In:
279  *      tsf		- Current TSF counter
280  *      beacon_interval - Beacon Interval
281  *  Out:
282  *      tsf		- Current TSF counter
283  *
284  * Return Value: TSF value of next Beacon
285  *
286  */
287 u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval)
288 {
289 	u32 beacon_int;
290 
291 	beacon_int = beacon_interval * 1024;
292 
293 	/* Next TBTT =
294 	 *	((local_current_TSF / beacon_interval) + 1) * beacon_interval
295 	 */
296 	if (beacon_int) {
297 		do_div(tsf, beacon_int);
298 		tsf += 1;
299 		tsf *= beacon_int;
300 	}
301 
302 	return tsf;
303 }
304 
305 int vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval)
306 {
307 	u64 next_tbtt = 0;
308 	u8 data[8];
309 
310 	vnt_clear_current_tsf(priv);
311 
312 	next_tbtt = vnt_get_next_tbtt(next_tbtt, beacon_interval);
313 
314 	data[0] = (u8)next_tbtt;
315 	data[1] = (u8)(next_tbtt >> 8);
316 	data[2] = (u8)(next_tbtt >> 16);
317 	data[3] = (u8)(next_tbtt >> 24);
318 	data[4] = (u8)(next_tbtt >> 32);
319 	data[5] = (u8)(next_tbtt >> 40);
320 	data[6] = (u8)(next_tbtt >> 48);
321 	data[7] = (u8)(next_tbtt >> 56);
322 
323 	return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT,
324 			       MESSAGE_REQUEST_TBTT, 0, 8, data);
325 }
326 
327 int vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf,
328 			 u16 beacon_interval)
329 {
330 	u8 data[8];
331 	int ret;
332 
333 	tsf = vnt_get_next_tbtt(tsf, beacon_interval);
334 
335 	data[0] = (u8)tsf;
336 	data[1] = (u8)(tsf >> 8);
337 	data[2] = (u8)(tsf >> 16);
338 	data[3] = (u8)(tsf >> 24);
339 	data[4] = (u8)(tsf >> 32);
340 	data[5] = (u8)(tsf >> 40);
341 	data[6] = (u8)(tsf >> 48);
342 	data[7] = (u8)(tsf >> 56);
343 
344 	ret = vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT,
345 			      MESSAGE_REQUEST_TBTT, 0, 8, data);
346 	if (ret)
347 		return ret;
348 
349 	dev_dbg(&priv->usb->dev, "%s TBTT: %8llx\n", __func__, tsf);
350 	return 0;
351 }
352 
353 /*
354  * Description: Turn off Radio power
355  *
356  * Parameters:
357  *  In:
358  *      priv         - The adapter to be turned off
359  *  Out:
360  *      none
361  *
362  * Return Value: true if success; otherwise false
363  *
364  */
365 int vnt_radio_power_off(struct vnt_private *priv)
366 {
367 	int ret = 0;
368 
369 	switch (priv->rf_type) {
370 	case RF_AL2230:
371 	case RF_AL2230S:
372 	case RF_VT3226:
373 	case RF_VT3226D0:
374 		ret = vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL,
375 					   (SOFTPWRCTL_SWPE2 |
376 					    SOFTPWRCTL_SWPE3));
377 		break;
378 	}
379 
380 	if (ret)
381 		goto end;
382 
383 	ret = vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_RXON);
384 	if (ret)
385 		goto end;
386 
387 	ret = vnt_set_deep_sleep(priv);
388 	if (ret)
389 		goto end;
390 
391 	ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD);
392 
393 end:
394 	return ret;
395 }
396 
397 /*
398  * Description: Turn on Radio power
399  *
400  * Parameters:
401  *  In:
402  *      priv         - The adapter to be turned on
403  *  Out:
404  *      none
405  *
406  * Return Value: true if success; otherwise false
407  *
408  */
409 int vnt_radio_power_on(struct vnt_private *priv)
410 {
411 	int ret = 0;
412 
413 	ret = vnt_exit_deep_sleep(priv);
414 	if (ret)
415 		return ret;
416 
417 	ret = vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_RXON);
418 	if (ret)
419 		return ret;
420 
421 	switch (priv->rf_type) {
422 	case RF_AL2230:
423 	case RF_AL2230S:
424 	case RF_VT3226:
425 	case RF_VT3226D0:
426 		ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL,
427 					  (SOFTPWRCTL_SWPE2 |
428 					   SOFTPWRCTL_SWPE3));
429 		if (ret)
430 			return ret;
431 	}
432 
433 	return vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD);
434 }
435 
436 int vnt_set_bss_mode(struct vnt_private *priv)
437 {
438 	int ret;
439 	unsigned char type = priv->bb_type;
440 	unsigned char data = 0;
441 	unsigned char bb_vga_2_3 = 0x00;
442 
443 	ret = vnt_mac_set_bb_type(priv, type);
444 	if (ret)
445 		return ret;
446 
447 	priv->packet_type = vnt_get_pkt_type(priv);
448 
449 	if (priv->bb_type == BB_TYPE_11A) {
450 		data = 0x03;
451 		bb_vga_2_3 = 0x10;
452 	} else if (priv->bb_type == BB_TYPE_11B) {
453 		data = 0x02;
454 	} else if (priv->bb_type == BB_TYPE_11G) {
455 		data = 0x08;
456 	}
457 
458 	if (data) {
459 		ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG,
460 					 0x88, data);
461 		if (ret)
462 			return ret;
463 	}
464 
465 	ret = vnt_update_ifs(priv);
466 	if (ret)
467 		return ret;
468 
469 	ret = vnt_set_rspinf(priv, priv->bb_type);
470 	if (ret)
471 		return ret;
472 
473 	priv->bb_vga[2] = bb_vga_2_3;
474 	priv->bb_vga[3] = bb_vga_2_3;
475 
476 	return vnt_set_vga_gain_offset(priv, priv->bb_vga[0]);
477 }
478