Beispiel #1
0
void ag7100_reset(ag7100_mac_t *mac) 
{
    uint32_t mask;

    //ag7100_reg_rmw_set(mac, AG7100_MAC_CFG1, AG7100_MAC_CFG1_SOFT_RST);
    mask = ag7100_reset_mask(mac->mac_unit);
        
    /*
     * put into reset, hold, pull out.
     */

    ar7100_reg_rmw_clear(AR7100_GPIO_INT_MASK,          /* set gpio to intr disable mode */
                      (1 << (GPIO_MDC - AR7100_GPIO_IRQ_BASE)));
    ar7100_reg_rmw_clear(AR7100_GPIO_OE, (1 << GPIO_MDC));  /* set gpio to out val mode */
    ar7100_reg_rmw_set(AR7100_GPIO_OUT, (1 << GPIO_MDC));    /* out val */
    
    ar7100_reg_rmw_clear(AR7100_GPIO_INT_MASK,          /* set gpio to intr disable mode */
                      (1 << (GPIO_MDIO - AR7100_GPIO_IRQ_BASE)));
    ar7100_reg_rmw_clear(AR7100_GPIO_OE, (1 << GPIO_MDIO));  /* set gpio to out val mode */
    ar7100_reg_rmw_set(AR7100_GPIO_OUT, (1 << GPIO_MDIO));    /* out val */
         
    ar7100_reg_rmw_set(AR7100_RESET, mask);  /* reset switch */
    A_MDELAY(200);
    ar7100_reg_rmw_clear(AR7100_RESET, mask);
    A_MDELAY(200);
}
Beispiel #2
0
void __init ath6kl_sdio_init_msm(void)
{
	printk("%s(): Enter\n", __func__);

	platform_driver_register(&ath6kl_pm_device);
	A_MDELAY(50);
}
Beispiel #3
0
A_STATUS 
bmiBufferReceive(HIF_DEVICE *device, 
                 A_UCHAR *buffer, 
                 A_UINT32 length) 
{
    A_STATUS status;
    A_UINT32 address;
    A_UINT32 timeout;
#ifdef ONLY_16BIT
    A_UINT16 cmdCredits;
#else
    A_UCHAR cmdCredits;
#endif
    HIF_REQUEST request;

    HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, 
                      HIF_BYTE_BASIS, HIF_FIXED_ADDRESS);
    address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
    status = HIFReadWrite(device, address, (A_UCHAR *)&cmdCredits, 
                    sizeof(cmdCredits), &request, NULL);
    if (status != A_OK) {
        BMI_DEBUG_PRINTF(ATH_LOG_ERR,"Unable to decrement the command credit count register\n");
        return A_ERROR;
    }

    timeout = BMI_COMMUNICATION_TIMEOUT;
    while(timeout--) {
        if (cmdCredits == 1) {
            HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, 
                              HIF_SYNCHRONOUS, HIF_BYTE_BASIS, 
                              HIF_FIXED_ADDRESS);
            address = HIF_MBOX_END_ADDR(ENDPOINT1);
            status = HIFReadWrite(device, address, buffer, length, 
                                  &request, NULL);
            if (status != A_OK) {
                BMI_DEBUG_PRINTF(ATH_LOG_ERR,"Unable to read the BMI data from the device\n");
                return A_ERROR;
            }
            break;
        }

        HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, 
                          HIF_BYTE_BASIS, HIF_FIXED_ADDRESS);
        address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
        status = HIFReadWrite(device, address, (A_UCHAR *)&cmdCredits, 
                    sizeof(cmdCredits), &request, NULL);
        if (status != A_OK) {
            BMI_DEBUG_PRINTF(ATH_LOG_ERR,"Unable to decrement the command credit count register\n");
            return A_ERROR;
        }
        status = A_ERROR;
        A_MDELAY(1);
    }

    if (status != A_OK) {
        BMI_DEBUG_PRINTF(ATH_LOG_ERR,"BMI Communication timeout\n");
    }

    return status;
}
A_STATUS
ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice)
{
    A_INT32 i;
    struct forceROM_s {
        A_UINT32 addr;
        A_UINT32 data;
    };
    struct forceROM_s *ForceROM;
    A_INT32 szForceROM;
    A_STATUS status = A_OK;
    A_UINT32 address;
    A_UINT32 data;

    static struct forceROM_s ForceROM_NEW[] = {
        {0x52df80, 0x20f31c07},
        {0x52df84, 0x92374420},
        {0x52df88, 0x1d120c03},
        {0x52df8c, 0xff8216f0},
        {0x52df90, 0xf01d120c},
        {0x52df94, 0x81004136},
        {0x52df98, 0xbc9100bd},
        {0x52df9c, 0x00bba100},

        {0x00008000|MC_TCAM_TARGET_ADDRESS, 0x0012dfe0}, /* Use remap entry 0 */
        {0x00008000|MC_TCAM_COMPARE_ADDRESS, 0x000e2380},
        {0x00008000|MC_TCAM_MASK_ADDRESS, 0x00000000},
        {0x00008000|MC_TCAM_VALID_ADDRESS, 0x00000001},

        {0x00018000|(LOCAL_COUNT_ADDRESS+0x10), 0}, /* clear BMI credit counter */

        {0x00004000|AR6002_RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
    };

    address = 0x004ed4b0; /* REV1 target software ID is stored here */
    status = ar6000_ReadRegDiag(hifDevice, &address, &data);
    if (A_FAILED(status) || (data != AR6002_VERSION_REV1)) {
        return A_ERROR; /* Not AR6002 REV1 */
    }

    ForceROM = ForceROM_NEW;
    szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM);

    ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Force Target to recognize Host....\n"));
    for (i = 0; i < szForceROM; i++)
    {
        if (ar6000_WriteRegDiag(hifDevice,
                                &ForceROM[i].addr,
                                &ForceROM[i].data) != A_OK)
        {
            ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Cannot force Target to recognize Host!\n"));
            return A_ERROR;
        }
    }

    A_MDELAY(1000);

    return A_OK;
}
Beispiel #5
0
static A_STATUS AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig)
{
    A_STATUS    status = A_OK;
    A_UINT8     hciBaudChangeCommand[] =  {0x0c,0xfc,0x2,0,0};
    A_UINT16    baudVal;
    A_UINT8     *pEvent = NULL;
    A_UINT8     *pBufferToFree = NULL;

    do {

        if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) {
            baudVal = (A_UINT16)(pConfig->AR3KBaudRate / 100);
            hciBaudChangeCommand[3] = (A_UINT8)baudVal;
            hciBaudChangeCommand[4] = (A_UINT8)(baudVal >> 8);

            status = SendHCICommandWaitCommandComplete(pConfig,
                                                       hciBaudChangeCommand,
                                                       sizeof(hciBaudChangeCommand),
                                                       &pEvent,
                                                       &pBufferToFree);
            if (A_FAILED(status)) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n"));
                break;
            }

            if (pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET] != 0) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                    ("AR3K Config: Baud change command event status failed: %d \n",
                                pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET]));
                status = A_ECOMM;
                break;
            }

            AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
                    ("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate));
        }

        if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) {
                /* some versions of AR3K do not switch baud immediately, up to 300MS */
            A_MDELAY(325);
        }

        if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP) {
            /* Tell target to change UART baud rate for AR6K */
            status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate);

            if (A_FAILED(status)) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                    ("AR3K Config: failed to set scale and step values: %d \n", status));
                break;
            }

            AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
                    ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate));
        }

    } while (FALSE);
