source: mainline/uspace/drv/nic/ar9271/hw.c@ 09044cb

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 09044cb was 053fc2b, checked in by Jan Kolarik <kolarik@…>, 10 years ago

Locking, correctly disconnecting device, sending DHCP address discover after connecting to WiFi network

  • Property mode set to 100644
File size: 16.1 KB
Line 
1/*
2 * Copyright (c) 2015 Jan Kolarik
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 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file hw.c
30 *
31 * AR9271 hardware related functions implementation.
32 *
33 */
34
35#include <macros.h>
36#include <usb/debug.h>
37#include <unistd.h>
38#include <nic.h>
39#include <ieee80211.h>
40
41#include "hw.h"
42#include "wmi.h"
43
44/**
45 * Try to wait for register value repeatedly until timeout is reached.
46 *
47 * @param ar9271 Device structure.
48 * @param offset Registry offset (address) to be read.
49 * @param mask Mask to apply on read result.
50 * @param value Required value we are waiting for.
51 *
52 * @return EOK if succeed, ETIMEOUT on timeout, negative error code otherwise.
53 */
54static int hw_read_wait(ar9271_t *ar9271, uint32_t offset, uint32_t mask,
55 uint32_t value)
56{
57 uint32_t result;
58
59 for(size_t i = 0; i < HW_WAIT_LOOPS; i++) {
60 udelay(HW_WAIT_TIME_US);
61
62 wmi_reg_read(ar9271->htc_device, offset, &result);
63 if((result & mask) == value) {
64 return EOK;
65 }
66 }
67
68 return ETIMEOUT;
69}
70
71static int hw_reset_power_on(ar9271_t *ar9271)
72{
73 wmi_reg_t buffer[] = {
74 {
75 .offset = AR9271_RTC_FORCE_WAKE,
76 .value = AR9271_RTC_FORCE_WAKE_ENABLE |
77 AR9271_RTC_FORCE_WAKE_ON_INT
78 },
79 {
80 .offset = AR9271_RC,
81 .value = AR9271_RC_AHB
82 },
83 {
84 .offset = AR9271_RTC_RESET,
85 .value = 0
86 }
87 };
88
89 wmi_reg_buffer_write(ar9271->htc_device, buffer,
90 sizeof(buffer) / sizeof(wmi_reg_t));
91
92 udelay(2);
93
94 wmi_reg_write(ar9271->htc_device, AR9271_RC, 0);
95 wmi_reg_write(ar9271->htc_device, AR9271_RTC_RESET, 1);
96
97 int rc = hw_read_wait(ar9271,
98 AR9271_RTC_STATUS,
99 AR9271_RTC_STATUS_MASK,
100 AR9271_RTC_STATUS_ON);
101 if(rc != EOK) {
102 usb_log_error("Failed to wait for RTC wake up register.\n");
103 return rc;
104 }
105
106 return EOK;
107}
108
109static int hw_set_reset(ar9271_t *ar9271, bool cold)
110{
111 uint32_t reset_value = AR9271_RTC_RC_MAC_WARM;
112
113 if(cold) {
114 reset_value |= AR9271_RTC_RC_MAC_COLD;
115 }
116
117 wmi_reg_t buffer[] = {
118 {
119 .offset = AR9271_RTC_FORCE_WAKE,
120 .value = AR9271_RTC_FORCE_WAKE_ENABLE |
121 AR9271_RTC_FORCE_WAKE_ON_INT
122 },
123 {
124 .offset = AR9271_RC,
125 .value = AR9271_RC_AHB
126 },
127 {
128 .offset = AR9271_RTC_RC,
129 .value = reset_value
130 }
131 };
132
133 wmi_reg_buffer_write(ar9271->htc_device, buffer,
134 sizeof(buffer) / sizeof(wmi_reg_t));
135
136 udelay(100);
137
138 wmi_reg_write(ar9271->htc_device, AR9271_RTC_RC, 0);
139
140 int rc = hw_read_wait(ar9271, AR9271_RTC_RC, AR9271_RTC_RC_MASK, 0);
141 if(rc != EOK) {
142 usb_log_error("Failed to wait for RTC RC register.\n");
143 return rc;
144 }
145
146 wmi_reg_write(ar9271->htc_device, AR9271_RC, 0);
147 wmi_reg_clear_bit(ar9271->htc_device, AR9271_STATION_ID1,
148 AR9271_STATION_ID1_POWER_SAVING);
149
150 return EOK;
151}
152
153static int hw_addr_init(ar9271_t *ar9271)
154{
155 uint32_t value;
156 nic_address_t ar9271_address;
157
158 for(int i = 0; i < 3; i++) {
159 wmi_reg_read(ar9271->htc_device,
160 AR9271_EEPROM_MAC_ADDR_START + i*4,
161 &value);
162
163 uint16_t two_bytes = uint16_t_be2host(value);
164 ar9271_address.address[2*i] = two_bytes >> 8;
165 ar9271_address.address[2*i+1] = two_bytes & 0xff;
166 }
167
168 nic_t *nic = nic_get_from_ddf_dev(ar9271->ddf_dev);
169
170 int rc = nic_report_address(nic, &ar9271_address);
171 if(rc != EOK) {
172 usb_log_error("Failed to report NIC HW address.\n");
173 return rc;
174 }
175
176 return EOK;
177}
178
179static int hw_gpio_set_output(ar9271_t *ar9271, uint32_t gpio, uint32_t type)
180{
181 uint32_t address, gpio_shift, temp;
182
183 if(gpio > 11) {
184 address = AR9271_GPIO_OUT_MUX3;
185 } else if(gpio > 5) {
186 address = AR9271_GPIO_OUT_MUX2;
187 } else {
188 address = AR9271_GPIO_OUT_MUX1;
189 }
190
191 gpio_shift = (gpio % 6) * 5;
192
193 wmi_reg_read(ar9271->htc_device, address, &temp);
194
195 temp = ((temp & 0x1F0) << 1) | (temp & ~0x1F0);
196 temp &= ~(0x1f << gpio_shift);
197 temp |= (type << gpio_shift);
198
199 wmi_reg_write(ar9271->htc_device, address, temp);
200
201 gpio_shift = 2 * gpio;
202
203 wmi_reg_set_clear_bit(ar9271->htc_device, AR9271_GPIO_OE_OUT,
204 AR9271_GPIO_OE_OUT_ALWAYS << gpio_shift,
205 AR9271_GPIO_OE_OUT_ALWAYS << gpio_shift);
206
207 return EOK;
208}
209
210static int hw_gpio_set_value(ar9271_t *ar9271, uint32_t gpio, uint32_t value)
211{
212 wmi_reg_set_clear_bit(ar9271->htc_device, AR9271_GPIO_IN_OUT,
213 (~value & 1) << gpio, 1 << gpio);
214 return EOK;
215}
216
217/**
218 * Hardware init procedure of AR9271 device.
219 *
220 * @param ar9271 Device structure.
221 *
222 * @return EOK if succeed, negative error code otherwise.
223 */
224static int hw_init_proc(ar9271_t *ar9271)
225{
226 int rc = hw_reset_power_on(ar9271);
227 if(rc != EOK) {
228 usb_log_error("Failed to HW reset power on.\n");
229 return rc;
230 }
231
232 rc = hw_set_reset(ar9271, false);
233 if(rc != EOK) {
234 usb_log_error("Failed to HW warm reset.\n");
235 return rc;
236 }
237
238 rc = hw_addr_init(ar9271);
239 if(rc != EOK) {
240 usb_log_error("Failed to init HW addr.\n");
241 return rc;
242 }
243
244 return EOK;
245}
246
247static int hw_init_led(ar9271_t *ar9271)
248{
249 int rc = hw_gpio_set_output(ar9271, AR9271_LED_PIN,
250 AR9271_GPIO_OUT_MUX_AS_OUT);
251 if(rc != EOK) {
252 usb_log_error("Failed to set led GPIO to output.\n");
253 return rc;
254 }
255
256 rc = hw_gpio_set_value(ar9271, AR9271_LED_PIN, 0);
257 if(rc != EOK) {
258 usb_log_error("Failed to init bring up GPIO led.\n");
259 return rc;
260 }
261
262 return EOK;
263}
264
265static int hw_activate_phy(ar9271_t *ar9271)
266{
267 wmi_reg_write(ar9271->htc_device, AR9271_PHY_ACTIVE, 1);
268 udelay(1000);
269
270 return EOK;
271}
272
273static int hw_set_operating_mode(ar9271_t *ar9271,
274 ieee80211_operating_mode_t op_mode)
275{
276 uint32_t set_bit = 0x10000000;
277
278 switch(op_mode) {
279 case IEEE80211_OPMODE_ADHOC:
280 set_bit |= AR9271_OPMODE_ADHOC_MASK;
281 wmi_reg_set_bit(ar9271->htc_device, AR9271_CONFIG,
282 AR9271_CONFIG_ADHOC);
283 break;
284 case IEEE80211_OPMODE_MESH:
285 case IEEE80211_OPMODE_AP:
286 set_bit |= AR9271_OPMODE_STATION_AP_MASK;
287 case IEEE80211_OPMODE_STATION:
288 wmi_reg_clear_bit(ar9271->htc_device, AR9271_CONFIG,
289 AR9271_CONFIG_ADHOC);
290 }
291
292 wmi_reg_set_clear_bit(ar9271->htc_device, AR9271_STATION_ID1,
293 set_bit,
294 AR9271_OPMODE_STATION_AP_MASK | AR9271_OPMODE_ADHOC_MASK);
295
296 ieee80211_report_current_op_mode(ar9271->ieee80211_dev, op_mode);
297
298 return EOK;
299}
300
301static int hw_reset_operating_mode(ar9271_t *ar9271)
302{
303 int rc = hw_set_operating_mode(ar9271, IEEE80211_OPMODE_STATION);
304 if(rc != EOK) {
305 usb_log_error("Failed to set opmode to station.\n");
306 return rc;
307 }
308
309 return EOK;
310}
311
312static int hw_noise_floor_calibration(ar9271_t *ar9271)
313{
314 uint32_t value;
315 wmi_reg_read(ar9271->htc_device, AR9271_PHY_CAL, &value);
316 value &= 0xFFFFFE00;
317 value |= (((uint32_t) AR9271_CALIB_NOMINAL_VALUE_2GHZ << 1) & 0x1FF);
318 wmi_reg_write(ar9271->htc_device, AR9271_PHY_CAL, value);
319
320 wmi_reg_clear_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
321 AR9271_AGC_CONTROL_NF_CALIB_EN);
322
323 wmi_reg_clear_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
324 AR9271_AGC_CONTROL_NF_NOT_UPDATE);
325
326 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
327 AR9271_AGC_CONTROL_NF_CALIB);
328
329 int rc = hw_read_wait(ar9271, AR9271_AGC_CONTROL,
330 AR9271_AGC_CONTROL_NF_CALIB, 0);
331 if(rc != EOK) {
332 usb_log_error("Failed to wait for NF calibration.\n");
333 return rc;
334 }
335
336 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
337 AR9271_AGC_CONTROL_NF_CALIB_EN);
338
339 wmi_reg_clear_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
340 AR9271_AGC_CONTROL_NF_NOT_UPDATE);
341
342 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
343 AR9271_AGC_CONTROL_NF_CALIB);
344
345 return EOK;
346}
347
348static int hw_set_freq(ar9271_t *ar9271, uint16_t freq)
349{
350 /* Not supported channel frequency. */
351 if(freq < IEEE80211_FIRST_FREQ || freq > IEEE80211_MAX_FREQ) {
352 return EINVAL;
353 }
354
355 /* Not supported channel frequency. */
356 if((freq - IEEE80211_FIRST_FREQ) % IEEE80211_CHANNEL_GAP != 0) {
357 return EINVAL;
358 }
359
360 uint32_t tx_control;
361 wmi_reg_read(ar9271->htc_device, AR9271_PHY_CCK_TX_CTRL, &tx_control);
362 wmi_reg_write(ar9271->htc_device, AR9271_PHY_CCK_TX_CTRL,
363 tx_control & ~AR9271_PHY_CCK_TX_CTRL_JAPAN);
364
365 /* Some magic here. */
366 uint32_t synth_ctl;
367 wmi_reg_read(ar9271->htc_device, AR9271_PHY_SYNTH_CONTROL, &synth_ctl);
368 synth_ctl &= 0xC0000000;
369 uint32_t channel_select = (freq * 0x10000) / 15;
370 synth_ctl = synth_ctl | (1 << 29) | (1 << 28) | channel_select;
371
372 wmi_reg_write(ar9271->htc_device, AR9271_PHY_SYNTH_CONTROL, synth_ctl);
373
374 ieee80211_report_current_freq(ar9271->ieee80211_dev, freq);
375
376 return EOK;
377}
378
379int hw_freq_switch(ar9271_t *ar9271, uint16_t freq)
380{
381 wmi_reg_write(ar9271->htc_device, AR9271_PHY_RFBUS_KILL, 0x1);
382
383 int rc = hw_read_wait(ar9271, AR9271_PHY_RFBUS_GRANT, 0x1, 0x1);
384 if(rc != EOK) {
385 usb_log_error("Failed to kill RF bus.\n");
386 return rc;
387 }
388
389 rc = hw_set_freq(ar9271, freq);
390 if(rc != EOK) {
391 usb_log_error("Failed to HW set frequency.\n");
392 return rc;
393 }
394
395 rc = hw_activate_phy(ar9271);
396 if(rc != EOK) {
397 usb_log_error("Failed to activate physical layer.\n");
398 return rc;
399 }
400
401 udelay(1000);
402 wmi_reg_write(ar9271->htc_device, AR9271_PHY_RFBUS_KILL, 0x0);
403
404 rc = hw_noise_floor_calibration(ar9271);
405 if(rc != EOK) {
406 usb_log_error("Failed to do NF calibration.\n");
407 return rc;
408 }
409
410 return EOK;
411}
412
413int hw_set_rx_filter(ar9271_t *ar9271, bool assoc)
414{
415 uint32_t filter_bits;
416
417 uint32_t additional_bits = 0;
418
419 if(assoc) {
420 additional_bits |= AR9271_RX_FILTER_MYBEACON;
421 } else {
422 additional_bits |= AR9271_RX_FILTER_BEACON;
423 }
424
425 filter_bits = AR9271_RX_FILTER_UNI | AR9271_RX_FILTER_MULTI |
426 AR9271_RX_FILTER_BROAD | additional_bits;
427
428 wmi_reg_write(ar9271->htc_device, AR9271_RX_FILTER, filter_bits);
429
430 return EOK;
431}
432
433int hw_set_bssid(ar9271_t *ar9271)
434{
435 ieee80211_dev_t *ieee80211_dev = ar9271->ieee80211_dev;
436
437 nic_address_t bssid;
438 ieee80211_query_bssid(ieee80211_dev, &bssid);
439
440 uint32_t *first_4bytes = (uint32_t *) &bssid.address;
441 uint16_t *last_2bytes = (uint16_t *) &bssid.address[4];
442
443 wmi_reg_write(ar9271->htc_device, AR9271_BSSID0,
444 uint32_t_le2host(*first_4bytes));
445
446 wmi_reg_write(ar9271->htc_device, AR9271_BSSID1,
447 uint16_t_le2host(*last_2bytes) |
448 ((ieee80211_get_aid(ieee80211_dev) & 0x3FFF) << 16));
449
450 return EOK;
451}
452
453int hw_rx_init(ar9271_t *ar9271)
454{
455 wmi_reg_write(ar9271->htc_device, AR9271_COMMAND,
456 AR9271_COMMAND_RX_ENABLE);
457
458 int rc = hw_set_rx_filter(ar9271, false);
459 if(rc != EOK) {
460 usb_log_error("Failed to set RX filtering.\n");
461 return rc;
462 }
463
464 wmi_reg_write(ar9271->htc_device, AR9271_MULTICAST_FILTER1, ~0);
465 wmi_reg_write(ar9271->htc_device, AR9271_MULTICAST_FILTER2, ~0);
466
467 /* Disable RX blocking. */
468 wmi_reg_clear_bit(ar9271->htc_device, AR9271_DIAG, (0x20 | 0x02000000));
469
470 return EOK;
471}
472
473static int hw_init_pll(ar9271_t *ar9271)
474{
475 uint32_t pll;
476
477 /* Some magic here (set for 2GHz channels). But VERY important :-) */
478 pll = (0x5 << 10) | 0x2C;
479
480 wmi_reg_write(ar9271->htc_device, AR9271_RTC_PLL_CONTROL, pll);
481
482 wmi_reg_write(ar9271->htc_device, AR9271_RTC_SLEEP_CLOCK,
483 AR9271_RTC_SLEEP_CLOCK_FORCE_DERIVED);
484 wmi_reg_set_bit(ar9271->htc_device, AR9271_RTC_FORCE_WAKE,
485 AR9271_RTC_FORCE_WAKE_ENABLE);
486
487 return EOK;
488}
489
490static void hw_set_init_values(ar9271_t *ar9271)
491{
492 uint32_t reg_offset, reg_value;
493
494 int size = ARRAY_SIZE(ar9271_2g_mode_array);
495
496 for(int i = 0; i < size; i++) {
497 reg_offset = ar9271_2g_mode_array[i][0];
498 reg_value = ar9271_2g_mode_array[i][1];
499 wmi_reg_write(ar9271->htc_device, reg_offset, reg_value);
500 }
501
502 size = ARRAY_SIZE(ar9271_2g_tx_array);
503
504 for(int i = 0; i < size; i++) {
505 reg_offset = ar9271_2g_tx_array[i][0];
506 reg_value = ar9271_2g_tx_array[i][1];
507 wmi_reg_write(ar9271->htc_device, reg_offset, reg_value);
508 }
509
510 size = ARRAY_SIZE(ar9271_init_array);
511
512 for(int i = 0; i < size; i++) {
513 reg_offset = ar9271_init_array[i][0];
514 reg_value = ar9271_init_array[i][1];
515 wmi_reg_write(ar9271->htc_device, reg_offset, reg_value);
516 }
517}
518
519static int hw_calibration(ar9271_t *ar9271)
520{
521 wmi_reg_set_bit(ar9271->htc_device, AR9271_CARRIER_LEAK_CONTROL,
522 AR9271_CARRIER_LEAK_CALIB);
523 wmi_reg_clear_bit(ar9271->htc_device, AR9271_ADC_CONTROL,
524 AR9271_ADC_CONTROL_OFF_PWDADC);
525 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
526 AR9271_AGC_CONTROL_TX_CALIB);
527 wmi_reg_set_bit(ar9271->htc_device, AR9271_PHY_TPCRG1,
528 AR9271_PHY_TPCRG1_PD_CALIB);
529 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
530 AR9271_AGC_CONTROL_CALIB);
531
532 int rc = hw_read_wait(ar9271, AR9271_AGC_CONTROL,
533 AR9271_AGC_CONTROL_CALIB, 0);
534 if(rc != EOK) {
535 usb_log_error("Failed to wait on calibrate completion.\n");
536 return rc;
537 }
538
539 wmi_reg_set_bit(ar9271->htc_device, AR9271_ADC_CONTROL,
540 AR9271_ADC_CONTROL_OFF_PWDADC);
541 wmi_reg_clear_bit(ar9271->htc_device, AR9271_CARRIER_LEAK_CONTROL,
542 AR9271_CARRIER_LEAK_CALIB);
543 wmi_reg_clear_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
544 AR9271_AGC_CONTROL_TX_CALIB);
545
546 return EOK;
547}
548
549int hw_reset(ar9271_t *ar9271)
550{
551 /* Set physical layer as deactivated. */
552 wmi_reg_write(ar9271->htc_device, AR9271_PHY_ACTIVE, 0);
553
554 if(ar9271->starting_up) {
555 wmi_reg_write(ar9271->htc_device,
556 AR9271_RESET_POWER_DOWN_CONTROL,
557 AR9271_RADIO_RF_RESET);
558
559 udelay(50);
560 }
561
562 /* Cold reset when RX is enabled. */
563 uint32_t config_reg;
564 wmi_reg_read(ar9271->htc_device, AR9271_COMMAND, &config_reg);
565 if(config_reg & AR9271_COMMAND_RX_ENABLE) {
566 hw_set_reset(ar9271, true);
567 }
568
569 int rc = hw_init_pll(ar9271);
570 if(rc != EOK) {
571 usb_log_error("Failed to init PLL.\n");
572 return rc;
573 }
574
575 udelay(500);
576
577 wmi_reg_write(ar9271->htc_device, AR9271_CLOCK_CONTROL,
578 AR9271_MAX_CPU_CLOCK);
579
580 udelay(100);
581
582 if(ar9271->starting_up) {
583 wmi_reg_write(ar9271->htc_device,
584 AR9271_RESET_POWER_DOWN_CONTROL,
585 AR9271_GATE_MAC_CONTROL);
586
587 udelay(50);
588 }
589
590 hw_set_init_values(ar9271);
591
592 /* Set physical layer mode. */
593 wmi_reg_write(ar9271->htc_device, AR9271_PHY_MODE,
594 AR9271_PHY_MODE_DYNAMIC);
595
596 /* Reset device operating mode. */
597 rc = hw_reset_operating_mode(ar9271);
598 if(rc != EOK) {
599 usb_log_error("Failed to reset operating mode.\n");
600 return rc;
601 }
602
603 /* Set initial channel frequency. */
604 rc = hw_set_freq(ar9271, IEEE80211_FIRST_FREQ);
605 if(rc != EOK) {
606 usb_log_error("Failed to set channel.\n");
607 return rc;
608 }
609
610 /* Initialize transmission queues. */
611 for(int i = 0; i < AR9271_QUEUES_COUNT; i++) {
612 wmi_reg_write(ar9271->htc_device,
613 AR9271_QUEUE_BASE_MASK + (i << 2),
614 1 << i);
615 }
616
617 /* Activate physical layer. */
618 rc = hw_activate_phy(ar9271);
619 if(rc != EOK) {
620 usb_log_error("Failed to activate physical layer.\n");
621 return rc;
622 }
623
624 /* Calibration. */
625 rc = hw_calibration(ar9271);
626 if(rc != EOK) {
627 usb_log_error("Failed to calibrate device.\n");
628 return rc;
629 }
630
631 rc = hw_noise_floor_calibration(ar9271);
632 if(rc != EOK) {
633 usb_log_error("Failed to calibrate noise floor.\n");
634 return rc;
635 }
636
637 /* Byteswap TX and RX data buffer words. */
638 wmi_reg_write(ar9271->htc_device, AR9271_CONFIG, 0xA);
639
640 return EOK;
641}
642
643/**
644 * Initialize hardware of AR9271 device.
645 *
646 * @param ar9271 Device structure.
647 *
648 * @return EOK if succeed, negative error code otherwise.
649 */
650int hw_init(ar9271_t *ar9271)
651{
652 int rc = hw_init_proc(ar9271);
653 if(rc != EOK) {
654 usb_log_error("Failed to HW reset device.\n");
655 return rc;
656 }
657
658 rc = hw_init_led(ar9271);
659 if(rc != EOK) {
660 usb_log_error("Failed to HW init led.\n");
661 return rc;
662 }
663
664 usb_log_info("HW initialization finished successfully.\n");
665
666 return EOK;
667}
Note: See TracBrowser for help on using the repository browser.