source: mainline/uspace/drv/nic/ar9271/hw.c@ 659ebd86

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 659ebd86 was 8a64320e, checked in by Martin Decky <martin@…>, 10 years ago

pre-merge coding style cleanup and code review

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