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); }
void __init ath6kl_sdio_init_msm(void) { printk("%s(): Enter\n", __func__); platform_driver_register(&ath6kl_pm_device); A_MDELAY(50); }
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; }
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);
/* 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; }
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; }
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; }
/* 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; }
/* 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 }
/* 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); }
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 */ }
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);
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; }
/* * 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; }
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 = ®List->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"); }
void __exit ath6kl_sdio_exit_msm(void) { platform_driver_unregister(&ath6kl_pm_device); A_MDELAY(1000); }
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, ðerType); 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; }
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; }