Beispiel #6
0
/*  Strrcl_ChipUpStart - Utility function to bring bring the chip back up. Also
 * 	 sets up the driver tempFunc so that when the WMI_READY is received the
 *	 store recall process can be completed via Strrcl_ChipUpFinish.
 *      void *pCxt - the driver context.
 *****************************************************************************/
static A_STATUS Strrcl_ChipUpStart(void *pCxt)
{
    A_STATUS status = A_ERROR;
    A_DRIVER_CONTEXT *pDCxt = GET_DRIVER_COMMON(pCxt);
    A_MDELAY(2);
    /* assert pwd line */
    HW_PowerUpDown(pCxt, true);

    A_MDELAY(2);
    do
    {
        /* reset htc_creditInit to re-process the HTC interrupt */
        pDCxt->htc_creditInit = 0;

        if ((status = Hcd_ReinitTarget(pCxt)) != A_OK)
        {
            break;
        }

        A_MDELAY(1);

        if (A_OK != (status = Driver_BootComm(pCxt)))
        {
            break;
        }

#if (DRIVER_CONFIG_ENABLE_HOST_FW_DOWNLOAD)
        if (A_OK != (status = Driver_StoreRecallFirmwareDownload(pCxt)))
        {
            break;
        }
#endif /* DRIVER_CONFIG_ENABLE_HOST_FW_DOWNLOAD */

        /* unmask the packet interrupt on-chip */
        Hcd_UnmaskInterrupts(pCxt, ATH_SPI_INTR_PKT_AVAIL);
        /* when the driver receives the WMI_READY event chip_up_finish
         * will complete the re-boot process and open the way for
         * outside requests to resume. */
        pDCxt->asynchRequest = Strrcl_ChipUpFinish;

    } while (0);

    return status;
}
Beispiel #7
0
int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending)
{
    int    status          = 0;
    u8     host_int_status = 0x0;
    u32 counter         = 0x0;

    if(TimeoutInMs < 100)
    {
        TimeoutInMs = 100;
    }

    counter = TimeoutInMs / 100;

    do
    {
        //Read the Host Interrupt Status Register
        status = HIFReadWrite(pDev->HIFDevice,
                              HOST_INT_STATUS_ADDRESS,
                             &host_int_status,
                              sizeof(u8),
                              HIF_RD_SYNC_BYTE_INC,
                              NULL);
        if (status)
        {
            AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status));
            break;
        }

        host_int_status = !status ? (host_int_status & (1 << 0)):0;
        if(!host_int_status)
        {
            status          = 0;
           *pbIsRecvPending = false;
            break;
        }
        else
        {
            *pbIsRecvPending = true;
        }

        A_MDELAY(100);

        counter--;

    }while(counter);
    return status;
}
Beispiel #8
0
A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pbIsRecvPending)
{
    A_STATUS    status          = A_OK;
    A_UCHAR     host_int_status = 0x0;
    A_UINT32    counter         = 0x0;

    if(TimeoutInMs < 100)
    {
        TimeoutInMs = 100;
    }

    counter = TimeoutInMs / 100;

    do
    {
        //Read the Host Interrupt Status Register
        status = HIFReadWrite(pDev->HIFDevice,
                              HOST_INT_STATUS_ADDRESS,
                             &host_int_status,
                              sizeof(A_UCHAR),
                              HIF_RD_SYNC_BYTE_INC,
                              NULL);
        if(A_FAILED(status))
        {
            AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status));
            break;
        }

        host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)):0;
        if(!host_int_status)
        {
            status          = A_OK;
           *pbIsRecvPending = FALSE;
            break;
        }
        else
        {
            *pbIsRecvPending = TRUE;
        }

        A_MDELAY(100);

        counter--;

    }while(counter);
    return status;
}
Beispiel #9
0
/* poll the mailbox credit counter until we get a credit or timeout */
static A_STATUS GetCredits(AR6K_DEVICE *pDev, int mbox, int *pCredits)
{
    A_STATUS status = A_OK;
    int      timeout = TEST_CREDITS_RECV_TIMEOUT;
    A_UINT8  credits = 0;
    A_UINT32 address;

    while (TRUE) 
	{

		/* Read the counter register to get credits, this auto-decrements  */
        address = COUNT_DEC_ADDRESS + (AR6K_MAILBOXES + mbox) * 4;
        status = HIFReadWrite(pDev->HIFDevice, address, &credits, sizeof(credits),
                              HIF_RD_SYNC_BYTE_FIX, NULL);
        if (status != A_OK) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                ("Unable to decrement the command credit count register (mbox=%d)\n",mbox));
            status = A_ERROR;
            break;
        }

        if (credits) {
            break;
        }

        timeout--;

        if (timeout <= 0) {
              AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                (" Timeout reading credit registers (mbox=%d, address:0x%X) \n",mbox,address));
            status = A_ERROR;
            break;
        }

         /* delay a little, target may not be ready */
         A_MDELAY(1000);

    }

    if (status == A_OK) {
        *pCredits = credits;
    }

    return status;
}
Beispiel #10
0
/* Useful for qualcom platform to detect our wlan card for mmc stack */
static void ar6000_enable_mmchost_detect_change(int enable)
{
#ifdef CONFIG_MMC_MSM
#define MMC_MSM_DEV "msm_sdcc.2"
    char buf[3];
    int length;

    if (!enable_mmc_host_detect_change) {
        return;
    }
    length = snprintf(buf, sizeof(buf), "%d\n", enable ? 1 : 0);
    if (android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/detect_change", 
                               NULL, buf, length) < 0) {
        /* fall back to polling */
        android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/polling", NULL, buf, length);
        A_MDELAY(50);
    }
