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

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

pre-merge coding style cleanup and code review

  • Property mode set to 100644
File size: 16.2 KB
RevLine 
[59fa7ab]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
[8a64320e]43/** Try to wait for register value repeatedly until timeout is reached.
44 *
[59fa7ab]45 * @param ar9271 Device structure.
46 * @param offset Registry offset (address) to be read.
[8a64320e]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 *
[59fa7ab]53 */
54static int hw_read_wait(ar9271_t *ar9271, uint32_t offset, uint32_t mask,
[8a64320e]55 uint32_t value)
[59fa7ab]56{
[8a64320e]57 for (size_t i = 0; i < HW_WAIT_LOOPS; i++) {
[59fa7ab]58 udelay(HW_WAIT_TIME_US);
[8a64320e]59
60 uint32_t result;
[59fa7ab]61 wmi_reg_read(ar9271->htc_device, offset, &result);
[8a64320e]62 if ((result & mask) == value)
[59fa7ab]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,
[8a64320e]74 .value = AR9271_RTC_FORCE_WAKE_ENABLE |
75 AR9271_RTC_FORCE_WAKE_ON_INT
[59fa7ab]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,
[8a64320e]88 sizeof(buffer) / sizeof(wmi_reg_t));
[59fa7ab]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
[8a64320e]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) {
[59fa7ab]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
[8a64320e]111 if (cold)
[59fa7ab]112 reset_value |= AR9271_RTC_RC_MAC_COLD;
113
114 wmi_reg_t buffer[] = {
115 {
116 .offset = AR9271_RTC_FORCE_WAKE,
[8a64320e]117 .value = AR9271_RTC_FORCE_WAKE_ENABLE |
118 AR9271_RTC_FORCE_WAKE_ON_INT
[59fa7ab]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
[8a64320e]130 wmi_reg_buffer_write(ar9271->htc_device, buffer,
131 sizeof(buffer) / sizeof(wmi_reg_t));
[59fa7ab]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);
[8a64320e]138 if (rc != EOK) {
[59fa7ab]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);
[8a64320e]144 wmi_reg_clear_bit(ar9271->htc_device, AR9271_STATION_ID1,
145 AR9271_STATION_ID1_POWER_SAVING);
[59fa7ab]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
[8a64320e]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);
[59fa7ab]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);
[8a64320e]167 if (rc != EOK) {
[59fa7ab]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{
[8a64320e]177 uint32_t address;
[59fa7ab]178
[8a64320e]179 if (gpio > 11)
[59fa7ab]180 address = AR9271_GPIO_OUT_MUX3;
[8a64320e]181 else if (gpio > 5)
[59fa7ab]182 address = AR9271_GPIO_OUT_MUX2;
[8a64320e]183 else
[59fa7ab]184 address = AR9271_GPIO_OUT_MUX1;
185
[8a64320e]186 uint32_t gpio_shift = (gpio % 6) * 5;
[59fa7ab]187
[8a64320e]188 uint32_t temp;
[59fa7ab]189 wmi_reg_read(ar9271->htc_device, address, &temp);
[8a64320e]190
191 temp = ((temp & 0x1f0) << 1) | (temp & ~0x1f0);
[59fa7ab]192 temp &= ~(0x1f << gpio_shift);
193 temp |= (type << gpio_shift);
[8a64320e]194
[59fa7ab]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,
[8a64320e]200 AR9271_GPIO_OE_OUT_ALWAYS << gpio_shift,
201 AR9271_GPIO_OE_OUT_ALWAYS << gpio_shift);
[59fa7ab]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,
[8a64320e]209 (~value & 1) << gpio, 1 << gpio);
[59fa7ab]210 return EOK;
211}
212
[8a64320e]213/**Hardware init procedure of AR9271 device.
214 *
[59fa7ab]215 * @param ar9271 Device structure.
[8a64320e]216 *
[59fa7ab]217 * @return EOK if succeed, negative error code otherwise.
[8a64320e]218 *
[59fa7ab]219 */
220static int hw_init_proc(ar9271_t *ar9271)
221{
222 int rc = hw_reset_power_on(ar9271);
[8a64320e]223 if (rc != EOK) {
[59fa7ab]224 usb_log_error("Failed to HW reset power on.\n");
225 return rc;
226 }
227
228 rc = hw_set_reset(ar9271, false);
[8a64320e]229 if (rc != EOK) {
[59fa7ab]230 usb_log_error("Failed to HW warm reset.\n");
231 return rc;
232 }
233
234 rc = hw_addr_init(ar9271);
[8a64320e]235 if (rc != EOK) {
[59fa7ab]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{
[8a64320e]245 int rc = hw_gpio_set_output(ar9271, AR9271_LED_PIN,
246 AR9271_GPIO_OUT_MUX_AS_OUT);
247 if (rc != EOK) {
[59fa7ab]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);
[8a64320e]253 if (rc != EOK) {
[59fa7ab]254 usb_log_error("Failed to init bring up GPIO led.\n");
255 return rc;
256 }
257
258 return EOK;
259}
260
[1dcc0b9]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
[8a64320e]269static int hw_set_operating_mode(ar9271_t *ar9271,
270 ieee80211_operating_mode_t op_mode)
[59fa7ab]271{
272 uint32_t set_bit = 0x10000000;
273
274 switch(op_mode) {
[8a64320e]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);
[59fa7ab]286 }
287
288 wmi_reg_set_clear_bit(ar9271->htc_device, AR9271_STATION_ID1,
[8a64320e]289 set_bit, AR9271_OPMODE_STATION_AP_MASK | AR9271_OPMODE_ADHOC_MASK);
[59fa7ab]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);
[8a64320e]299 if (rc != EOK) {
[59fa7ab]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{
[1dcc0b9]309 uint32_t value;
310 wmi_reg_read(ar9271->htc_device, AR9271_PHY_CAL, &value);
[8a64320e]311
312 value &= 0xfffffe00;
313 value |= (((uint32_t) AR9271_CALIB_NOMINAL_VALUE_2GHZ << 1) & 0x1ff);
314
[1dcc0b9]315 wmi_reg_write(ar9271->htc_device, AR9271_PHY_CAL, value);
316
[8a64320e]317 wmi_reg_clear_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
318 AR9271_AGC_CONTROL_NF_CALIB_EN);
[1dcc0b9]319
[8a64320e]320 wmi_reg_clear_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
321 AR9271_AGC_CONTROL_NF_NOT_UPDATE);
[1dcc0b9]322
[8a64320e]323 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
324 AR9271_AGC_CONTROL_NF_CALIB);
[1dcc0b9]325
[8a64320e]326 int rc = hw_read_wait(ar9271, AR9271_AGC_CONTROL,
327 AR9271_AGC_CONTROL_NF_CALIB, 0);
328 if (rc != EOK) {
[1dcc0b9]329 usb_log_error("Failed to wait for NF calibration.\n");
330 return rc;
331 }
332
[8a64320e]333 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
334 AR9271_AGC_CONTROL_NF_CALIB_EN);
[59fa7ab]335
[8a64320e]336 wmi_reg_clear_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
337 AR9271_AGC_CONTROL_NF_NOT_UPDATE);
[59fa7ab]338
[8a64320e]339 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
340 AR9271_AGC_CONTROL_NF_CALIB);
[59fa7ab]341
342 return EOK;
343}
344
345static int hw_set_freq(ar9271_t *ar9271, uint16_t freq)
346{
347 /* Not supported channel frequency. */
[8a64320e]348 if ((freq < IEEE80211_FIRST_FREQ) || (freq > IEEE80211_MAX_FREQ))
[59fa7ab]349 return EINVAL;
350
351 /* Not supported channel frequency. */
[8a64320e]352 if ((freq - IEEE80211_FIRST_FREQ) % IEEE80211_CHANNEL_GAP != 0)
[59fa7ab]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,
[8a64320e]358 tx_control & ~AR9271_PHY_CCK_TX_CTRL_JAPAN);
[59fa7ab]359
360 /* Some magic here. */
361 uint32_t synth_ctl;
362 wmi_reg_read(ar9271->htc_device, AR9271_PHY_SYNTH_CONTROL, &synth_ctl);
[8a64320e]363 synth_ctl &= 0xc0000000;
[59fa7ab]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);
[8a64320e]379 if (rc != EOK) {
[59fa7ab]380 usb_log_error("Failed to kill RF bus.\n");
381 return rc;
382 }
383
384 rc = hw_set_freq(ar9271, freq);
[8a64320e]385 if (rc != EOK) {
[59fa7ab]386 usb_log_error("Failed to HW set frequency.\n");
387 return rc;
388 }
389
[1dcc0b9]390 rc = hw_activate_phy(ar9271);
[8a64320e]391 if (rc != EOK) {
[1dcc0b9]392 usb_log_error("Failed to activate physical layer.\n");
393 return rc;
394 }
395
[59fa7ab]396 udelay(1000);
397 wmi_reg_write(ar9271->htc_device, AR9271_PHY_RFBUS_KILL, 0x0);
398
399 rc = hw_noise_floor_calibration(ar9271);
[8a64320e]400 if (rc != EOK) {
[59fa7ab]401 usb_log_error("Failed to do NF calibration.\n");
402 return rc;
403 }
404
405 return EOK;
406}
407
[1dcc0b9]408int hw_set_rx_filter(ar9271_t *ar9271, bool assoc)
[59fa7ab]409{
[1dcc0b9]410 uint32_t additional_bits = 0;
411
[8a64320e]412 if (assoc)
[1dcc0b9]413 additional_bits |= AR9271_RX_FILTER_MYBEACON;
[8a64320e]414 else
[1dcc0b9]415 additional_bits |= AR9271_RX_FILTER_BEACON;
[59fa7ab]416
[8a64320e]417 uint32_t filter_bits = AR9271_RX_FILTER_UNI |
418 AR9271_RX_FILTER_MULTI | AR9271_RX_FILTER_BROAD |
419 additional_bits;
[59fa7ab]420
421 wmi_reg_write(ar9271->htc_device, AR9271_RX_FILTER, filter_bits);
422
423 return EOK;
424}
425
[1dcc0b9]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
[8a64320e]436 wmi_reg_write(ar9271->htc_device, AR9271_BSSID0,
437 uint32_t_le2host(*first_4bytes));
[1dcc0b9]438
[8a64320e]439 wmi_reg_write(ar9271->htc_device, AR9271_BSSID1,
440 uint16_t_le2host(*last_2bytes) |
441 ((ieee80211_get_aid(ieee80211_dev) & 0x3fff) << 16));
[1dcc0b9]442
443 return EOK;
444}
445
[59fa7ab]446int hw_rx_init(ar9271_t *ar9271)
447{
[8a64320e]448 wmi_reg_write(ar9271->htc_device, AR9271_COMMAND,
449 AR9271_COMMAND_RX_ENABLE);
[59fa7ab]450
[1dcc0b9]451 int rc = hw_set_rx_filter(ar9271, false);
[8a64320e]452 if (rc != EOK) {
[59fa7ab]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 :-) */
[8a64320e]469 uint32_t pll = (0x5 << 10) | 0x2c;
[59fa7ab]470
471 wmi_reg_write(ar9271->htc_device, AR9271_RTC_PLL_CONTROL, pll);
472
[1dcc0b9]473 wmi_reg_write(ar9271->htc_device, AR9271_RTC_SLEEP_CLOCK,
[8a64320e]474 AR9271_RTC_SLEEP_CLOCK_FORCE_DERIVED);
[1dcc0b9]475 wmi_reg_set_bit(ar9271->htc_device, AR9271_RTC_FORCE_WAKE,
[8a64320e]476 AR9271_RTC_FORCE_WAKE_ENABLE);
[1dcc0b9]477
[59fa7ab]478 return EOK;
479}
480
[1dcc0b9]481static void hw_set_init_values(ar9271_t *ar9271)
[59fa7ab]482{
[8a64320e]483 uint32_t reg_offset;
484 uint32_t reg_value;
[59fa7ab]485
[8a64320e]486 size_t size = ARRAY_SIZE(ar9271_2g_mode_array);
[59fa7ab]487
[8a64320e]488 for (size_t i = 0; i < size; i++) {
[59fa7ab]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
[8a64320e]496 for (size_t i = 0; i < size; i++) {
[59fa7ab]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
[8a64320e]504 for (size_t i = 0; i < size; i++) {
[59fa7ab]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,
[8a64320e]514 AR9271_CARRIER_LEAK_CALIB);
[59fa7ab]515 wmi_reg_clear_bit(ar9271->htc_device, AR9271_ADC_CONTROL,
[8a64320e]516 AR9271_ADC_CONTROL_OFF_PWDADC);
[59fa7ab]517 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
[8a64320e]518 AR9271_AGC_CONTROL_TX_CALIB);
[59fa7ab]519 wmi_reg_set_bit(ar9271->htc_device, AR9271_PHY_TPCRG1,
[8a64320e]520 AR9271_PHY_TPCRG1_PD_CALIB);
[59fa7ab]521 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
[8a64320e]522 AR9271_AGC_CONTROL_CALIB);
[59fa7ab]523
[8a64320e]524 int rc = hw_read_wait(ar9271, AR9271_AGC_CONTROL,
525 AR9271_AGC_CONTROL_CALIB, 0);
526 if (rc != EOK) {
[59fa7ab]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,
[8a64320e]532 AR9271_ADC_CONTROL_OFF_PWDADC);
[59fa7ab]533 wmi_reg_clear_bit(ar9271->htc_device, AR9271_CARRIER_LEAK_CONTROL,
[8a64320e]534 AR9271_CARRIER_LEAK_CALIB);
[59fa7ab]535 wmi_reg_clear_bit(ar9271->htc_device, AR9271_AGC_CONTROL,
[8a64320e]536 AR9271_AGC_CONTROL_TX_CALIB);
[59fa7ab]537
538 return EOK;
539}
540
[8a64320e]541int hw_reset(ar9271_t *ar9271)
[59fa7ab]542{
543 /* Set physical layer as deactivated. */
544 wmi_reg_write(ar9271->htc_device, AR9271_PHY_ACTIVE, 0);
545
546 if(ar9271->starting_up) {
[8a64320e]547 wmi_reg_write(ar9271->htc_device,
548 AR9271_RESET_POWER_DOWN_CONTROL,
549 AR9271_RADIO_RF_RESET);
550
[59fa7ab]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);
[8a64320e]557 if (config_reg & AR9271_COMMAND_RX_ENABLE)
[59fa7ab]558 hw_set_reset(ar9271, true);
559
560 int rc = hw_init_pll(ar9271);
[8a64320e]561 if (rc != EOK) {
[59fa7ab]562 usb_log_error("Failed to init PLL.\n");
563 return rc;
564 }
565
566 udelay(500);
567
[8a64320e]568 wmi_reg_write(ar9271->htc_device, AR9271_CLOCK_CONTROL,
569 AR9271_MAX_CPU_CLOCK);
[59fa7ab]570
571 udelay(100);
572
[8a64320e]573 if (ar9271->starting_up) {
574 wmi_reg_write(ar9271->htc_device,
575 AR9271_RESET_POWER_DOWN_CONTROL,
576 AR9271_GATE_MAC_CONTROL);
577
[59fa7ab]578 udelay(50);
579 }
580
[1dcc0b9]581 hw_set_init_values(ar9271);
[59fa7ab]582
583 /* Set physical layer mode. */
[8a64320e]584 wmi_reg_write(ar9271->htc_device, AR9271_PHY_MODE,
585 AR9271_PHY_MODE_DYNAMIC);
[59fa7ab]586
587 /* Reset device operating mode. */
588 rc = hw_reset_operating_mode(ar9271);
[8a64320e]589 if (rc != EOK) {
[59fa7ab]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);
[8a64320e]596 if (rc != EOK) {
[59fa7ab]597 usb_log_error("Failed to set channel.\n");
598 return rc;
599 }
600
601 /* Initialize transmission queues. */
[8a64320e]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);
[59fa7ab]605 }
606
607 /* Activate physical layer. */
608 rc = hw_activate_phy(ar9271);
[8a64320e]609 if (rc != EOK) {
[59fa7ab]610 usb_log_error("Failed to activate physical layer.\n");
611 return rc;
612 }
613
614 /* Calibration. */
615 rc = hw_calibration(ar9271);
[8a64320e]616 if (rc != EOK) {
[59fa7ab]617 usb_log_error("Failed to calibrate device.\n");
618 return rc;
619 }
620
621 rc = hw_noise_floor_calibration(ar9271);
[8a64320e]622 if (rc != EOK) {
[59fa7ab]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
[8a64320e]633/** Initialize hardware of AR9271 device.
634 *
[59fa7ab]635 * @param ar9271 Device structure.
[8a64320e]636 *
[59fa7ab]637 * @return EOK if succeed, negative error code otherwise.
638 */
639int hw_init(ar9271_t *ar9271)
640{
641 int rc = hw_init_proc(ar9271);
[8a64320e]642 if (rc != EOK) {
[59fa7ab]643 usb_log_error("Failed to HW reset device.\n");
644 return rc;
645 }
646
647 rc = hw_init_led(ar9271);
[8a64320e]648 if (rc != EOK) {
[59fa7ab]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;
[8a64320e]656}
Note: See TracBrowser for help on using the repository browser.