static int wl1271_suspend(struct device *dev) { /* Tell MMC/SDIO core it's OK to power down the card * (if it isn't already), but not to remove it completely */ struct sdio_func *func = dev_to_sdio_func(dev); struct wl1271 *wl = sdio_get_drvdata(func); mmc_pm_flag_t sdio_flags; int ret = 0; wl1271_debug(DEBUG_MAC80211, "wl1271 suspend. wow_enabled: %d", wl->wow_enabled); /* check whether sdio should keep power */ if (wl->wow_enabled) { sdio_flags = sdio_get_host_pm_caps(func); if (!(sdio_flags & MMC_PM_KEEP_POWER)) { wl1271_error("can't keep power while host " "is suspended"); ret = -EINVAL; goto out; } printk("\n\nSetting MMC_PM_KEEP_POWER\n"); /* keep power while host suspended */ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); if (ret) { wl1271_error("error while trying to keep power"); goto out; } /* release host */ sdio_release_host(func); } out: return ret; }
static int bcmsdh_sdmmc_suspend(struct device *pdev) { int err; sdioh_info_t *sdioh; struct sdio_func *func = dev_to_sdio_func(pdev); mmc_pm_flag_t sdio_flags; dev_err(pdev,"%s(%d) [%08x]\n",__func__, __LINE__,(unsigned int*) pdev); sd_err(("%s Enter\n", __FUNCTION__)); if (func->num != 2) return 0; sdioh = sdio_get_drvdata(func); err = bcmsdh_suspend(sdioh->bcmsdh); if (err) return err; sdio_flags = sdio_get_host_pm_caps(func); if (!(sdio_flags & MMC_PM_KEEP_POWER)) { sd_err(("%s: can't keep power while host is suspended\n", __FUNCTION__)); return -EINVAL; } /* keep power while host suspended */ err = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); if (err) { sd_err(("%s: error while trying to keep power\n", __FUNCTION__)); return err; } #if defined(OOB_INTR_ONLY) bcmsdh_oob_intr_set(sdioh->bcmsdh, FALSE); #endif dhd_mmc_suspend = TRUE; smp_mb(); return 0; }
static void r8712s_dev_remove(struct sdio_func *func) { _adapter *padapter = (_adapter*) (((struct dvobj_priv*)sdio_get_drvdata(func))->padapter); struct net_device *pnetdev = (struct net_device *)padapter->pnetdev; _func_exit_; if (padapter) { RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n")); // padapter->bSurpriseRemoved = _TRUE; if (pnetdev) unregister_netdev(pnetdev); //will call netdev_close() cancel_all_timer(padapter); r871x_dev_unload(padapter); rtw_free_drv_sw(padapter); sdio_claim_host(func); RT_TRACE(_module_hci_intfs_c_,_drv_err_,(" in dev_remove():sdio_claim_host !\n")); sdio_release_irq(func); RT_TRACE(_module_hci_intfs_c_,_drv_err_,(" in dev_remove():sdio_release_irq !\n")); sdio_disable_func(func); RT_TRACE(_module_hci_intfs_c_,_drv_err_,(" in dev_remove():sdio_disable_func !\n")); sdio_release_host(func); RT_TRACE(_module_hci_intfs_c_,_drv_err_,(" in dev_remove():sdio_release_host !\n")); } RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-dev_remove()\n")); _func_exit_; return; }
/** @brief This function handles client driver resume * * @param dev A pointer to device structure * @return BT_STATUS_SUCCESS */ int bt_sdio_resume(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); mmc_pm_flag_t pm_flags = 0; bt_private *priv = NULL; struct sdio_mmc_card *cardp; struct hci_dev *hcidev; ENTER(); if (func) { pm_flags = sdio_get_host_pm_caps(func); PRINTM(CMD, "BT: %s: resume: PM flags = 0x%x\n", sdio_func_id(func), pm_flags); cardp = sdio_get_drvdata(func); if (!cardp || !cardp->priv) { PRINTM(ERROR, "BT: Card or priv structure is not valid\n"); LEAVE(); return BT_STATUS_SUCCESS; } } else { PRINTM(ERROR, "BT: sdio_func is not specified\n"); LEAVE(); return BT_STATUS_SUCCESS; } priv = cardp->priv; priv->adapter->is_suspended = FALSE; hcidev = priv->bt_dev.hcidev; PRINTM(CMD, "BT %s: SDIO resume\n", hcidev->name); hci_resume_dev(hcidev); sbi_wakeup_firmware(priv); priv->adapter->hs_state = HS_DEACTIVATED; PRINTM(CMD, "BT:%s: HS DEACTIVATED in Resume!\n", hcidev->name); LEAVE(); return BT_STATUS_SUCCESS; }
/* * Process an interrupt from the SDIO card * * FIXME: need to process other events that are not just ready-to-read * * Checks there is data ready and then proceeds to read it. */ static void i2400ms_irq(struct sdio_func *func) { int ret; struct i2400ms *i2400ms = sdio_get_drvdata(func); struct device *dev = &func->dev; int val; d_fnstart(6, dev, "(i2400ms %p)\n", i2400ms); val = sdio_readb(func, I2400MS_INTR_STATUS_ADDR, &ret); if (ret < 0) { dev_err(dev, "RX: Can't read interrupt status: %d\n", ret); goto error_no_irq; } if (!val) { dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n"); goto error_no_irq; } sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret); i2400ms_rx(i2400ms); error_no_irq: d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms); return; }
static void mwifiex_sdio_remove(struct sdio_func *func) { struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; struct mwifiex_private *priv; int i; pr_debug("info: SDIO func num=%d\n", func->num); card = sdio_get_drvdata(func); if (!card) return; adapter = card->adapter; if (!adapter || !adapter->priv_num) return; if (user_rmmod) { if (adapter->is_suspended) mwifiex_sdio_resume(adapter->dev); for (i = 0; i < adapter->priv_num; i++) if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) && adapter->priv[i]->media_connected) mwifiex_deauthenticate(adapter->priv[i], NULL); priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); mwifiex_disable_auto_ds(priv); mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN); } mwifiex_remove_card(card->adapter, &add_remove_card_sem); kfree(card); }
static void smssdio_interrupt(struct sdio_func *func) { int ret, isr; struct smssdio_device *smsdev; struct smscore_buffer_t *cb; struct SmsMsgHdr_ST *hdr; size_t size; smsdev = sdio_get_drvdata(func); /* * The interrupt register has no defined meaning. It is just * a way of turning of the level triggered interrupt. */ isr = sdio_readb(func, SMSSDIO_INT, &ret); if (ret) { dev_err(&smsdev->func->dev, "Unable to read interrupt register!\n"); return; } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { dev_err(&smsdev->func->dev, "Unable to allocate data buffer!\n"); return; } ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1); if (ret) { dev_err(&smsdev->func->dev, "Error %d reading initial block!\n", ret); return; } hdr = cb->p; if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) { smsdev->split_cb = cb; return; } size = hdr->msgLength - smsdev->func->cur_blksize; } else { cb = smsdev->split_cb; hdr = cb->p; size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST); smsdev->split_cb = NULL; } if (hdr->msgLength > smsdev->func->cur_blksize) { void *buffer; size = ALIGN(size, 128); buffer = cb->p + hdr->msgLength; BUG_ON(smsdev->func->cur_blksize != 128); /* * First attempt to transfer all of it in one go... */ ret = sdio_read_blocks(smsdev->func, buffer, SMSSDIO_DATA, size / 128); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); dev_err(&smsdev->func->dev, "Error %d reading data from card!\n", ret); return; } /* * ..then fall back to one block at a time if that is * not possible... * * (we have to do this manually because of the * problem with the "increase address" bit) */ if (ret == -EINVAL) { while (size) { ret = sdio_read_blocks(smsdev->func, buffer, SMSSDIO_DATA, 1); if (ret) { smscore_putbuffer(smsdev->coredev, cb); dev_err(&smsdev->func->dev, "Error %d reading " "data from card!\n", ret); return; } buffer += smsdev->func->cur_blksize; if (size > smsdev->func->cur_blksize) size -= smsdev->func->cur_blksize; else size = 0; } } } cb->size = hdr->msgLength; cb->offset = 0; smscore_onresponse(smsdev->coredev, cb); }
/** @brief This function handles client driver suspend * * @param dev A pointer to device structure * @return BT_STATUS_SUCCESS or other error no. */ int bt_sdio_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); mmc_pm_flag_t pm_flags = 0; bt_private *priv = NULL; struct sdio_mmc_card *cardp; struct hci_dev *hcidev; ENTER(); if (func) { pm_flags = sdio_get_host_pm_caps(func); PRINTM(CMD, "BT: %s: suspend: PM flags = 0x%x\n", sdio_func_id(func), pm_flags); if (!(pm_flags & MMC_PM_KEEP_POWER)) { PRINTM(ERROR, "BT: %s: cannot remain alive while host is suspended\n", sdio_func_id(func)); return -ENOSYS; } cardp = sdio_get_drvdata(func); if (!cardp || !cardp->priv) { PRINTM(ERROR, "BT: Card or priv structure is not valid\n"); LEAVE(); return BT_STATUS_SUCCESS; } } else { PRINTM(ERROR, "BT: sdio_func is not specified\n"); LEAVE(); return BT_STATUS_SUCCESS; } priv = cardp->priv; if ((pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) { if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) { PRINTM(CMD, "BT: HS not actived, suspend fail!\n"); LEAVE(); return -EBUSY; } } hcidev = priv->bt_dev.hcidev; PRINTM(CMD, "BT %s: SDIO suspend\n", hcidev->name); hci_suspend_dev(hcidev); skb_queue_purge(&priv->adapter->tx_queue); priv->adapter->is_suspended = TRUE; LEAVE(); /* We will keep the power when hs enabled successfully */ if ((pm_keep_power) && (priv->adapter->hs_state == HS_ACTIVATED)) { #ifdef MMC_PM_SKIP_RESUME_PROBE PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER and " "MMC_PM_SKIP_RESUME_PROBE\n"); return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER | MMC_PM_SKIP_RESUME_PROBE); #else PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER\n"); return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); #endif } else { PRINTM(CMD, "BT: suspend without MMC_PM_KEEP_POWER\n"); return BT_STATUS_SUCCESS; } }
static void iwm_sdio_isr(struct sdio_func *func) { struct iwm_priv *iwm; struct iwm_sdio_priv *hw; struct iwm_rx_info *rx_info; struct sk_buff *skb; unsigned long buf_size, read_size; int ret; u8 val; hw = sdio_get_drvdata(func); iwm = hw_to_iwm(hw); buf_size = hw->blk_size; /* We're checking the status */ val = sdio_readb(func, IWM_SDIO_INTR_STATUS_ADDR, &ret); if (val == 0 || ret < 0) { IWM_ERR(iwm, "Wrong INTR_STATUS\n"); return; } /* See if we have free buffers */ if (skb_queue_len(&iwm->rx_list) > IWM_RX_LIST_SIZE) { IWM_ERR(iwm, "No buffer for more Rx frames\n"); return; } /* We first read the transaction size */ read_size = sdio_readb(func, IWM_SDIO_INTR_GET_SIZE_ADDR + 1, &ret); read_size = read_size << 8; if (ret < 0) { IWM_ERR(iwm, "Couldn't read the xfer size\n"); return; } /* We need to clear the INT register */ sdio_writeb(func, 1, IWM_SDIO_INTR_CLEAR_ADDR, &ret); if (ret < 0) { IWM_ERR(iwm, "Couldn't clear the INT register\n"); return; } while (buf_size < read_size) buf_size <<= 1; skb = dev_alloc_skb(buf_size); if (!skb) { IWM_ERR(iwm, "Couldn't alloc RX skb\n"); return; } rx_info = skb_to_rx_info(skb); rx_info->rx_size = read_size; rx_info->rx_buf_size = buf_size; /* Now we can read the actual buffer */ ret = sdio_memcpy_fromio(func, skb_put(skb, read_size), IWM_SDIO_DATA_ADDR, read_size); /* The skb is put on a driver's specific Rx SKB list */ skb_queue_tail(&iwm->rx_list, skb); /* We can now schedule the actual worker */ queue_work(hw->isr_wq, &hw->isr_worker); }
static void ks_sdio_interrupt(struct sdio_func *func) { int retval; struct ks_sdio_card *card; struct ks_wlan_private *priv; unsigned char status, rsize, rw_data; card = sdio_get_drvdata(func); priv = card->priv; DPRINTK(4, "\n"); if (priv->dev_state >= DEVICE_STATE_BOOT) { retval = ks7010_sdio_read(priv, INT_PENDING, &status, sizeof(status)); if (retval) { DPRINTK(1, "read INT_PENDING Failed!!(%d)\n", retval); goto intr_out; } DPRINTK(4, "INT_PENDING=%02X\n", rw_data); /* schedule task for interrupt status */ /* bit7 -> Write General Communication B register */ /* read (General Communication B register) */ /* bit5 -> Write Status Idle */ /* bit2 -> Read Status Busy */ if (status & INT_GCR_B || atomic_read(&priv->psstatus.status) == PS_SNOOZE) { retval = ks7010_sdio_read(priv, GCR_B, &rw_data, sizeof(rw_data)); if (retval) { DPRINTK(1, " error : GCR_B=%02X\n", rw_data); goto intr_out; } /* DPRINTK(1, "GCR_B=%02X\n", rw_data); */ if (rw_data == GCR_B_ACTIVE) { if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) { atomic_set(&priv->psstatus.status, PS_WAKEUP); priv->wakeup_count = 0; } complete(&priv->psstatus.wakeup_wait); } } do { /* read (WriteStatus/ReadDataSize FN1:00_0014) */ retval = ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data, sizeof(rw_data)); if (retval) { DPRINTK(1, " error : WSTATUS_RSIZE=%02X\n", rw_data); goto intr_out; } DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data); rsize = rw_data & RSIZE_MASK; if (rsize) { /* Read schedule */ ks_wlan_hw_rx((void *)priv, (uint16_t) (((rsize) << 4))); } if (rw_data & WSTATUS_MASK) { #if 0 if (status & INT_WRITE_STATUS && !cnt_txqbody(priv)) { /* dummy write for interrupt clear */ rw_data = 0; retval = ks7010_sdio_write(priv, DATA_WINDOW, &rw_data, sizeof(rw_data)); if (retval) { DPRINTK(1, "write DATA_WINDOW Failed!!(%d)\n", retval); } status &= ~INT_WRITE_STATUS; } else { #endif if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) { if (cnt_txqbody(priv)) { ks_wlan_hw_wakeup_request(priv); queue_delayed_work (priv->ks_wlan_hw. ks7010sdio_wq, &priv->ks_wlan_hw. rw_wq, 1); return; } } else { tx_device_task((void *)priv); } #if 0 } #endif } } while (rsize); } intr_out: queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq, &priv->ks_wlan_hw.rw_wq, 0); return; }
static void iwm_sdio_isr(struct sdio_func *func) { struct iwm_priv *iwm; struct iwm_sdio_priv *hw; struct iwm_rx_info *rx_info; struct sk_buff *skb; unsigned long buf_size, read_size; int ret; u8 val; hw = sdio_get_drvdata(func); iwm = hw_to_iwm(hw); buf_size = hw->blk_size; val = sdio_readb(func, IWM_SDIO_INTR_STATUS_ADDR, &ret); if (val == 0 || ret < 0) { IWM_ERR(iwm, "Wrong INTR_STATUS\n"); return; } if (skb_queue_len(&iwm->rx_list) > IWM_RX_LIST_SIZE) { IWM_ERR(iwm, "No buffer for more Rx frames\n"); return; } read_size = sdio_readb(func, IWM_SDIO_INTR_GET_SIZE_ADDR + 1, &ret); read_size = read_size << 8; if (ret < 0) { IWM_ERR(iwm, "Couldn't read the xfer size\n"); return; } sdio_writeb(func, 1, IWM_SDIO_INTR_CLEAR_ADDR, &ret); if (ret < 0) { IWM_ERR(iwm, "Couldn't clear the INT register\n"); return; } while (buf_size < read_size) buf_size <<= 1; skb = dev_alloc_skb(buf_size); if (!skb) { IWM_ERR(iwm, "Couldn't alloc RX skb\n"); return; } rx_info = skb_to_rx_info(skb); rx_info->rx_size = read_size; rx_info->rx_buf_size = buf_size; ret = sdio_memcpy_fromio(func, skb_put(skb, read_size), IWM_SDIO_DATA_ADDR, read_size); skb_queue_tail(&iwm->rx_list, skb); queue_work(hw->isr_wq, &hw->isr_worker); }
static struct hif_device *ath6kl_get_hifdev(struct sdio_func *func) { return (struct hif_device *) sdio_get_drvdata(func); }
static void ks7010_sdio_remove(struct sdio_func *func) { int ret; struct ks_sdio_card *card; struct ks_wlan_private *priv; struct net_device *netdev; DPRINTK(1, "ks7010_sdio_remove()\n"); card = sdio_get_drvdata(func); if (card == NULL) return; DPRINTK(1, "priv = card->priv\n"); priv = card->priv; netdev = priv->net_dev; if (priv) { ks_wlan_net_stop(netdev); DPRINTK(1, "ks_wlan_net_stop\n"); /* interrupt disable */ sdio_claim_host(func); sdio_writeb(func, 0, INT_ENABLE, &ret); sdio_writeb(func, 0xff, INT_PENDING, &ret); sdio_release_host(func); DPRINTK(1, "interrupt disable\n"); /* send stop request to MAC */ { struct hostif_stop_request_t *pp; pp = (struct hostif_stop_request_t *) kzalloc(hif_align_size(sizeof(*pp)), GFP_KERNEL); if (pp == NULL) { DPRINTK(3, "allocate memory failed..\n"); return; /* to do goto ni suru */ } pp->header.size = cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); pp->header.event = cpu_to_le16((uint16_t) HIF_STOP_REQ); sdio_claim_host(func); write_to_device(priv, (unsigned char *)pp, hif_align_size(sizeof(*pp))); sdio_release_host(func); kfree(pp); } DPRINTK(1, "STOP Req\n"); if (priv->ks_wlan_hw.ks7010sdio_wq) { flush_workqueue(priv->ks_wlan_hw.ks7010sdio_wq); destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_wq); } DPRINTK(1, "destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_wq);\n"); hostif_exit(priv); DPRINTK(1, "hostif_exit\n"); unregister_netdev(netdev); trx_device_exit(priv); if (priv->ks_wlan_hw.read_buf) { kfree(priv->ks_wlan_hw.read_buf); } free_netdev(priv->net_dev); card->priv = NULL; } sdio_claim_host(func); sdio_release_irq(func); DPRINTK(1, "sdio_release_irq()\n"); sdio_disable_func(func); DPRINTK(1, "sdio_disable_func()\n"); sdio_release_host(func); sdio_set_drvdata(func, NULL); kfree(card); DPRINTK(1, "kfree()\n"); DPRINTK(5, " Bye !!\n"); return; }
static void rtw_dev_remove(struct sdio_func *func) { PADAPTER padapter; struct net_device *pnetdev; #ifdef CONFIG_IOCTL_CFG80211 struct wireless_dev *wdev; #endif _func_enter_; RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_dev_remove\n")); padapter = ((struct dvobj_priv*)sdio_get_drvdata(func))->padapter; #ifdef CONFIG_IOCTL_CFG80211 wdev = padapter->rtw_wdev; #endif #if defined(CONFIG_HAS_EARLYSUSPEND ) || defined(CONFIG_ANDROID_POWER) rtw_unregister_early_suspend(&padapter->pwrctrlpriv); #endif if (padapter->bSurpriseRemoved == _FALSE) { // test surprise remove int err; sdio_claim_host(func); sdio_readb(func, 0, &err); sdio_release_host(func); if (err == -ENOMEDIUM) { padapter->bSurpriseRemoved = _TRUE; DBG_871X(KERN_NOTICE "%s: device had been removed!\n", __func__); } } #ifdef CONFIG_HOSTAPD_MLME hostapd_mode_unload(padapter); #endif LeaveAllPowerSaveMode(padapter); pnetdev = (struct net_device*)padapter->pnetdev; if (pnetdev) { unregister_netdev(pnetdev); //will call netdev_close() RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("rtw_dev_remove: unregister netdev\n")); #ifdef CONFIG_PROC_DEBUG rtw_proc_remove_one(pnetdev); #endif } else { RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("rtw_dev_remove: NO padapter->pnetdev!\n")); } rtw_cancel_all_timer(padapter); rtw_dev_unload(padapter); // interface deinit sdio_deinit(padapter); RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("rtw_dev_remove: deinit intf complete!\n")); rtw_free_drv_sw(padapter); #ifdef CONFIG_IOCTL_CFG80211 rtw_wdev_free(wdev); #endif RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_dev_remove\n")); _func_exit_; }
static int sqn_handle_mac_addr_tag(struct sdio_func *func, u8 *data, u32 length) { int rv = 0; struct sqn_private *priv = ((struct sqn_sdio_card *)sdio_get_drvdata(func))->priv; sqn_pr_enter(); /* * This tag could contain one or two mac addresses in string * form, delimited by some symbol (space or something else). * Each mac address written as a string has constant length. * Thus we can determine the number of mac addresses by the * length of the tag: * * mac addr length in string form: XX:XX:XX:XX:XX:XX = 17 bytes * tag length: 17 bytes [ + 1 byte + 17 bytes ] */ #define MAC_ADDR_STRING_LEN 17 /* * If we have only one mac addr we should increment it by one * and use it. * If we have two mac addresses we should use a second one. */ if (MAC_ADDR_STRING_LEN <= length && length < 2 * MAC_ADDR_STRING_LEN + 1) { sqn_pr_dbg("single mac address\n"); /* we have only one mac addr */ get_mac_addr_from_str(data, length, priv->mac_addr); // Andrew 0720 // ++(priv->mac_addr[ETH_ALEN - 1]) // real MAC: 38:E6:D8:86:00:00 // hboot will store: 38:E6:D8:85:FF:FF (minus 1) // sdio need to recovery it by plusing 1: 38:E6:D8:86:00:00 (plus 1) if ((++(priv->mac_addr[ETH_ALEN - 1])) == 0x00) if ((++(priv->mac_addr[ETH_ALEN - 2])) == 0x00) if ((++(priv->mac_addr[ETH_ALEN - 3])) == 0x00) if ((++(priv->mac_addr[ETH_ALEN - 4])) == 0x00) if ((++(priv->mac_addr[ETH_ALEN - 5])) == 0x00) ++(priv->mac_addr[ETH_ALEN - 6]); } else if (2 * MAC_ADDR_STRING_LEN + 1 == length) { /* we have two macs */ sqn_pr_dbg("two mac addresses, using second\n"); get_mac_addr_from_str(data + MAC_ADDR_STRING_LEN + 1 , length - (MAC_ADDR_STRING_LEN + 1), priv->mac_addr); } else { /* incorrect data length */ sqn_pr_err("can't get mac address from bootloader" " - incorrect mac address length\n"); rv = -1; goto out; } sqn_pr_info("setting MAC address from bootloader: " "%02x:%02x:%02x:%02x:%02x:%02x\n", priv->mac_addr[0] , priv->mac_addr[1], priv->mac_addr[2], priv->mac_addr[3] , priv->mac_addr[4], priv->mac_addr[5]); out: sqn_pr_leave(); return rv; }
static void iwmct_irq(struct sdio_func *func) { struct iwmct_priv *priv; int val, ret; int iosize; int addr = IWMC_SDIO_INTR_GET_SIZE_ADDR; struct iwmct_work_struct *read_req; priv = sdio_get_drvdata(func); LOG_TRACE(priv, IRQ, "enter iwmct_irq\n"); /* read the function's status register */ val = sdio_readb(func, IWMC_SDIO_INTR_STATUS_ADDR, &ret); LOG_TRACE(priv, IRQ, "iir value = %d, ret=%d\n", val, ret); if (!val) { LOG_ERROR(priv, IRQ, "iir = 0, exiting ISR\n"); goto exit_clear_intr; } /* * read 2 bytes of the transaction size * IMPORTANT: sdio transaction size has to be read before clearing * sdio interrupt!!! */ val = sdio_readb(priv->func, addr++, &ret); iosize = val; val = sdio_readb(priv->func, addr++, &ret); iosize += val << 8; LOG_INFO(priv, IRQ, "READ size %d\n", iosize); if (iosize == 0) { LOG_ERROR(priv, IRQ, "READ size %d, exiting ISR\n", iosize); goto exit_clear_intr; } /* allocate a work structure to pass iosize to the worker */ read_req = kzalloc(sizeof(struct iwmct_work_struct), GFP_KERNEL); if (!read_req) { LOG_ERROR(priv, IRQ, "failed to allocate read_req, exit ISR\n"); goto exit_clear_intr; } INIT_LIST_HEAD(&read_req->list); read_req->iosize = iosize; list_add_tail(&priv->read_req_list, &read_req->list); /* clear the function's interrupt request bit (write 1 to clear) */ sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret); queue_work(priv->wq, &priv->isr_worker); LOG_TRACE(priv, IRQ, "exit iwmct_irq\n"); return; exit_clear_intr: /* clear the function's interrupt request bit (write 1 to clear) */ sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret); }
/** @brief This function handles client driver suspend * * @param dev A pointer to device structure * @return BT_STATUS_SUCCESS or other error no. */ int bt_sdio_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); mmc_pm_flag_t pm_flags = 0; bt_private *priv = NULL; struct sdio_mmc_card *cardp; struct m_dev *m_dev = NULL; ENTER(); pm_flags = sdio_get_host_pm_caps(func); PRINTM(CMD, "BT: %s: suspend: PM flags = 0x%x\n", sdio_func_id(func), pm_flags); if (!(pm_flags & MMC_PM_KEEP_POWER)) { PRINTM(ERROR, "BT: %s: cannot remain alive while host is suspended\n", sdio_func_id(func)); return -ENOSYS; } cardp = sdio_get_drvdata(func); if (!cardp || !cardp->priv) { PRINTM(ERROR, "BT: Card or priv structure is not valid\n"); LEAVE(); return BT_STATUS_SUCCESS; } priv = cardp->priv; if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) { /* disable FM event mask */ if ((priv->bt_dev.m_dev[FM_SEQ].dev_type == FM_TYPE) && test_bit(HCI_RUNNING, &(priv->bt_dev.m_dev[FM_SEQ].flags))) fm_set_intr_mask(priv, FM_DISABLE_INTR_MASK); if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) { PRINTM(CMD, "BT: HS not actived, suspend fail!\n"); if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) { PRINTM(CMD, "BT: HS not actived the second time, force to suspend!\n"); } } } m_dev = &(priv->bt_dev.m_dev[BT_SEQ]); PRINTM(CMD, "BT %s: SDIO suspend\n", m_dev->name); mbt_hci_suspend_dev(m_dev); skb_queue_purge(&priv->adapter->tx_queue); priv->adapter->is_suspended = TRUE; LEAVE(); /* We will keep the power when hs enabled successfully */ if ((mbt_pm_keep_power) && (priv->adapter->hs_state == HS_ACTIVATED)) { #ifdef MMC_PM_SKIP_RESUME_PROBE PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER and " "MMC_PM_SKIP_RESUME_PROBE\n"); return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER | MMC_PM_SKIP_RESUME_PROBE); #else PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER\n"); return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); #endif } else { PRINTM(CMD, "BT: suspend without MMC_PM_KEEP_POWER\n"); return BT_STATUS_SUCCESS; } }
static void ks_sdio_interrupt(struct sdio_func *func) { int ret; struct ks_sdio_card *card; struct ks_wlan_private *priv; unsigned char status, rsize, byte; card = sdio_get_drvdata(func); priv = card->priv; DPRINTK(4, "\n"); if (priv->dev_state < DEVICE_STATE_BOOT) goto queue_delayed_work; ret = ks7010_sdio_readb(priv, INT_PENDING, &status); if (ret) { DPRINTK(1, "error : INT_PENDING\n"); goto queue_delayed_work; } DPRINTK(4, "INT_PENDING=%02X\n", status); /* schedule task for interrupt status */ /* bit7 -> Write General Communication B register */ /* read (General Communication B register) */ /* bit5 -> Write Status Idle */ /* bit2 -> Read Status Busy */ if (status & INT_GCR_B || atomic_read(&priv->psstatus.status) == PS_SNOOZE) { ret = ks7010_sdio_readb(priv, GCR_B, &byte); if (ret) { DPRINTK(1, " error : GCR_B\n"); goto queue_delayed_work; } if (byte == GCR_B_ACTIVE) { if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) { atomic_set(&priv->psstatus.status, PS_WAKEUP); priv->wakeup_count = 0; } complete(&priv->psstatus.wakeup_wait); } } do { /* read (WriteStatus/ReadDataSize FN1:00_0014) */ ret = ks7010_sdio_readb(priv, WSTATUS_RSIZE, &byte); if (ret) { DPRINTK(1, " error : WSTATUS_RSIZE\n"); goto queue_delayed_work; } DPRINTK(4, "WSTATUS_RSIZE=%02X\n", byte); rsize = byte & RSIZE_MASK; if (rsize != 0) /* Read schedule */ ks_wlan_hw_rx(priv, (uint16_t)(rsize << 4)); if (byte & WSTATUS_MASK) { if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) { if (cnt_txqbody(priv)) { ks_wlan_hw_wakeup_request(priv); queue_delayed_work(priv->wq, &priv->rw_dwork, 1); return; } } else { tx_device_task(priv); } } } while (rsize); queue_delayed_work: queue_delayed_work(priv->wq, &priv->rw_dwork, 0); }
static void ks7010_sdio_remove(struct sdio_func *func) { int ret; struct ks_sdio_card *card; struct ks_wlan_private *priv; card = sdio_get_drvdata(func); if (!card) return; DPRINTK(1, "priv = card->priv\n"); priv = card->priv; if (priv) { struct net_device *netdev = priv->net_dev; ks_wlan_net_stop(netdev); DPRINTK(1, "ks_wlan_net_stop\n"); /* interrupt disable */ sdio_claim_host(func); sdio_writeb(func, 0, INT_ENABLE, &ret); sdio_writeb(func, 0xff, INT_PENDING, &ret); sdio_release_host(func); DPRINTK(1, "interrupt disable\n"); ret = send_stop_request(func); if (ret) /* memory allocation failure */ return; DPRINTK(1, "STOP Req\n"); if (priv->wq) { flush_workqueue(priv->wq); destroy_workqueue(priv->wq); } DPRINTK(1, "destroy_workqueue(priv->wq);\n"); hostif_exit(priv); DPRINTK(1, "hostif_exit\n"); unregister_netdev(netdev); trx_device_exit(priv); free_netdev(priv->net_dev); card->priv = NULL; } sdio_claim_host(func); sdio_release_irq(func); DPRINTK(1, "sdio_release_irq()\n"); sdio_disable_func(func); DPRINTK(1, "sdio_disable_func()\n"); sdio_release_host(func); sdio_set_drvdata(func, NULL); kfree(card); DPRINTK(1, "kfree()\n"); DPRINTK(5, " Bye !!\n"); }
static void esp_sdio_remove(struct sdio_func *func) { struct esp_sdio_ctrl *sctrl = NULL; esp_dbg(ESP_SHOW, "%s enter\n", __func__); sctrl = sdio_get_drvdata(func); if (sctrl == NULL) { esp_dbg(ESP_DBG_ERROR, "%s no sctrl\n", __func__); return; } do { if (sctrl->epub == NULL) { esp_dbg(ESP_DBG_ERROR, "%s epub null\n", __func__); break; } sctrl->epub->sdio_state = sif_sdio_state; if(sif_sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT){ if (sctrl->epub->sip) { sip_detach(sctrl->epub->sip); sctrl->epub->sip = NULL; esp_dbg(ESP_DBG_TRACE, "%s sip detached \n", __func__); } #ifdef USE_EXT_GPIO if (sif_get_ate_config() == 0) ext_gpio_deinit(); #endif } else { //sif_disable_target_interrupt(sctrl->epub); atomic_set(&sctrl->epub->sip->state, SIP_STOP); sif_disable_irq(sctrl->epub); } #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)) esdio_power_off(sctrl); esp_dbg(ESP_DBG_TRACE, "%s power off \n", __func__); #endif /* kernel < 3.3.0 */ #ifdef TEST_MODE test_exit_netlink(); #endif /* TEST_MODE */ if(sif_sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT){ esp_pub_dealloc_mac80211(sctrl->epub); esp_dbg(ESP_DBG_TRACE, "%s dealloc mac80211 \n", __func__); if (sctrl->dma_buffer) { kfree(sctrl->dma_buffer); sctrl->dma_buffer = NULL; esp_dbg(ESP_DBG_TRACE, "%s free dma_buffer \n", __func__); } kfree(sctrl); } } while (0); sdio_set_drvdata(func,NULL); esp_dbg(ESP_DBG_TRACE, "eagle sdio remove complete\n"); }
static void smssdio_interrupt(struct sdio_func *func) { int ret; struct smssdio_device *smsdev; struct smscore_buffer_t *cb; struct sms_msg_hdr *hdr; size_t size; smsdev = sdio_get_drvdata(func); /* * The interrupt register has no defined meaning. It is just * a way of turning of the level triggered interrupt. */ (void)sdio_readb(func, SMSSDIO_INT, &ret); if (ret) { pr_err("Unable to read interrupt register!\n"); return; } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { pr_err("Unable to allocate data buffer!\n"); return; } ret = sdio_memcpy_fromio(smsdev->func, cb->p, SMSSDIO_DATA, SMSSDIO_BLOCK_SIZE); if (ret) { pr_err("Error %d reading initial block!\n", ret); return; } hdr = cb->p; if (hdr->msg_flags & MSG_HDR_FLAG_SPLIT_MSG) { smsdev->split_cb = cb; return; } if (hdr->msg_length > smsdev->func->cur_blksize) size = hdr->msg_length - smsdev->func->cur_blksize; else size = 0; } else { cb = smsdev->split_cb; hdr = cb->p; size = hdr->msg_length - sizeof(struct sms_msg_hdr); smsdev->split_cb = NULL; } if (size) { void *buffer; buffer = cb->p + (hdr->msg_length - size); size = ALIGN(size, SMSSDIO_BLOCK_SIZE); BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE); /* * First attempt to transfer all of it in one go... */ ret = sdio_memcpy_fromio(smsdev->func, buffer, SMSSDIO_DATA, size); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); pr_err("Error %d reading data from card!\n", ret); return; } /* * ..then fall back to one block at a time if that is * not possible... * * (we have to do this manually because of the * problem with the "increase address" bit) */ if (ret == -EINVAL) { while (size) { ret = sdio_memcpy_fromio(smsdev->func, buffer, SMSSDIO_DATA, smsdev->func->cur_blksize); if (ret) { smscore_putbuffer(smsdev->coredev, cb); pr_err("Error %d reading data from card!\n", ret); return; } buffer += smsdev->func->cur_blksize; if (size > smsdev->func->cur_blksize) size -= smsdev->func->cur_blksize; else size = 0; } } } cb->size = hdr->msg_length; cb->offset = 0; smsendian_handle_rx_message((struct sms_msg_data *) cb->p); smscore_onresponse(smsdev->coredev, cb); }
/** @brief This function handles client driver suspend * * @param dev A pointer to device structure * @return MLAN_STATUS_SUCCESS or error code */ int woal_sdio_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); mmc_pm_flag_t pm_flags = 0; moal_handle *handle = NULL; struct sdio_mmc_card *cardp; int i, retry_num = 8; int ret = MLAN_STATUS_SUCCESS; int hs_actived = 0; mlan_ds_ps_info pm_info; ENTER(); PRINTM(MCMND, "<--- Enter woal_sdio_suspend --->\n"); pm_flags = sdio_get_host_pm_caps(func); PRINTM(MCMND, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func), pm_flags); if (!(pm_flags & MMC_PM_KEEP_POWER)) { PRINTM(MERROR, "%s: cannot remain alive while host is suspended\n", sdio_func_id(func)); LEAVE(); return -ENOSYS; } cardp = sdio_get_drvdata(func); if (!cardp || !cardp->handle) { PRINTM(MERROR, "Card or moal_handle structure is not valid\n"); LEAVE(); return MLAN_STATUS_SUCCESS; } handle = cardp->handle; if (handle->is_suspended == MTRUE) { PRINTM(MWARN, "Device already suspended\n"); LEAVE(); return MLAN_STATUS_SUCCESS; } if (handle->fw_dump) { PRINTM(MMSG, "suspend not allowed while FW dump!"); ret = -EBUSY; goto done; } handle->suspend_fail = MFALSE; memset(&pm_info, 0, sizeof(pm_info)); for (i = 0; i < retry_num; i++) { if (MLAN_STATUS_SUCCESS == woal_get_pm_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), &pm_info)) { if (pm_info.is_suspend_allowed == MTRUE) break; else PRINTM(MMSG, "Suspend not allowed and retry again\n"); } woal_sched_timeout(100); } if (pm_info.is_suspend_allowed == MFALSE) { PRINTM(MMSG, "Suspend not allowed\n"); ret = -EBUSY; goto done; } for (i = 0; i < handle->priv_num; i++) netif_device_detach(handle->priv[i]->netdev); if (pm_keep_power) { /* Enable the Host Sleep */ #ifdef MMC_PM_FUNC_SUSPENDED handle->suspend_notify_req = MTRUE; #endif hs_actived = woal_enable_hs(woal_get_priv (handle, MLAN_BSS_ROLE_ANY)); #ifdef MMC_PM_FUNC_SUSPENDED handle->suspend_notify_req = MFALSE; #endif if (hs_actived) { #ifdef MMC_PM_SKIP_RESUME_PROBE PRINTM(MCMND, "suspend with MMC_PM_KEEP_POWER and MMC_PM_SKIP_RESUME_PROBE\n"); ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER | MMC_PM_SKIP_RESUME_PROBE); #else PRINTM(MCMND, "suspend with MMC_PM_KEEP_POWER\n"); ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); #endif } else { PRINTM(MMSG, "HS not actived, suspend fail!"); handle->suspend_fail = MTRUE; for (i = 0; i < handle->priv_num; i++) netif_device_attach(handle->priv[i]->netdev); ret = -EBUSY; goto done; } } /* Indicate device suspended */ handle->is_suspended = MTRUE; done: PRINTM(MCMND, "<--- Leave woal_sdio_suspend --->\n"); LEAVE(); return ret; }
static int rtw_sdio_suspend(struct device *dev) { struct sdio_func *func =dev_to_sdio_func(dev); struct dvobj_priv *psdpriv = sdio_get_drvdata(func); _adapter *padapter = psdpriv->padapter; struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct net_device *pnetdev = padapter->pnetdev; int ret = 0; u32 start_time = rtw_get_current_time(); _func_enter_; DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid); if((!padapter->bup) || (padapter->bDriverStopped)||(padapter->bSurpriseRemoved)) { DBG_871X("%s bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", __FUNCTION__ ,padapter->bup, padapter->bDriverStopped,padapter->bSurpriseRemoved); goto exit; } pwrpriv->bInSuspend = _TRUE; rtw_cancel_all_timer(padapter); LeaveAllPowerSaveMode(padapter); //padapter->net_closed = _TRUE; //s1. if(pnetdev) { netif_carrier_off(pnetdev); netif_stop_queue(pnetdev); } #ifdef CONFIG_WOWLAN padapter->pwrctrlpriv.bSupportWakeOnWlan=_TRUE; #else //s2. //s2-1. issue rtw_disassoc_cmd to fw disconnect_hdl(padapter, NULL); //rtw_disassoc_cmd(padapter); #endif #ifdef CONFIG_LAYER2_ROAMING_RESUME if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) ) { DBG_871X("%s %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n",__FUNCTION__, pmlmepriv->cur_network.network.Ssid.Ssid, MAC_ARG(pmlmepriv->cur_network.network.MacAddress), pmlmepriv->cur_network.network.Ssid.SsidLength, pmlmepriv->assoc_ssid.SsidLength); pmlmepriv->to_roaming = 1; } #endif //s2-2. indicate disconnect to os rtw_indicate_disconnect(padapter); //s2-3. rtw_free_assoc_resources(padapter, 1); //s2-4. rtw_free_network_queue(padapter, _TRUE); rtw_led_control(padapter, LED_CTL_POWER_OFF); rtw_dev_unload(padapter); exit: DBG_871X("<=== %s return %d.............. in %dms\n", __FUNCTION__ , ret, rtw_get_passing_time_ms(start_time)); /*depends on sunxi power control */ #if defined(CONFIG_MMC_SUNXI_POWER_CONTROL) // sunximmc_rescan_card(SDIOID, 0); // rtl8723as_sdio_poweroff(); printk("[rtl8723as] %s: suspend end.\n", __FUNCTION__); #endif _func_exit_; return ret; }
/** @brief This function handles client driver shutdown * * @param dev A pointer to device structure * @return N/A */ void woal_sdio_shutdown(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); moal_handle *handle = NULL; struct sdio_mmc_card *cardp; mlan_ds_hs_cfg hscfg; int timeout = 0; int i; ENTER(); PRINTM(MCMND, "<--- Enter woal_sdio_shutdown --->\n"); cardp = sdio_get_drvdata(func); if (!cardp || !cardp->handle) { PRINTM(MERROR, "Card or moal_handle structure is not valid\n"); LEAVE(); return; } handle = cardp->handle; for (i = 0; i < handle->priv_num; i++) netif_device_detach(handle->priv[i]->netdev); if (shutdown_hs) { memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg)); hscfg.is_invoke_hostcmd = MFALSE; hscfg.conditions = SHUTDOWN_HOST_SLEEP_DEF_COND; hscfg.gap = SHUTDOWN_HOST_SLEEP_DEF_GAP; hscfg.gpio = SHUTDOWN_HOST_SLEEP_DEF_GPIO; if (woal_set_get_hs_params (woal_get_priv(handle, MLAN_BSS_ROLE_ANY), MLAN_ACT_SET, MOAL_IOCTL_WAIT, &hscfg) == MLAN_STATUS_FAILURE) { PRINTM(MERROR, "Fail to set HS parameter in shutdown: 0x%x 0x%x 0x%x\n", hscfg.conditions, hscfg.gap, hscfg.gpio); goto done; } /* Enable Host Sleep */ handle->hs_activate_wait_q_woken = MFALSE; memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg)); hscfg.is_invoke_hostcmd = MTRUE; if (woal_set_get_hs_params (woal_get_priv(handle, MLAN_BSS_ROLE_ANY), MLAN_ACT_SET, MOAL_NO_WAIT, &hscfg) == MLAN_STATUS_FAILURE) { PRINTM(MERROR, "Request HS enable failed in shutdown\n"); goto done; } timeout = wait_event_interruptible_timeout(handle-> hs_activate_wait_q, handle-> hs_activate_wait_q_woken, HS_ACTIVE_TIMEOUT); if (handle->hs_activated == MTRUE) PRINTM(MMSG, "HS actived in shutdown\n"); else PRINTM(MMSG, "Fail to enable HS in shutdown\n"); } done: PRINTM(MCMND, "<--- Leave woal_sdio_shutdown --->\n"); LEAVE(); return; }
int sqn_wakeup_fw(struct sdio_func *func) { int rv = 0; int ver = 0; int counter = 0; int retry_cnt = 3; u32 wakeup_delay = 0; unsigned long timeout = msecs_to_jiffies(800); unsigned long irq_flags = 0; struct sqn_private *priv = ((struct sqn_sdio_card *)sdio_get_drvdata(func))->priv; struct sqn_sdio_card *card = priv->card; u8 need_to_unlock_wakelock = 0; sqn_pr_enter(); sqn_pr_info("waking up the card...\n"); if (!wake_lock_active(&card->wakelock_tx)) { if (mmc_wimax_get_sdio_wakelock_log()) { printk(KERN_INFO "[WIMAX] lock wl_tx2,"); PRINTRTC; } wake_lock(&card->wakelock_tx); need_to_unlock_wakelock = 1; } retry: if (priv->removed) goto out; sdio_claim_host(func); #define SDIO_CCCR_CCCR_SDIO_VERSION_VALUE 0x11 wakeup_delay = 2; counter = 5; do { sqn_pr_dbg("CMD52 #%d, delay %d msec\n", counter, wakeup_delay); ver = sdio_readb(func, SDIO_CCCR_CCCR_SDIO_VERSION, &rv); // To avoid FW sutck in PLLOFF, SDIO isn't able to wake up it. mdelay(wakeup_delay); --counter; } while((rv || ver != SDIO_CCCR_CCCR_SDIO_VERSION_VALUE) && counter > 0); if (rv) { sqn_pr_err("error when reading SDIO_VERSION\n"); if (mmc_wimax_get_wimax_FW_freeze_WK_TX()) { sqn_pr_info("[ste]set is_card_sleeps 0 to avoid TX polling\n"); card->is_card_sleeps = 0; } sdio_release_host(func); goto out; } else sqn_pr_dbg("SDIO_VERSION has been read successfully\n"); sqn_pr_dbg("send wake-up signal to card\n"); sdio_writeb(func, 1, SQN_SOC_SIGS_LSBS, &rv); if (rv) sqn_pr_err("error when writing to SQN_SOC_SIGS_LSBS: %d\n", rv); sdio_release_host(func); sqn_pr_info("wait for completion (timeout %d msec)...\n" , jiffies_to_msecs(timeout)); rv = wait_event_interruptible_timeout(g_card_sleep_waitq , 0 == card->is_card_sleeps || priv->removed, timeout); if (priv->removed) goto out; if (-ERESTARTSYS == rv) { sqn_pr_warn("got a signal from kernel %d\n", rv); } else if (0 == rv) { rv = -1; sqn_pr_err("can't wake up the card - timeout elapsed\n"); if (retry_cnt-- > 0 && card->is_card_sleeps) { sqn_pr_info("retry wake up\n"); goto retry; } sqn_pr_info("giving up to wake up the card\n"); spin_lock_irqsave(&priv->drv_lock, irq_flags); card->is_card_sleeps = 0; spin_unlock_irqrestore(&priv->drv_lock, irq_flags); } else { rv = 0; sqn_pr_info("card is waked up successfully\n"); } out: if (need_to_unlock_wakelock && wake_lock_active(&card->wakelock_tx)) { if (mmc_wimax_get_sdio_wakelock_log()) { printk(KERN_INFO "[WIMAX] release wake_lock_tx in %s,", __func__); PRINTRTC; } wake_unlock(&card->wakelock_tx); /* TX */ } sqn_pr_leave(); return rv; }
static HIF_DEVICE * getHifDevice(struct sdio_func *func) { AR_DEBUG_ASSERT(func != NULL); return (HIF_DEVICE *)sdio_get_drvdata(func); }
static int write_data(struct sdio_func *func, u32 addr, void *data , u32 size, u32 access_size) { int rv = 0; struct sqn_sdio_card *sqn_card = sdio_get_drvdata(func); sqn_pr_enter(); sdio_claim_host(func); if (is_good_ahb_address(addr, sqn_card->version) && 0 == (size % 4) && 4 == access_size) { /* write data using AHB */ u8 *data_cp = 0; #ifdef DEBUG u8 *read_data = 0; #endif sqn_pr_dbg("write data using AHB\n"); sdio_writel(func, addr, SQN_SDIO_ADA_ADDR, &rv); if (rv) { sqn_pr_dbg("can't set SQN_SDIO_ADA_ADDR register\n"); goto out; } sqn_pr_dbg("after SQN_SDIO_ADA_ADDR\n"); data_cp = kmalloc(size, GFP_KERNEL | GFP_DMA); memcpy(data_cp, data, size); rv = sdio_writesb(func, SQN_SDIO_ADA_RDWR, data_cp, size); if (rv) { sqn_pr_dbg("can't write to SQN_SDIO_ADA_RDWR register\n"); goto out; } kfree(data_cp); /* * Workaround when sdio_writesb doesn't work because DMA * alignment */ /* int i = 0; for (; i < size/4; ++i) { sdio_writel(func, *((u32*)data + i), SQN_SDIO_ADA_RDWR, &rv); if (rv) { sqn_pr_dbg("can't write to SQN_SDIO_ADA_RDWR register\n"); goto out; } } */ sqn_pr_dbg("after SQN_SDIO_ADA_RDWR\n"); /* ******** only for debugging ******** */ /* validate written data */ /* #ifdef DEBUG */ #if 0 sqn_pr_dbg("reading data using AHB\n"); sdio_writel(func, addr, SQN_SDIO_ADA_ADDR, &rv); if (rv) { sqn_pr_dbg("can't set SQN_SDIO_ADA_ADDR register\n"); goto out; } sqn_pr_dbg("after SQN_SDIO_ADA_ADDR\n"); read_data = kmalloc(size, GFP_KERNEL); rv = sdio_readsb(func, read_data, SQN_SDIO_ADA_RDWR, size); if (rv) { sqn_pr_dbg("can't read from SQN_SDIO_ADA_RDWR register\n"); kfree(read_data); goto out; } if (memcmp(data, read_data, size)) sqn_pr_dbg("WARNING: written data are __not__ equal\n"); else sqn_pr_dbg("OK: written data are equal\n"); kfree(read_data); #endif /* DEBUG */ /* ******** only for debugging ******** */ } else if (4 == access_size && size >= 4) { /* write data using CMD53 */ sqn_pr_dbg("write data using CMD53\n"); rv = sdio_memcpy_toio(func, addr, data , size); } else { /* write data using CMD52 */ /* not implemented yet, so we use CMD53 */ /* rv = sdio_memcpy_toio(func, addr, data , size); */ int i = 0; sqn_pr_dbg("write data using CMD52\n"); for (i = 0; i < size; ++i) { sdio_writeb(func, *((u8*)data + i), addr + i, &rv); if (rv) { sqn_pr_dbg("can't write 1 byte to %xh addr using CMD52\n" , addr + i); goto out; } } } out: sdio_release_host(func); sqn_pr_leave(); return rv; }