#endif
}
/* Useful for qualcom platform to detect our wlan card for mmc stack */
static void ar6000_enable_mmchost_detect_change(int enable)
{
#ifdef CONFIG_MMC_MSM
#if defined(CONFIG_MMC_MSM) && defined(CONFIG_ARCH_MSM7X27) && defined(CONFIG_MSM_SOC_REV_A)
#define MMC_MSM_DEV "msm_sdcc.2"
#else
#define MMC_MSM_DEV "msm_sdcc.1"
#endif
    char buf[3];
    int length;

    if (!enable_mmc_host_detect_change) {
        return;
    }
    length = snprintf(buf, sizeof(buf), "%d\n", enable ? 1 : 0);
    android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/polling", NULL, buf, length);
    A_MDELAY(50);
#endif
}
Beispiel #12
0
/*  Strrcl_Recall - Implements the store-recall procedure.  powers down the chip
 *	 waits for x msec powers up the chip, reboots the chip. Called when the
 * 	 store-recall event is received from the chip indicating that it can be
 *	 powered down for the specified timeout.
 *      void *pCxt - the driver context.
 *		uint32_t msec_sleep - number of milliseconds to wait
 *****************************************************************************/
void Strrcl_Recall(void *pCxt, uint32_t msec_sleep)
{
    /* bring down the chip */
    Strrcl_ChipDown(pCxt);
    /* this will block the driver thread */
    /* FIXME: should instead implement a way to block the driver at driver_main thus
     * allowing the thread to continue running in single-threaded systems.*/
    if (ath_custom_init.Custom_Delay != NULL)
    {
        /*It is possible that some hosts support low power modes, this would be a
          good place to invoke it. Call app defined function if available*/
        ath_custom_init.Custom_Delay(msec_sleep);
    }
    else
        A_MDELAY(msec_sleep);

    /* wake up chip */
    Strrcl_ChipUpStart(pCxt);
}
Beispiel #13
0
static A_STATUS
_delay_until_target_alive(HIF_DEVICE *hifDevice, A_INT32 wait_msecs, A_UINT32 TargetType)
{
    A_INT32 actual_wait;
    A_INT32 i;
    A_UINT32 address;

    actual_wait = 0;

    /* Hardcode the address of LOCAL_COUNT_ADDRESS based on the target type */
    if (TargetType == TARGET_TYPE_AR6001) {
        address = AR6001_LOCAL_COUNT_ADDRESS;
    } else if (TargetType == TARGET_TYPE_AR6002) {
       address = AR6002_LOCAL_COUNT_ADDRESS;
    } else if (TargetType == TARGET_TYPE_AR6003) {
       address = AR6003_LOCAL_COUNT_ADDRESS;
    } else {
       A_ASSERT(0);
    }
    address += 0x10;
    for (i=0; actual_wait < wait_msecs; i++) {
        A_UINT32 data;

        A_MDELAY(100);
        actual_wait += 100;

        data = 0;
        if (ar6000_ReadRegDiag(hifDevice, &address, &data) != A_OK) {
            return A_ERROR;
        }

        if (data != 0) {
            /* No need to wait longer -- we have a BMI credit */
            return A_OK;
        }
    }
    return A_ERROR; /* timed out */
}
Beispiel #14
0
static int ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle,
                                           struct hci_transport_properties *pProps, 
                                           void                     *pContext)
{
    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
    int              status;
    u32 address, hci_uart_pwr_mgmt_params;
//    struct ar3k_config_info      ar3kconfig;
    
    pHcidevInfo->pHCIDev = HCIHandle;
    
    memcpy(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps));
    
    AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%lX, headroom:%d, tailroom:%d blockpad:%d) \n", 
            (unsigned long)HCIHandle, 
            pHcidevInfo->HCIProps.HeadRoom, 
            pHcidevInfo->HCIProps.TailRoom,
            pHcidevInfo->HCIProps.IOBlockPad));
    
