Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset ab365c4 in mainline for uspace/drv/bus/usb/ar9271/hw.c


Ignore:
Timestamp:
2015-02-13T12:15:00Z (5 years ago)
Author:
Jan Kolarik <kolarik@…>
Branches:
master
Children:
56c0930
Parents:
462054a
Message:

Created library for IEEE802.11 related stuff. Mostly done device startup initialization.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ar9271/hw.c

    r462054a rab365c4  
    3636#include <unistd.h>
    3737#include <nic.h>
     38#include <ieee80211.h>
    3839
    3940#include "hw.h"
     
    7677static int hw_reset_power_on(ar9271_t *ar9271)
    7778{
    78         int rc = wmi_reg_write(ar9271->htc_device, AR9271_RTC_FORCE_WAKE,
    79                 AR9271_RTC_FORCE_WAKE_ENABLE |  AR9271_RTC_FORCE_WAKE_ON_INT);
    80         if(rc != EOK) {
    81                 usb_log_error("Failed to bring up RTC register.\n");
    82                 return rc;
    83         }
    84        
    8579        wmi_reg_t buffer[] = {
    8680                {
     
    9993        };
    10094       
    101         rc = wmi_reg_buffer_write(ar9271->htc_device, buffer,
     95        int rc = wmi_reg_buffer_write(ar9271->htc_device, buffer,
    10296                sizeof(buffer) / sizeof(wmi_reg_t));
    10397        if(rc != EOK) {
     
    132126}
    133127
    134 static int hw_warm_reset(ar9271_t *ar9271)
    135 {
     128static int hw_set_reset(ar9271_t *ar9271, bool cold)
     129{
     130        uint32_t reset_value = AR9271_RTC_RC_MAC_WARM;
     131       
     132        if(cold) {
     133                reset_value |= AR9271_RTC_RC_MAC_COLD;
     134        }
     135       
    136136        wmi_reg_t buffer[] = {
    137137                {
     
    146146                {
    147147                        .offset = AR9271_RTC_RC,
    148                         .value = 1
     148                        .value = reset_value
    149149                }
    150150        };
     
    202202        }
    203203       
    204         nic_t *nic = nic_get_from_ddf_dev(ar9271->ddf_device);
     204        nic_t *nic = nic_get_from_ddf_dev(ar9271->ddf_dev);
    205205       
    206206        rc = nic_report_address(nic, &ar9271_address);
     
    269269
    270270/**
    271  * Hardware reset of AR9271 device.
     271 * Hardware init procedure of AR9271 device.
    272272 *
    273273 * @param ar9271 Device structure.
     
    275275 * @return EOK if succeed, negative error code otherwise.
    276276 */
    277 static int hw_reset(ar9271_t *ar9271)
     277static int hw_init_proc(ar9271_t *ar9271)
    278278{
    279279        int rc = hw_reset_power_on(ar9271);
     
    283283        }
    284284       
    285         rc = hw_warm_reset(ar9271);
     285        rc = hw_set_reset(ar9271, false);
    286286        if(rc != EOK) {
    287287                usb_log_error("Failed to HW warm reset.\n");
     
    310310        if(rc != EOK) {
    311311                usb_log_error("Failed to init bring up GPIO led.\n");
     312                return rc;
     313        }
     314       
     315        return EOK;
     316}
     317
     318static int hw_set_operating_mode(ar9271_t *ar9271,
     319        ieee80211_operating_mode_t opmode)
     320{
     321        uint32_t set_bit = 0x10000000;
     322       
     323        /* NOTICE: Fall-through switch statement! */
     324        switch(opmode) {
     325                case IEEE80211_OPMODE_ADHOC:
     326                        set_bit |= AR9271_OPMODE_ADHOC_MASK;
     327                case IEEE80211_OPMODE_MESH:
     328                case IEEE80211_OPMODE_AP:
     329                        set_bit |= AR9271_OPMODE_STATION_AP_MASK;
     330                case IEEE80211_OPMODE_STATION:
     331                        wmi_reg_clear_bit(ar9271->htc_device, AR9271_CONFIG,
     332                                AR9271_CONFIG_ADHOC);
     333        }
     334       
     335        wmi_reg_clear_set_bit(ar9271->htc_device, AR9271_STATION_ID1,
     336                set_bit,
     337                AR9271_OPMODE_STATION_AP_MASK | AR9271_OPMODE_ADHOC_MASK);
     338       
     339        return EOK;
     340}
     341
     342static uint32_t hw_reverse_bits(uint32_t value, uint32_t count)
     343{
     344        uint32_t ret_val = 0;
     345       
     346        for(size_t i = 0; i < count; i++) {
     347                ret_val = (ret_val << 1) | (value & 1);
     348                value >>= 1;
     349        }
     350       
     351        return ret_val;
     352}
     353
     354static int hw_set_channel(ar9271_t *ar9271, uint16_t freq)
     355{
     356        /* Not supported channel frequency. */
     357        if(freq < IEEE80211_FIRST_CHANNEL || freq > IEEE80211_MAX_CHANNEL) {
     358                return EINVAL;
     359        }
     360       
     361        /* Not supported channel frequency. */
     362        if((freq - IEEE80211_FIRST_CHANNEL) % IEEE80211_CHANNEL_GAP != 0) {
     363                return EINVAL;
     364        }
     365       
     366        uint32_t result;
     367        wmi_reg_read(ar9271->htc_device, AR9271_PHY_CCK_TX_CTRL, &result);
     368        wmi_reg_write(ar9271->htc_device, AR9271_PHY_CCK_TX_CTRL,
     369                result & ~AR9271_PHY_CCK_TX_CTRL_JAPAN);
     370       
     371        /* Some magic here. */
     372        uint32_t channel = hw_reverse_bits(
     373                (((((freq - 672) * 2 - 3040) / 10) << 2) & 0xFF), 8);
     374        uint32_t to_write = (channel << 8) | 33;
     375       
     376        wmi_reg_write(ar9271->htc_device, AR9271_PHY_BASE + (0x37 << 2),
     377                to_write);
     378       
     379        return EOK;
     380}
     381
     382int hw_reset(ar9271_t *ar9271)
     383{
     384        int rc = wmi_reg_write(ar9271->htc_device,
     385                AR9271_RESET_POWER_DOWN_CONTROL,
     386                AR9271_RADIO_RF_RESET);
     387        if(rc != EOK) {
     388                usb_log_error("Failed to reset radio rf.\n");
     389                return rc;
     390        }
     391       
     392        udelay(50);
     393       
     394        rc = wmi_reg_write(ar9271->htc_device,
     395                AR9271_RESET_POWER_DOWN_CONTROL,
     396                AR9271_GATE_MAC_CONTROL);
     397        if(rc != EOK) {
     398                usb_log_error("Failed to set the gate reset controls for MAC."
     399                        "\n");
     400                return rc;
     401        }
     402       
     403        udelay(50);
     404       
     405        /* Perform cold reset of device. */
     406        rc = hw_set_reset(ar9271, true);
     407        if(rc != EOK) {
     408                usb_log_error("Failed to HW cold reset.\n");
     409                return rc;
     410        }
     411       
     412        /* Set physical layer mode. */
     413        rc = wmi_reg_write(ar9271->htc_device, AR9271_PHY_MODE,
     414                AR9271_PHY_MODE_DYNAMIC | AR9271_PHY_MODE_2G);
     415        if(rc != EOK) {
     416                usb_log_error("Failed to set physical layer mode.\n");
     417                return rc;
     418        }
     419       
     420        /* Set device operating mode. */
     421        rc = hw_set_operating_mode(ar9271, IEEE80211_OPMODE_STATION);
     422        if(rc != EOK) {
     423                usb_log_error("Failed to set opmode to station.\n");
     424                return rc;
     425        }
     426       
     427        /* Set channel. */
     428        rc = hw_set_channel(ar9271, IEEE80211_FIRST_CHANNEL);
     429        if(rc != EOK) {
     430                usb_log_error("Failed to set channel.\n");
     431                return rc;
     432        }
     433       
     434        /* Initialize transmission queues. */
     435        for(int i = 0; i < AR9271_QUEUES_COUNT; i++) {
     436                rc = wmi_reg_write(ar9271->htc_device,
     437                        AR9271_QUEUE_BASE_MASK + (i << 2),
     438                        1 << i);
     439                if(rc != EOK) {
     440                        usb_log_error("Failed to initialize transmission queue."
     441                                "\n");
     442                        return rc;
     443                }
     444        }
     445       
     446        /* Activate physical layer. */
     447        rc = wmi_reg_write(ar9271->htc_device, AR9271_PHY_ACTIVE, 1);
     448        if(rc != EOK) {
     449                usb_log_error("Failed to activate physical layer.\n");
    312450                return rc;
    313451        }
     
    325463int hw_init(ar9271_t *ar9271)
    326464{
    327         int rc = hw_reset(ar9271);
     465        int rc = hw_init_proc(ar9271);
    328466        if(rc != EOK) {
    329467                usb_log_error("Failed to HW reset device.\n");
Note: See TracChangeset for help on using the changeset viewer.