#ifdef EXPORT_HCI_BRIDGE_INTERFACE
    A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)->hard_header_len);
#else
    A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= pHcidevInfo->ar->arNetDev->hard_header_len);
#endif
                             
        /* provide buffers */
    RefillRecvBuffers(pHcidevInfo, HCI_ACL_TYPE, MAX_ACL_RECV_BUFS);
    RefillRecvBuffers(pHcidevInfo, HCI_EVENT_TYPE, MAX_EVT_RECV_BUFS);
   
    do {
            /* start transport */
        status = HCI_TransportStart(pHcidevInfo->pHCIDev);
         
        if (status) {
            break;    
        }
        
        if (!pHcidevInfo->HciNormalMode) {
                /* in test mode, no need to go any further */
            break;    
        }

        // The delay is required when AR6K is driving the BT reset line
        // where time is needed after the BT chip is out of reset (HCI_TransportStart)
        // and before the first HCI command is issued (AR3KConfigure)
        // FIXME
        // The delay should be configurable and be only applied when AR6K driving the BT
        // reset line. This could be done by some module parameter or based on some HW config
        // info. For now apply 100ms delay blindly
        A_MDELAY(100);
        
        A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig));
        ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev;
        ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps;
#ifdef EXPORT_HCI_BRIDGE_INTERFACE
        ar3kconfig.pHIFDevice = (struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice);
#else
        ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice;
#endif
        ar3kconfig.pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev;
        
        if (ar3khcibaud != 0) {
                /* user wants ar3k baud rate change */
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD;
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY;
            ar3kconfig.AR3KBaudRate = ar3khcibaud;    
        }
        
        if ((hciuartscale != 0) || (hciuartstep != 0)) {   
                /* user wants to tune HCI bridge UART scale/step values */
            ar3kconfig.AR6KScale = (u16)hciuartscale;
            ar3kconfig.AR6KStep = (u16)hciuartstep;
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP;
        }
        
        /* Fetch the address of the hi_hci_uart_pwr_mgmt_params instance in the host interest area */
        address = TARG_VTOP(pHcidevInfo->ar->arTargetType, 
                            HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar, hi_hci_uart_pwr_mgmt_params));
        status = ar6000_ReadRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params);
        if (0 == status) {
            ar3kconfig.PwrMgmtEnabled = (hci_uart_pwr_mgmt_params & 0x1);
            ar3kconfig.IdleTimeout = (hci_uart_pwr_mgmt_params & 0xFFFF0000) >> 16;
            ar3kconfig.WakeupTimeout = (hci_uart_pwr_mgmt_params & 0xFF00) >> 8;
        } else {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to read hci_uart_pwr_mgmt_params! \n"));
        }
        /* configure the AR3K device */         
		memcpy(ar3kconfig.bdaddr,pHcidevInfo->ar->bdaddr,6);
        status = AR3KConfigure(&ar3kconfig);
        if (status) {
            break; 
        }

        /* Make sure both AR6K and AR3K have power management enabled */
        if (ar3kconfig.PwrMgmtEnabled) {
            status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, true);
            if (status) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to enable TLPM for AR6K! \n"));
            }
        }
        
        status = bt_register_hci(pHcidevInfo);
        
    } while (false);
Beispiel #15
0
void __init ath6kl_sdio_init_c210(void)
{
	platform_driver_register(&ath6kl_pm_device);
	A_MDELAY(50);
}
/* mailbox recv message polling */
int DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
                            u32 *pLookAhead,
                            int          TimeoutMS)
{
    int status = 0;
    int      timeout = TimeoutMS/DELAY_PER_INTERVAL_MS;

    A_ASSERT(timeout > 0);

    AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n"));

    while (true) {

        if (pDev->GetPendingEventsFunc != NULL) {

            HIF_PENDING_EVENTS_INFO events;

#ifdef THREAD_X
			events.Polling =1;
#endif

            /* the HIF layer uses a special mechanism to get events, do this
             * synchronously */
            status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
                                            &events,
                                            NULL);
            if (status)
            {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n"));
                break;
            }

            if (events.Events & HIF_RECV_MSG_AVAIL)
            {
                    /*  there is a message available, the lookahead should be valid now */
                *pLookAhead = events.LookAhead;

                break;
            }
        } else {

                /* this is the standard HIF way.... */
                /* load the register table */
            status = HIFReadWrite(pDev->HIFDevice,
                                  HOST_INT_STATUS_ADDRESS,
                                  (u8 *)&pDev->IrqProcRegisters,
                                  AR6K_IRQ_PROC_REGS_SIZE,
                                  HIF_RD_SYNC_BYTE_INC,
                                  NULL);

            if (status){
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n"));
                break;
            }

                /* check for MBOX data and valid lookahead */
            if (pDev->IrqProcRegisters.host_int_status & (1 << HTC_MAILBOX)) {
                if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX))
                {
                    /* mailbox has a message and the look ahead is valid */
                    *pLookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX];
                    break;
                }
            }

        }

        timeout--;

        if (timeout <= 0) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Timeout waiting for recv message \n"));
            status = A_ERROR;

                /* check if the target asserted */
            if ( pDev->IrqProcRegisters.counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) {
                    /* target signaled an assert, process this pending interrupt
                     * this will call the target failure handler */
                DevServiceDebugInterrupt(pDev);
            }

            break;
        }

            /* delay a little  */
        A_MDELAY(DELAY_PER_INTERVAL_MS);
        AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("  Retry Mbox Poll : %d \n",timeout));
    }

    AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevPollMboxMsgRecv \n"));

    return status;
}
Beispiel #17
0
/*
 * Call this function just before the call to BMIInit
 * in order to force* AR6002 rev 1.x firmware to detect a Host.
 * THIS IS FOR USE ONLY WITH AR6002 REV 1.x.
 * TBDXXX: Remove this function when REV 1.x is desupported.
 */
A_STATUS
ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice)
{
    A_INT32 i;
    struct forceROM_s {
        A_UINT32 addr;
        A_UINT32 data;
    };
    struct forceROM_s *ForceROM;
    A_INT32 szForceROM;
    A_STATUS status = A_OK;
    A_UINT32 address;
    A_UINT32 data;

    /* Force AR6002 REV1.x to recognize Host presence.
     *
     * Note: Use RAM at 0x52df80..0x52dfa0 with ROM Remap entry 0
     * so that this workaround functions with AR6002.war1.sh.  We
     * could fold that entire workaround into this one, but it's not
     * worth the effort at this point.  This workaround cannot be
     * merged into the other workaround because this must be done
     * before BMI.
     */

    static struct forceROM_s ForceROM_NEW[] = {
        {0x52df80, 0x20f31c07},
        {0x52df84, 0x92374420},
        {0x52df88, 0x1d120c03},
        {0x52df8c, 0xff8216f0},
        {0x52df90, 0xf01d120c},
        {0x52df94, 0x81004136},
        {0x52df98, 0xbc9100bd},
        {0x52df9c, 0x00bba100},

        {0x00008000|MC_TCAM_TARGET_ADDRESS, 0x0012dfe0}, /* Use remap entry 0 */
        {0x00008000|MC_TCAM_COMPARE_ADDRESS, 0x000e2380},
        {0x00008000|MC_TCAM_MASK_ADDRESS, 0x00000000},
        {0x00008000|MC_TCAM_VALID_ADDRESS, 0x00000001},

        {0x00018000|(LOCAL_COUNT_ADDRESS+0x10), 0}, /* clear BMI credit counter */

        {0x00004000|AR6002_RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
    };

    address = 0x004ed4b0; /* REV1 target software ID is stored here */
    status = ar6000_ReadRegDiag(hifDevice, &address, &data);
    if (A_FAILED(status) || (data != AR6002_VERSION_REV1)) {
        return A_ERROR; /* Not AR6002 REV1 */
    }

    ForceROM = ForceROM_NEW;
    szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM);

    ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Force Target to recognize Host....\n"));
    for (i = 0; i < szForceROM; i++)
    {
        if (ar6000_WriteRegDiag(hifDevice,
                                &ForceROM[i].addr,
                                &ForceROM[i].data) != A_OK)
        {
            ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Cannot force Target to recognize Host!\n"));
            return A_ERROR;
        }
    }

    A_MDELAY(1000);

    return A_OK;
}
Beispiel #18
0
void
HTCStop(HTC_TARGET *target)
{
    A_UINT32 count;
    A_STATUS status;
    A_UINT32 address;
    HIF_REQUEST request;
    A_UINT32 window_data;
    HTC_ENDPOINT *endPoint;
    HTC_REG_REQUEST_LIST *regList;
    HTC_REG_REQUEST_ELEMENT *element;
    HTC_DATA_REQUEST_QUEUE *sendQueue;
    HTC_DATA_REQUEST_QUEUE *recvQueue;

    HTC_DEBUG_PRINTF(ATH_LOG_TRC, "HTCStop: Enter");

    /* Disable all the dragon interrupts */
    target->table.int_status_enable = 0;
    target->table.cpu_int_status_enable = 0;
    target->table.error_status_enable = 0;
    target->table.counter_int_status_enable = 0;
    HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS,
                      HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS);
    address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED);
    status = HIFReadWrite(target->device, address, 
                          &target->table.int_status_enable, 4, &request, NULL);
    AR_DEBUG_ASSERT(status == A_OK);

    /* Disable the host controller interrupts */
    HIFMaskInterrupt(target->device);

    /* Flush all the queues and return the buffers to their owner */
    for (count = ENDPOINT1; count <= ENDPOINT4; count ++) {
        endPoint = &target->endPoint[count];

        /* Decrement the number of credits consumed */
        if (endPoint->txCreditsConsumed) {
            HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, 
                              HIF_SYNCHRONOUS, HIF_BYTE_BASIS, 
                              HIF_FIXED_ADDRESS);
            address = getRegAddr(TX_CREDIT_COUNTER_DECREMENT_REG, count);
#ifdef ONLY_16BIT
            status = HIFReadWrite(target->device, address, 
                                  (A_UCHAR *)endPoint->txCreditsAvailable, 
                                  endPoint->txCreditsConsumed * 2, &request, NULL);
#else
            status = HIFReadWrite(target->device, address, 
                                  endPoint->txCreditsAvailable, 
                                  endPoint->txCreditsConsumed, &request, NULL);
#endif
            AR_DEBUG_ASSERT(status == A_OK);
        }

        SET_TX_CREDITS_AVAILABLE(endPoint, 0);
        SET_TX_CREDITS_CONSUMED(endPoint, 0);

#ifdef DEBUG
        txcreditsavailable[count] = GET_TX_CREDITS_AVAILABLE(endPoint);
        txcreditsconsumed[count] = GET_TX_CREDITS_CONSUMED(endPoint);
#endif

        endPoint->txCreditsIntrEnable = FALSE;
        endPoint->rxLengthPending = 0;
        endPoint->enabled = FALSE;

        /* Flush the Pending Receive Queue */
        HTC_DEBUG_PRINTF(ATH_LOG_INF, 
                        "Flushing the recv queue & returning the buffers\n");

        recvQueue = &endPoint->recvQueue;
        flushMboxQueue(endPoint, recvQueue, HTC_BUFFER_RECEIVED);

        /* Flush the Pending Send Queue */
        HTC_DEBUG_PRINTF(ATH_LOG_INF, 
                        "Flushing the send queue & returning the buffers\n");
        sendQueue = &endPoint->sendQueue;
        flushMboxQueue(endPoint, sendQueue, HTC_BUFFER_SENT);
    }

    /* Clear the tx counters */
    memset(tx_attempt, 0, sizeof(tx_attempt));
    memset(tx_post, 0, sizeof(tx_post));
    memset(tx_complete, 0, sizeof(tx_complete));

    /* Attempting a force reset of the target */
    window_data = RESET_CONTROL_COLD_RST_MASK;
    HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS,
                      HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS);
    address = getRegAddr(WINDOW_DATA_REG, ENDPOINT_UNUSED);
    status = HIFReadWrite(target->device, address, (A_UCHAR *)&window_data, 
                          4, &request, NULL);
    AR_DEBUG_ASSERT(status == A_OK);
    
    _WRITE_WINDOW_ADDR(target, WINDOW_WRITE_ADDR_REG, RESET_CONTROL_ADDRESS);

    /* 
     * Read back the RESET CAUSE register to ensure that the cold reset 
     * went through.
     */
    A_MDELAY(2000); /* 2 Second delay to allow dragon to settle down */
    _WRITE_WINDOW_ADDR(target, WINDOW_READ_ADDR_REG, RESET_CAUSE_ADDRESS);
    window_data = 0;
    HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS,
                      HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS);
    address = getRegAddr(WINDOW_DATA_REG, ENDPOINT_UNUSED);
    status = HIFReadWrite(target->device, address, (A_UCHAR *)&window_data, 
                          4, &request, NULL);
    AR_DEBUG_ASSERT(status == A_OK);     
    HTC_DEBUG_PRINTF(ATH_LOG_INF, "window data: %d\n", window_data);
    window_data &= RESET_CAUSE_LAST_MASK;

    if (window_data != 2) {
        HTC_DEBUG_PRINTF(ATH_LOG_ERR, "Unable to cold reset the target\n");
    }

    /* 
     * Ensure that all the pending asynchronous register read/writes have 
     * been finished.
     */
    regList = &target->regList;
    for (count = 0; count < HTC_REG_REQUEST_LIST_SIZE; count ++) {
        element = &regList->element[count];
        AR_DEBUG_ASSERT(IS_ELEMENT_FREE(element));
    }

    /* Initialize the shadow copy of the target register table */
    A_MEMZERO(&target->table, sizeof(HTC_REGISTER_TABLE));
    target->ready = FALSE;

    HTC_DEBUG_PRINTF(ATH_LOG_TRC, "HTCStop: Exit");
}
Beispiel #19
0
void __exit ath6kl_sdio_exit_msm(void)
{
	platform_driver_unregister(&ath6kl_pm_device);
	A_MDELAY(1000);
}
Beispiel #20
0
A_STATUS RunConnectionTest()
{
    A_STATUS        status = A_OK;
    HTC_ENDPOINT_ID endpointID;
    int             length;
    DWORD           startTime;
    DWORD           currentTime;
    DWORD           dhcpRequestTimeStart;
    int             dhcpAttempt = 0;
        
        /* set initial status and state */
    g_WifiMTE.TestState = TEST_STATE_WAIT_WMI_READY;
    
    startTime = A_GET_SECONDS_TICK();
    
    while (A_SUCCESS(status) && (g_WifiMTE.TestState != TEST_GEN_FAILURE)) {

        currentTime = A_GET_SECONDS_TICK();
        A_ASSERT(startTime <= currentTime);
        
        if ((currentTime - startTime) >= CONNECTION_TEST_EXPIRATION) {
            DBG_LOG_PRINT(DBG_ZONE_ERR, ("Time Expired! Current State: %d \r\n", g_WifiMTE.TestState));   
            status = A_ERROR;
            break;    
        }
        
        endpointID = ENDPOINT_MAX;
        
           /* poll for a message */
        status = HTCGetMessage(g_WifiMTE.htcHandle,                
                               &endpointID, 
                               g_WifiMTE.pReceivePayloadStart,  /* reuse transmit buffer */
                               MAX_MESSAGE_BUFFER_SIZE,
                               &length,
                               0); /* no timeout */
                               
        if (A_FAILED(status)) {
            break;    
        }            
                
        if (endpointID == ENDPOINT_MAX) {
                /* polling was successful, but no message was retrieved */
            continue;    
        }
        
        if (endpointID == g_WifiMTE.ControlEp) {
                /* process control message */
            status = wmi_control_rx(g_WifiMTE.pReceivePayloadStart, length);
            
        } else if (endpointID == g_WifiMTE.DataEp) {
           A_UINT8  *pNetFrameStart; 
           int      networkFrameLength;
           A_UINT16 etherType;
           
                /* process data message */
                
                /* get the frame information, the payload is the WMI message */
            wmi_get_network_frame_info(g_WifiMTE.pReceivePayloadStart, 
                                       length, 
                                       &pNetFrameStart,
                                       &networkFrameLength,
                                       &etherType);
            
            if ((networkFrameLength != 0) && (etherType == 0x0800)) {  
                    /* an IP packet arrived */
                if (!g_WifiMTE.GotDhcpOffer) {
                        /* run it through DHCP */
                    if (CheckDHCPOffer(pNetFrameStart,networkFrameLength)) {
                        g_WifiMTE.GotDhcpOffer = TRUE;              
                    }
                }
            }                     
                                    
        } else {
            A_ASSERT(FALSE);
            status = A_EPROTO;
            break;    
        }
        
        if (A_FAILED(status)) {
            break;    
        }   
        
        /* run through state machine */
        
        switch (g_WifiMTE.TestState) {
            case TEST_STATE_WAIT_WMI_READY :
                if (g_WifiMTE.WMIReady) {
                    DBG_LOG_PRINT(DBG_ZONE_INIT, ("WMI is ready\n"));
                        /* next state is to wait for connection */
                    g_WifiMTE.TestState = TEST_STATE_WAIT_WMI_CONNECT;
                    
                    status = ar6000_set_wmi_protocol_ver(g_WifiMTE.HifDevice, 
                                                         g_WifiMTE.TargetInfo.target_type, 
                                                         WMI_PROTOCOL_VERSION); 
                    
                    if (A_FAILED(status)) {
                        A_ASSERT(FALSE);
                        break;    
                    }          
        
                        /* make sure we are fully awake */
                    DBG_LOG_PRINT(DBG_ZONE_INIT, ("Changing power mode\n"));
                    status = wmi_powermode_cmd(MAX_PERF_POWER);
                    
                    if (A_FAILED(status)) {
                        break;    
                    }   
                    DBG_LOG_PRINT(DBG_ZONE_INIT, ("Sending connect\n"));
                        /* connect to SSID */
                    status = wmi_connect_cmd(INFRA_NETWORK,
                                             OPEN_AUTH, 
                                             NONE_AUTH,
                                             NONE_CRYPT, 0,
                                             NONE_CRYPT, 0,
                                             g_WifiMTE.SSIDLength, 
                                             g_WifiMTE.SSID,
                                             NULL, 
                                             g_WifiMTE.WiFiChannel, 
                                             0);
                }
                break;
            case TEST_STATE_WAIT_WMI_CONNECT :
                if (g_WifiMTE.APConnected) {
                        /* next state */
                    g_WifiMTE.TestState = TEST_WAIT_DHCP_REPLY;   
                        /* capture start time to retry DHCP request */
                    dhcpRequestTimeStart = A_GET_SECONDS_TICK();
                    DBG_LOG_PRINT(DBG_ZONE_INIT, ("Sending DHCP Discover... \r\n"));   
                    status = SendDhcpDiscover(g_WifiMTE.TransmitBuffer);
                    if (A_FAILED(status)) {
                        break;   
                    }
                }            
                break;
            
            case TEST_WAIT_DHCP_REPLY :
                if ((A_GET_SECONDS_TICK() - dhcpRequestTimeStart) > 1) {
                     dhcpAttempt++;
                        /* time expired, resend DHCP again */
                    DBG_LOG_PRINT(DBG_ZONE_INIT, ("Retrying DHCP request.. re-attempt : %d \r\n", dhcpAttempt));   
                    dhcpRequestTimeStart = A_GET_SECONDS_TICK();
                       /* resend again */
                    status = SendDhcpDiscover(g_WifiMTE.TransmitBuffer);
                    if (A_FAILED(status)) {
                        break;   
                    }
                }
                
                if (g_WifiMTE.GotDhcpOffer) {
                        /* issue get status command and wait for response */
                    g_WifiMTE.TestState = TEST_WAIT_WMI_STATS;
                    status = wmi_get_stats_cmd();
                }
            
                break;
            
            case TEST_WAIT_WMI_STATS:
                if (g_WifiMTE.ReceivedStats) {                    
                    g_WifiMTE.TestState = TEST_END_SUCCESS;
                }       
                break;           
            
            case TEST_END_SUCCESS:
                
                break;
            
            default:
                g_WifiMTE.TestState = TEST_GEN_FAILURE;
                A_ASSERT(FALSE);
                break;    
        }
        
        if (g_WifiMTE.TestState == TEST_END_SUCCESS) {
                /* all done */
            break;    
        }
    
    }
    
    if (g_WifiMTE.APConnected) {
            /* if we were connected, issue the disconnect command to disconnect from the AP */
        wmi_disconnect_cmd();
            /* before exiting make sure the target sends out the disconnect */    
        A_MDELAY(200);
    }
    
    g_WifiMTE.MteStatus = GetMTEStatus();   
        
    return status;
}
Beispiel #21
0
int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int Signal, int AckTimeoutMS)
{
    int status = 0;
    int      i;
    u8 buffer[4];
    
    A_MEMZERO(buffer, sizeof(buffer));
    
    do {
        
        if (Signal >= MBOX_SIG_HCI_BRIDGE_MAX) {
            status = A_EINVAL;
            break;    
        }
        
            /* set the last buffer to do the actual signal trigger */
        buffer[3] = (1 << Signal);
        
        status = HIFReadWrite(pDev->HIFDevice,
                              INT_WLAN_ADDRESS,
                              buffer,
                              sizeof(buffer),
                              HIF_WR_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
                              NULL);    
                          
        if (status) {
            break;    
        }
        
    } while (false);
    
    
    if (!status) {
            /* now read back the register to see if the bit cleared */
        while (AckTimeoutMS) {        
            status = HIFReadWrite(pDev->HIFDevice,
                                  INT_WLAN_ADDRESS,
                                  buffer,
                                  sizeof(buffer),
                                  HIF_RD_SYNC_BYTE_FIX,
                                  NULL);    
                          
            if (status) {
                break;    
            }
                            
            for (i = 0; i < sizeof(buffer); i++) {
                if (buffer[i] & (1 << Signal)) {
                    /* bit is still set */
                    break;    
                }   
            }
            
            if (i >= sizeof(buffer)) {
                /* done */
                break;    
            }
            
            AckTimeoutMS--;
            A_MDELAY(1);  
        }
        
        if (0 == AckTimeoutMS) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                ("DevGMboxSetTargetInterrupt : Ack Timed-out (sig:%d) \n",Signal));
            status = A_ERROR;    
        }        
    }
    
    return status;
    
}
static A_STATUS ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle, 
                                           HCI_TRANSPORT_PROPERTIES *pProps, 
                                           void                     *pContext)
{
    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
    A_STATUS              status;
    AR_SOFTC_DEV_T *arDev = pHcidevInfo->ar->arDev[0];

    
    pHcidevInfo->pHCIDev = HCIHandle;
    
    A_MEMCPY(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps));
    
    AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%lX, headroom:%d, tailroom:%d blockpad:%d) \n", 
            (unsigned long)HCIHandle, 
            pHcidevInfo->HCIProps.HeadRoom, 
            pHcidevInfo->HCIProps.TailRoom,
            pHcidevInfo->HCIProps.IOBlockPad));
    
#ifdef EXPORT_HCI_BRIDGE_INTERFACE
    A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)->hard_header_len);
#else
    A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= arDev->arNetDev->hard_header_len);
#endif
                             
        /* provide buffers */
    RefillRecvBuffers(pHcidevInfo, HCI_ACL_TYPE, MAX_ACL_RECV_BUFS);
    RefillRecvBuffers(pHcidevInfo, HCI_EVENT_TYPE, MAX_EVT_RECV_BUFS);
   
    do {
            /* start transport */
        status = HCI_TransportStart(pHcidevInfo->pHCIDev);
         
        if (A_FAILED(status)) {
            break;    
        }
        
        if (!pHcidevInfo->HciNormalMode) {
                /* in test mode, no need to go any further */
            break;    
        }

        /* The delay is required when AR6K is driving the BT reset line */
        /* where time is needed after the BT chip is out of reset (HCI_TransportStart) */
        /* and before the first HCI command is issued (AR3KConfigure) */
        /* FIXME */
        /* The delay should be configurable and be only applied when AR6K driving the BT */
        /* reset line. This could be done by some module parameter or based on some HW config */
        /* info. For now apply 100ms delay blindly */
        A_MDELAY(100);
        
        A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig));
        ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev;
        ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps;
#ifdef EXPORT_HCI_BRIDGE_INTERFACE
        ar3kconfig.pHIFDevice = (HIF_DEVICE *)(pHcidevInfo->HCITransHdl.hifDevice);
#else
        ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice;
#endif
        ar3kconfig.pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev;
        
        if (ar3khcibaud != 0) {
                /* user wants ar3k baud rate change */
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD;
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY;
            ar3kconfig.AR3KBaudRate = ar3khcibaud;    
        }
        
        if ((hciuartscale != 0) || (hciuartstep != 0)) {   
                /* user wants to tune HCI bridge UART scale/step values */
            ar3kconfig.AR6KScale = (A_UINT16)hciuartscale;
            ar3kconfig.AR6KStep = (A_UINT16)hciuartstep;           
            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP;
        }
        
            /* configure the AR3K device */  
		memcpy(ar3kconfig.bdaddr,arDev->bdaddr,6);       
        status = AR3KConfigure(&ar3kconfig);
        if (A_FAILED(status)) {
            extern unsigned int setuphci;
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Fail to configure AR3K. No device? Cleanup HCI\n"));
            pHcidevInfo->ar->exitCallback = NULL;
            ar6000_cleanup_hci(pHcidevInfo->ar);
            setuphci = 0;
            pHcidevInfo->ar->arBTSharing = 0;
            break; 
        }

        /* Make sure both AR6K and AR3K have power management enabled */
        if (ar3kconfig.PwrMgmtEnabled) {
            A_UINT32 address, hci_uart_pwr_mgmt_params;
            /* Fetch the address of the hi_hci_uart_pwr_mgmt_params instance in the host interest area */
            address = TARG_VTOP(pHcidevInfo->ar->arTargetType, 
                                HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar->arTargetType, hi_hci_uart_pwr_mgmt_params));
            status = ar6000_ReadRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params);
            hci_uart_pwr_mgmt_params &= 0xFFFF;
            /* wakeup timeout is [31:16] */
            hci_uart_pwr_mgmt_params |= (ar3kconfig.WakeupTimeout << 16);
            status |= ar6000_WriteRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params);
            if (A_OK != status) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to write hci_uart_pwr_mgmt_params!\n"));
            }

            /* Fetch the address of the hi_hci_uart_pwr_mgmt_params_ext instance in the host interest area */
            address = TARG_VTOP(pHcidevInfo->ar->arTargetType, 
                                HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar->arTargetType, hi_hci_uart_pwr_mgmt_params_ext));
            status = ar6000_WriteRegDiag(pHcidevInfo->ar->arHifDevice, &address, &ar3kconfig.IdleTimeout);
            if (A_OK != status) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to write hci_uart_pwr_mgmt_params_ext!\n"));
            }
        
            status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, TRUE);
            if (A_FAILED(status)) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to enable TLPM for AR6K! \n"));
            }
        }
        
        status = bt_register_hci(pHcidevInfo);
        
    } while (FALSE);

    return status; 
}