/*
 *	Public entry points & extern's
 */
int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
{
	int err_ret = 0;

	brcmf_dbg(TRACE, "\n");

	sdiodev->num_funcs = 2;

	sdio_claim_host(sdiodev->func[1]);
	err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
	sdio_release_host(sdiodev->func[1]);
	if (err_ret) {
		brcmf_dbg(ERROR, "Failed to set F1 blocksize\n");
		goto out;
	}

	sdio_claim_host(sdiodev->func[2]);
	err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
	sdio_release_host(sdiodev->func[2]);
	if (err_ret) {
		brcmf_dbg(ERROR, "Failed to set F2 blocksize\n");
		goto out;
	}

	brcmf_sdioh_enablefuncs(sdiodev);

out:
	brcmf_dbg(TRACE, "Done\n");
	return err_ret;
}
Example #2
0
static int emapi_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
{
   	int rc;

	emapi_setfunc(NULL);

	printk("emapi router - class 0x%x, Vendor 0x%x, Device 0x%x\n",
	      	func->class, func->vendor, func->device);

	if (func->vendor != VENDOR_ID || func->device != DEVICE_ID)
	   	return -ENODEV;

	sdio_claim_host(func);
	rc = sdio_enable_func(func);
	if (rc)
	   	goto sdio_err1;

	rc = sdio_claim_irq(func, emapi_sdio_irq);
	if (rc)
	   	goto sdio_err2;

	rc = sdio_set_block_size(func, 512); 
	if (rc)
	   	goto sdio_err2;

	emapi_setfunc(func);

	return 0;

sdio_err2:
	sdio_disable_func(func);
sdio_err1:
	sdio_release_host(func);
	return rc;
}
Example #3
0
extern unsigned int sd_dvobj_init(_adapter * padapter){

	struct dvobj_priv *psddev=&padapter->dvobjpriv;
	struct sdio_func *func=psddev->func;
	int ret;
	_func_enter_;
	//_rtw_init_sema(&psddev->init_finish,0);
	sdio_claim_host(func);
	 ret=sdio_enable_func(func);
	if(ret){	
	RT_TRACE(_module_hci_intfs_c_,_drv_err_,("sd_dvobj_init: sdio_enable_func fail!!!!!\n"));
		return _FAIL;
	}
	RT_TRACE(_module_hci_intfs_c_,_drv_err_,("sd_dvobj_init: sdio_enable_func success!!!!!\n"));
	padapter->EepromAddressSize = 6;
	psddev->tx_block_mode=1;
	psddev->rx_block_mode=1;
	sdio_set_block_size(func, 512);
	psddev->block_transfer_len=512;
	psddev->blk_shiftbits=9;
	ret=sdio_claim_irq(func,sd_sync_int_hdl);
	sdio_release_host(func);
	psddev->sdio_himr=0xff;
	if(ret)	
		return _FAIL;
	_func_exit_;
	return _SUCCESS;
}
Example #4
0
/*----------------------------------------------------------------------------*/
BOOL glBusInit(PVOID pvData)
{
#if (MTK_WCN_HIF_SDIO == 0)
	int ret = 0;
	struct sdio_func *func = NULL;

	ASSERT(pvData);

	func = (struct sdio_func *)pvData;

	sdio_claim_host(func);
	ret = sdio_set_block_size(func, 512);
	sdio_release_host(func);

	if (ret) {
		/* printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 failed!\n"); */
	} else {
		/* printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 done!\n"); */
	}

	/* printk(KERN_INFO DRV_NAME"param: func->cur_blksize(%d)\n", func->cur_blksize); */
	/* printk(KERN_INFO DRV_NAME"param: func->max_blksize(%d)\n", func->max_blksize); */
	/* printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_size(%d)\n", func->card->host->max_blk_size); */
	/* printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_count(%d)\n", func->card->host->max_blk_count); */
#endif
	return TRUE;
}				/* end of glBusInit() */
Example #5
0
int bcmsdio_set_blk_size(int func, unsigned int blk_size)
{
	struct sdio_func *function = func_data[BCM_SDIO_FN1]->func;
	int ret = 0;

	if (function == NULL) {
		BCM_DEBUG_PRINT(ERROR_LEVEL, KERN_ALERT " ***Error: %s %d ***\n", __func__, __LINE__);
		return -ENON_INTF_ERR;
	}

	sdio_claim_host(function);

	if(func != BCM_SDIO_FN0)
		ret = sdio_set_block_size(function, blk_size);
	else
	{
		BCM_SDIO_FN0_BLK_SIZE = blk_size;
		sdio_f0_writeb(function,BCM_SDIO_FN0_BLK_SIZE & 0xFF, 0x10, &ret);
		if(ret < 0)
		{
			BCM_DEBUG_PRINT(debuglevel, KERN_ALERT "failed to set the f0 block size");
		}
		sdio_f0_writeb(function,(BCM_SDIO_FN0_BLK_SIZE >> 8) &0xFF , 0x11, &ret);
		if(ret < 0)
		{
			BCM_DEBUG_PRINT(debuglevel, KERN_ALERT "failed to set the f0 block size");
		}

	}	

	sdio_release_host(function);

	return ret;
}
Example #6
0
void cmc7xx_sdio_reset(struct work_struct *work)
{
	struct net_adapter *adapter = container_of(work,
			struct net_adapter, wimax_reset);
	u8 data[100];

	sdio_claim_host(adapter->func);
	sdio_release_irq(adapter->func);
	sdio_release_host(adapter->func);

	if (wimax_cmc7xx_sdio_reset_comm(adapter->func->card))
		dump_debug("%s: cmc7xx_sdio_reset_comm fail", __func__);

	sdio_claim_host(adapter->func);
	if (sdio_enable_func(adapter->func))
		dump_debug("%s: sdio_enable_func fail", __func__);

	if (sdio_claim_irq(adapter->func, adapter_interrupt))
		dump_debug("%s: sdio_claim_irq fail", __func__);

	if (sdio_set_block_size(adapter->func, 512))
		dump_debug("%s: sdio_set_block_size fail", __func__);

	sdio_memcpy_toio(adapter->func,
		SDIO_TX_BANK_ADDR + 4,
		data, 32);

	sdio_release_host(adapter->func);
}
Example #7
0
static void wl1271_sdio_set_block_size(struct wl1271 *wl)
{
	wl->block_size = TX_PAD_SDIO_BLK_SIZE;

	sdio_claim_host(wl->if_priv);
	sdio_set_block_size(wl->if_priv, TX_PAD_SDIO_BLK_SIZE);
	sdio_release_host(wl->if_priv);
}
int sdioDrv_SetBlockSize(unsigned int uFunc, unsigned int blksz)
{
	PDEBUG("%s: func %d\n", __func__, uFunc);

	/* currently only wlan sdio function is supported */
	BUG_ON(uFunc != SDIO_WLAN_FUNC);
	BUG_ON(tiwlan_func[uFunc] == NULL);

	return sdio_set_block_size(tiwlan_func[uFunc], blksz);
}
Example #9
0
static void wl1271_sdio_set_block_size(struct device *child,
				       unsigned int blksz)
{
	struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
	struct sdio_func *func = dev_to_sdio_func(glue->dev);

	sdio_claim_host(func);
	sdio_set_block_size(func, blksz);
	sdio_release_host(func);
}
Example #10
0
/*
 * This function registers the SDIO device.
 *
 * SDIO IRQ is claimed, block size is set and driver data is initialized.
 */
static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
{
	int ret = 0;
	struct sdio_mmc_card *card = adapter->card;
	struct sdio_func *func = card->func;

	/* save adapter pointer in card */
	card->adapter = adapter;

	sdio_claim_host(func);

	/* Request the SDIO IRQ */
	ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
	if (ret) {
		pr_err("claim irq failed: ret=%d\n", ret);
		goto disable_func;
	}

	/* Set block size */
	ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE);
	if (ret) {
		pr_err("cannot set SDIO block size\n");
		ret = -1;
		goto release_irq;
	}

	sdio_release_host(func);
	sdio_set_drvdata(func, card);

	adapter->dev = &func->dev;

	switch (func->device) {
	case SDIO_DEVICE_ID_MARVELL_8786:
		strcpy(adapter->fw_name, SD8786_DEFAULT_FW_NAME);
		break;
	case SDIO_DEVICE_ID_MARVELL_8797:
		strcpy(adapter->fw_name, SD8797_DEFAULT_FW_NAME);
		break;
	case SDIO_DEVICE_ID_MARVELL_8787:
	default:
		strcpy(adapter->fw_name, SD8787_DEFAULT_FW_NAME);
		break;
	}

	return 0;

release_irq:
	sdio_release_irq(func);
disable_func:
	sdio_disable_func(func);
	sdio_release_host(func);
	adapter->card = NULL;

	return -1;
}
Example #11
0
/*
 *	Public entry points & extern's
 */
extern sdioh_info_t * sdioh_attach(void *bar0, uint irq)
{
	sdioh_info_t *sd;
	int err_ret;

	if (gInstance == NULL) 
		return NULL;

    memset(&g_sdioh_info_t, 0, sizeof(sdioh_info_t));
    sd = &g_sdioh_info_t;
	if (sd == NULL) 
		return NULL;

	sd->num_funcs = 2;
	sd->sd_blockmode = TRUE;
	sd->use_client_ints = TRUE;
	sd->client_block_size[0] = 64;
	
	sd->client_block_size[1] = 64;
	err_ret = sdio_set_block_size(gInstance->func[1], 64);
	if (err_ret) 
	{
		BCMDEBUG("bcmsdh_sdmmc: Failed to set F1 blocksize\n");
	}

	if (gInstance->func[2]) 
	{
		sd->client_block_size[2] = sd_f2_blocksize;
		err_ret = sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
		if (err_ret) 
		{
			BCMDEBUG("bcmsdh_sdmmc: Failed to set F2 blocksize\n");
		}
	}

	sdioh_sdmmc_card_enablefuncs(sd);
	
	gInstance->sd = sd;

	return sd;
}
Example #12
0
static u32 sdio_init(PADAPTER padapter)
{
	struct dvobj_priv *psddev;
	PSDIO_DATA psdio_data;
	struct sdio_func *func;
	int err;

_func_enter_;

	RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+sdio_init\n"));
	if (padapter == NULL) {
		DBG_871X(KERN_ERR "%s: padapter is NULL!\n", __func__);
		err = -1;
		goto exit;
	}

	psddev = &padapter->dvobjpriv;
	psdio_data = &psddev->intf_data;
	func = psdio_data->func;

	//3 1. init SDIO bus
	sdio_claim_host(func);

	err = sdio_enable_func(func);
	if (err) {
		DBG_871X(KERN_CRIT "%s: sdio_enable_func FAIL(%d)!\n", __func__, err);
		goto release;
	}

	err = sdio_set_block_size(func, 512);
	if (err) {
		DBG_871X(KERN_CRIT "%s: sdio_set_block_size FAIL(%d)!\n", __func__, err);
		goto release;
	}
	psdio_data->block_transfer_len = 512;
	psdio_data->tx_block_mode = 1;
	psdio_data->rx_block_mode = 1;

release:
	sdio_release_host(func);

exit:
_func_exit_;

	if (err) return _FAIL;
	return _SUCCESS;
}
Example #13
0
/*
 * Setup minimal device communication infrastructure needed to at
 * least be able to update the firmware.
 *
 * Note the ugly trick: if we are in the probe path
 * (i2400ms->debugfs_dentry == NULL), we only retry function
 * enablement one, to avoid racing with the iwmc3200 top controller.
 */
static
int i2400ms_bus_setup(struct i2400m *i2400m)
{
	int result;
	struct i2400ms *i2400ms =
		container_of(i2400m, struct i2400ms, i2400m);
	struct device *dev = i2400m_dev(i2400m);
	struct sdio_func *func = i2400ms->func;
	int retries;

	sdio_claim_host(func);
	result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
	sdio_release_host(func);
	if (result < 0) {
		dev_err(dev, "Failed to set block size: %d\n", result);
		goto error_set_blk_size;
	}

	if (i2400ms->iwmc3200 && i2400ms->debugfs_dentry == NULL)
		retries = 1;
	else
		retries = 0;
	result = i2400ms_enable_function(i2400ms, retries);
	if (result < 0) {
		dev_err(dev, "Cannot enable SDIO function: %d\n", result);
		goto error_func_enable;
	}

	result = i2400ms_tx_setup(i2400ms);
	if (result < 0)
		goto error_tx_setup;
	result = i2400ms_rx_setup(i2400ms);
	if (result < 0)
		goto error_rx_setup;
	return 0;

error_rx_setup:
	i2400ms_tx_release(i2400ms);
error_tx_setup:
	sdio_claim_host(func);
	sdio_disable_func(func);
	sdio_release_host(func);
error_func_enable:
error_set_blk_size:
	return result;
}
Example #14
0
/**
 *  @brief This function registers the device
 *
 *  @param handle  A pointer to moal_handle structure
 *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
woal_register_dev(moal_handle *handle)
{
	int ret = MLAN_STATUS_SUCCESS;
	struct sdio_mmc_card *card = handle->card;
	struct sdio_func *func;

	ENTER();

	func = card->func;
	sdio_claim_host(func);
	/* Request the SDIO IRQ */
	ret = sdio_claim_irq(func, woal_sdio_interrupt);
	if (ret) {
		PRINTM(MFATAL, "sdio_claim_irq failed: ret=%d\n", ret);
		goto release_host;
	}

	/* Set block size */
	ret = sdio_set_block_size(card->func, MLAN_SDIO_BLOCK_SIZE);
	if (ret) {
		PRINTM(MERROR,
		       "sdio_set_block_seize(): cannot set SDIO block size\n");
		ret = MLAN_STATUS_FAILURE;
		goto release_irq;
	}

	sdio_release_host(func);
	sdio_set_drvdata(func, card);

	handle->hotplug_device = &func->dev;

	LEAVE();
	return MLAN_STATUS_SUCCESS;

release_irq:
	sdio_release_irq(func);
release_host:
	sdio_release_host(func);
	handle->card = NULL;

	LEAVE();
	return MLAN_STATUS_FAILURE;
}
Example #15
0
static void sd_intf_start(PADAPTER padapter)
{
	struct dvobj_priv *psddev;
	struct sdio_func *func;
	int err;

	if (padapter == NULL) goto exit;
	
	psddev = &padapter->dvobjpriv;
	func = psddev->intf_data.func;

	//os/intf dep
	if (func) {		
		sdio_claim_host(func);

		//according to practice, this is needed...
		err = sdio_set_block_size(func, 512);
		if (err) {
			DBG_871X(KERN_CRIT "%s: sdio_set_block_size FAIL(%d)!\n", __func__, err);
			goto release_host;
		}	
		err = sdio_claim_irq(func, &sd_sync_int_hdl);
		if (err) {
			DBG_871X(KERN_CRIT "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err);
			goto release_host;
		}
	
release_host:
		sdio_release_host(func);
	}

	//hal dep
	if (padapter->HalFunc.enable_interrupt)
		padapter->HalFunc.enable_interrupt(padapter);
	else {
		DBG_871X("%s HalFunc.enable_interrupt is %p\n", __FUNCTION__, padapter->HalFunc.enable_interrupt);
		goto exit;
	}

exit:
	return;
}
Example #16
0
/*
 * This function registers the SDIO device.
 *
 * SDIO IRQ is claimed, block size is set and driver data is initialized.
 */
static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
{
	int ret = 0;
	struct sdio_mmc_card *card = adapter->card;
	struct sdio_func *func = card->func;

	/* save adapter pointer in card */
	card->adapter = adapter;

	sdio_claim_host(func);

	/* Request the SDIO IRQ */
	ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
	if (ret) {
		pr_err("claim irq failed: ret=%d\n", ret);
		goto disable_func;
	}

	/* Set block size */
	ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE);
	if (ret) {
		pr_err("cannot set SDIO block size\n");
		ret = -1;
		goto release_irq;
	}

	sdio_release_host(func);
	sdio_set_drvdata(func, card);

	adapter->dev = &func->dev;

	return 0;

release_irq:
	sdio_release_irq(func);
disable_func:
	sdio_disable_func(func);
	sdio_release_host(func);
	adapter->card = NULL;

	return -1;
}
Example #17
0
static int wl1271_sdio_power_on(struct wl1271 *wl)
{
	struct sdio_func *func = wl_to_func(wl);
	int ret;


        printk("%s: function entered \n", __FUNCTION__);
#if 1
	/* Make sure the card will not be powered off by runtime PM */
#if 0  // Added Michael Carrier
        printk("%s: Calling pm_runtime_get_sync\n", __FUNCTION__);
	ret = pm_runtime_get_sync(&func->dev);
        printk("%s: pm_runtime_get_sync returned %d\n", __FUNCTION__, ret);
	if (ret < 0)
		goto out;
	/* Runtime PM might be disabled, so power up the card manually */
#endif 

        printk("%s: Calling mmc_power_restore_host\n", __FUNCTION__);
	ret = mmc_power_restore_host(func->card->host);
        printk("%s: mmc_power_restore_host() returned %d\n", __FUNCTION__, ret);
	if (ret < 0)
		goto out;
#else
       //wl1271_setpower(1);

#endif
	/* if the power is already on (WHY?) ret == 1 */
	ret = 0;

	sdio_claim_host(func);
	sdio_enable_func(func);

	/* Set the default block size in case it was modified */
	sdio_set_block_size(func, 0);

out:
	return ret;
}
Example #18
0
static u32 sdio_init(struct dvobj_priv *dvobj)
{
	PSDIO_DATA psdio_data;
	struct sdio_func *func;
	int err;

_func_enter_;

	psdio_data = &dvobj->intf_data;
	func = psdio_data->func;

	// 1. init SDIO bus
	sdio_claim_host(func);

	err = sdio_enable_func(func);
	if (err) {
		DBG_871X(KERN_CRIT "%s: sdio_enable_func FAIL(%d)!\n", __func__, err);
		goto release;
	}

	err = sdio_set_block_size(func, 512);
	if (err) {
		DBG_871X(KERN_CRIT "%s: sdio_set_block_size FAIL(%d)!\n", __func__, err);
		goto release;
	}
	psdio_data->block_transfer_len = 512;
	psdio_data->tx_block_mode = 1;
	psdio_data->rx_block_mode = 1;

release:
	sdio_release_host(func);

_func_exit_;
	if (err) return _FAIL;
	return _SUCCESS;
}
Example #19
0
static int hifDeviceResume(struct device *dev)
{
    struct task_struct* pTask;
    const char *taskName;
    int (*taskFunc)(void *);
	struct sdio_func *func = dev_to_sdio_func(dev);
    A_STATUS ret = A_OK;
    HIF_DEVICE *device;   
    device = getHifDevice(func);

    if (device->is_suspend) {
       /* enable the SDIO function */
        sdio_claim_host(func);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
        /* give us some time to enable, in ms */
        func->enable_timeout = 100;
#endif
        ret = sdio_enable_func(func);
        if (ret) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n",
					  __FUNCTION__, ret));
            sdio_release_host(func);
            return ret;
    }
        ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
        sdio_release_host(func);
        if (ret) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x  AR6K: 0x%X\n",
					  __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret));
            return ret;
        }
        device->is_suspend = FALSE;
        /* create async I/O thread */
        if (!device->async_task) {
            device->async_shutdown = 0;
            device->async_task = kthread_create(async_task,
                                           (void *)device,
                                           "AR6K Async");
           if (IS_ERR(device->async_task)) {
               AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__));
                return A_ERROR;
           }
           AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n"));
           wake_up_process(device->async_task );    
        }
    }

    if (!device->claimedContext) {
        printk("WARNING!!! No claimedContext during resume wlan\n"); 
        taskFunc = startup_task;
        taskName = "AR6K startup";
    } else {
        taskFunc = resume_task;
        taskName = "AR6K resume";
    }
    /* create resume thread */
    pTask = kthread_create(taskFunc, (void *)device, taskName);
    if (IS_ERR(pTask)) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create resume task\n", __FUNCTION__));
        return A_ERROR;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start resume task\n"));
    wake_up_process(pTask);
    return A_SUCCESS(ret) ? 0 : ret;
}
Example #20
0
static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id)
{
    int ret;
    HIF_DEVICE * device;
    int count;
    struct task_struct* startup_task_struct;

    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
		    ("AR6000: hifDeviceInserted, Function: 0x%X, Vendor ID: 0x%X, Device ID: 0x%X, block size: 0x%X/0x%X\n",
		     func->num, func->vendor, func->device, func->max_blksize, func->cur_blksize));

    addHifDevice(func);
    device = getHifDevice(func);

    spin_lock_init(&device->lock);

    spin_lock_init(&device->asynclock);
    
    DL_LIST_INIT(&device->ScatterReqHead);
    
    if (!nohifscattersupport) {
            /* try to allow scatter operation on all instances,
             * unless globally overridden */
        device->scatter_enabled = TRUE;
    }
    
        /* enable the SDIO function */
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: claim\n"));
    sdio_claim_host(func);
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: enable\n"));

    if ((id->device & MANUFACTURER_ID_AR6K_BASE_MASK) >= MANUFACTURER_ID_AR6003_BASE) {
        /* enable 4-bit ASYNC interrupt on AR6003 or later devices */    
        ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG, SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
        if (ret) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to enable 4-bit ASYNC IRQ mode %d \n",ret));    
            sdio_release_host(func);
            return ret;
        }
        AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: 4-bit ASYNC IRQ mode enabled\n"));   
    }
    
    
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
    /* give us some time to enable, in ms */
    func->enable_timeout = 100;
#endif
    ret = sdio_enable_func(func);
    if (ret) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n",
					  __FUNCTION__, ret)); 
        sdio_release_host(func);
        return ret;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: set block size 0x%X\n", HIF_MBOX_BLOCK_SIZE));
    ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
    sdio_release_host(func);
    if (ret) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x  AR6K: 0x%X\n",
					  __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret));
        return ret;
    }
    /* Initialize the bus requests to be used later */
    A_MEMZERO(device->busRequest, sizeof(device->busRequest));
    for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
        sema_init(&device->busRequest[count].sem_req, 0);
        hifFreeBusRequest(device, &device->busRequest[count]);
    }

    /* create async I/O thread */
    device->async_shutdown = 0;
    device->async_task = kthread_create(async_task,
                                       (void *)device,
                                       "AR6K Async");
    if (IS_ERR(device->async_task)) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__));
        return A_ERROR;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n"));
    sema_init(&device->sem_async, 0);
    wake_up_process(device->async_task );

    /* create startup thread */
    startup_task_struct = kthread_create(startup_task,
                                  (void *)device,
                                  "AR6K startup");
    if (IS_ERR(startup_task_struct)) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create startup task\n", __FUNCTION__));
        return A_ERROR;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start startup task\n"));
    wake_up_process(startup_task_struct);

    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: return %d\n", ret));
    return ret;
}
Example #21
0
static int wl1251_sdio_probe(struct sdio_func *func,
			     const struct sdio_device_id *id)
{
	int ret;
	struct wl1251 *wl;
	struct ieee80211_hw *hw;
	struct wl1251_sdio *wl_sdio;
	const struct wl1251_platform_data *wl1251_board_data;

	hw = wl1251_alloc_hw();
	if (IS_ERR(hw))
		return PTR_ERR(hw);

	wl = hw->priv;

	wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL);
	if (wl_sdio == NULL) {
		ret = -ENOMEM;
		goto out_free_hw;
	}

	sdio_claim_host(func);
	ret = sdio_enable_func(func);
	if (ret)
		goto release;

	sdio_set_block_size(func, 512);
	sdio_release_host(func);

	SET_IEEE80211_DEV(hw, &func->dev);
	wl_sdio->func = func;
	wl->if_priv = wl_sdio;
	wl->if_ops = &wl1251_sdio_ops;

	wl1251_board_data = wl1251_get_platform_data();
	if (!IS_ERR(wl1251_board_data)) {
		wl->power_gpio = wl1251_board_data->power_gpio;
		wl->irq = wl1251_board_data->irq;
		wl->use_eeprom = wl1251_board_data->use_eeprom;
	}

	if (gpio_is_valid(wl->power_gpio)) {
#if 0 /* Not in RHEL */
		ret = devm_gpio_request(&func->dev, wl->power_gpio,
								"wl1251 power");
#else
		ret = gpio_request(wl->power_gpio, "wl1251 power");
#endif
		if (ret) {
			wl1251_error("Failed to request gpio: %d\n", ret);
			goto disable;
		}
	}

	if (wl->irq) {
		irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
		ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
		if (ret < 0) {
			wl1251_error("request_irq() failed: %d", ret);
			goto disable;
		}

		irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);

		wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
		wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;

		wl1251_info("using dedicated interrupt line");
	} else {
		wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
		wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;

		wl1251_info("using SDIO interrupt");
	}

	ret = wl1251_init_ieee80211(wl);
	if (ret)
		goto out_free_irq;

	sdio_set_drvdata(func, wl);

	/* Tell PM core that we don't need the card to be powered now */
	pm_runtime_put_noidle(&func->dev);

	return ret;

out_free_irq:
	if (wl->irq)
		free_irq(wl->irq, wl);
disable:
	sdio_claim_host(func);
	sdio_disable_func(func);
release:
	sdio_release_host(func);
	kfree(wl_sdio);
out_free_hw:
	wl1251_free_hw(wl);
	return ret;
}
Example #22
0
static int smssdio_probe(struct sdio_func *func,
                         const struct sdio_device_id *id)
{
    int ret;

    int board_id;
    struct smssdio_device *smsdev;
    struct smsdevice_params_t params;

    board_id = id->driver_data;

    smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL);
    if (!smsdev)
        return -ENOMEM;

    smsdev->func = func;

    memset(&params, 0, sizeof(struct smsdevice_params_t));

    params.device = &func->dev;
    params.buffer_size = 0x5000;	/* ?? */
    params.num_buffers = 22;	/* ?? */
    params.context = smsdev;

    snprintf(params.devpath, sizeof(params.devpath),
             "sdio\\%s", sdio_func_id(func));

    params.sendrequest_handler = smssdio_sendrequest;

    params.device_type = sms_get_board(board_id)->type;

    if (params.device_type != SMS_STELLAR)
        params.flags |= SMS_DEVICE_FAMILY2;
    else {
        /*
         * FIXME: Stellar needs special handling...
         */
        ret = -ENODEV;
        goto free;
    }

    ret = smscore_register_device(&params, &smsdev->coredev);
    if (ret < 0)
        goto free;

    smscore_set_board_id(smsdev->coredev, board_id);

    sdio_claim_host(func);

    ret = sdio_enable_func(func);
    if (ret)
        goto release;

    ret = sdio_set_block_size(func, 128);
    if (ret)
        goto disable;

    ret = sdio_claim_irq(func, smssdio_interrupt);
    if (ret)
        goto disable;

    sdio_set_drvdata(func, smsdev);

    sdio_release_host(func);

    ret = smscore_start_device(smsdev->coredev);
    if (ret < 0)
        goto reclaim;

    return 0;

reclaim:
    sdio_claim_host(func);
    sdio_release_irq(func);
disable:
    sdio_disable_func(func);
release:
    sdio_release_host(func);
    smscore_unregister_device(smsdev->coredev);
free:
    kfree(smsdev);

    return ret;
}
Example #23
0
static void wl1271_sdio_set_block_size(struct wl1271 *wl, unsigned int blksz)
{
	sdio_claim_host(wl->if_priv);
	sdio_set_block_size(wl->if_priv, blksz);
	sdio_release_host(wl->if_priv);
}
Example #24
0
static int wl1251_sdio_probe(struct sdio_func *func,
			     const struct sdio_device_id *id)
{
	int ret, t;
	struct wl1251 *wl;
	struct ieee80211_hw *hw;
	struct wl1251_sdio *wl_sdio;
	const struct wl12xx_platform_data *wl12xx_board_data;

	hw = wl1251_alloc_hw();
	if (IS_ERR(hw))
		return PTR_ERR(hw);

	wl = hw->priv;

	wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL);
	if (wl_sdio == NULL) {
		ret = -ENOMEM;
		goto out_free_hw;
	}

	sdio_claim_host(func);
	ret = sdio_enable_func(func);
	if (ret)
		goto release;

	sdio_set_block_size(func, 512);
	sdio_release_host(func);

	SET_IEEE80211_DEV(hw, &func->dev);
	wl_sdio->func = func;
	wl->if_priv = wl_sdio;
	wl->if_ops = &wl1251_sdio_ops;

	wl12xx_board_data = wl12xx_get_platform_data();
	if (!IS_ERR(wl12xx_board_data)) {
		wl->set_power = wl12xx_board_data->set_power;
		wl->irq = wl12xx_board_data->irq;
		wl->use_eeprom = wl12xx_board_data->use_eeprom;
	}

	if (force_nvs_file)
		wl->use_eeprom = false;
	wl->dump_eeprom = dump_eeprom;

	if (wl->irq) {
		irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);

		ret = request_threaded_irq(wl->irq, NULL, wl1251_irq,
			IRQF_ONESHOT, "wl1251", wl);
		if (ret < 0) {
			wl1251_error("request_irq() failed: %d", ret);
			goto disable;
		}

		irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);

		wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
		wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;

		wl1251_info("using dedicated interrupt line");
	} else {
		wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
		wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;

		wl1251_info("using SDIO interrupt");
	}

	ret = wl1251_init_ieee80211(wl);
	if (ret)
		goto out_free_irq;

	sdio_set_drvdata(func, wl);

	for (t = 0; t < ARRAY_SIZE(wl1251_attrs); t++) {
		ret = device_create_file(&func->dev, &wl1251_attrs[t]);
		if (ret) {
			while (--t >= 0)
				device_remove_file(&func->dev,
						   &wl1251_attrs[t]);
			goto out_free_irq;
		}
	}

	/* Tell PM core that we don't need the card to be powered now */
	pm_runtime_put_noidle(&func->dev);

	return ret;

out_free_irq:
	if (wl->irq)
		free_irq(wl->irq, wl);
disable:
	sdio_claim_host(func);
	sdio_disable_func(func);
release:
	sdio_release_host(func);
	kfree(wl_sdio);
out_free_hw:
	wl1251_free_hw(wl);
	return ret;
}
Example #25
0
static int iwmct_probe(struct sdio_func *func,
			   const struct sdio_device_id *id)
{
	struct iwmct_priv *priv;
	int ret;
	int val = 1;
	int addr = IWMC_SDIO_INTR_ENABLE_ADDR;

	dev_dbg(&func->dev, "enter iwmct_probe\n");

	dev_dbg(&func->dev, "IRQ polling period id %u msecs, HZ is %d\n",
		jiffies_to_msecs(2147483647), HZ);

	priv = kzalloc(sizeof(struct iwmct_priv), GFP_KERNEL);
	if (!priv) {
		dev_err(&func->dev, "kzalloc error\n");
		return -ENOMEM;
	}
	priv->func = func;
	sdio_set_drvdata(func, priv);


	/* create drivers work queue */
	priv->wq = create_workqueue(DRV_NAME "_wq");
	priv->bus_rescan_wq = create_workqueue(DRV_NAME "_rescan_wq");
	INIT_WORK(&priv->bus_rescan_worker, iwmct_rescan_worker);
	INIT_WORK(&priv->isr_worker, iwmct_irq_read_worker);

	init_waitqueue_head(&priv->wait_q);

	sdio_claim_host(func);
	/* FIXME: Remove after it is fixed in the Boot ROM upgrade */
	func->enable_timeout = 10;

	/* In our HW, setting the block size also wakes up the boot rom. */
	ret = sdio_set_block_size(func, priv->dbg.block_size);
	if (ret) {
		LOG_ERROR(priv, INIT,
			"sdio_set_block_size() failure: %d\n", ret);
		goto error_sdio_enable;
	}

	ret = sdio_enable_func(func);
	if (ret) {
		LOG_ERROR(priv, INIT, "sdio_enable_func() failure: %d\n", ret);
		goto error_sdio_enable;
	}

	/* init reset and dev_sync states */
	atomic_set(&priv->reset, 0);
	atomic_set(&priv->dev_sync, 0);

	/* init read req queue */
	INIT_LIST_HEAD(&priv->read_req_list);

	/* process configurable parameters */
	iwmct_dbg_init_params(priv);
	ret = sysfs_create_group(&func->dev.kobj, &iwmct_attribute_group);
	if (ret) {
		LOG_ERROR(priv, INIT, "Failed to register attributes and "
			 "initialize module_params\n");
		goto error_dev_attrs;
	}

	iwmct_dbgfs_register(priv, DRV_NAME);

	if (!priv->dbg.direct && priv->dbg.download_trans_blks > 8) {
		LOG_INFO(priv, INIT,
			 "Reducing transaction to 8 blocks = 2K (from %d)\n",
			 priv->dbg.download_trans_blks);
		priv->dbg.download_trans_blks = 8;
	}
	priv->trans_len = priv->dbg.download_trans_blks * priv->dbg.block_size;
	LOG_INFO(priv, INIT, "Transaction length = %d\n", priv->trans_len);

	ret = sdio_claim_irq(func, iwmct_irq);
	if (ret) {
		LOG_ERROR(priv, INIT, "sdio_claim_irq() failure: %d\n", ret);
		goto error_claim_irq;
	}


	/* Enable function's interrupt */
	sdio_writeb(priv->func, val, addr, &ret);
	if (ret) {
		LOG_ERROR(priv, INIT, "Failure writing to "
			  "Interrupt Enable Register (%d): %d\n", addr, ret);
		goto error_enable_int;
	}

	sdio_release_host(func);

	LOG_INFO(priv, INIT, "exit iwmct_probe\n");

	return ret;

error_enable_int:
	sdio_release_irq(func);
error_claim_irq:
	sdio_disable_func(func);
error_dev_attrs:
	iwmct_dbgfs_unregister(priv->dbgfs);
	sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group);
error_sdio_enable:
	sdio_release_host(func);
	return ret;
}
Example #26
0
/** 
 *  @brief This function registers the device.
 *  
 *  @param priv    A pointer to bt_private structure
 *  @return 	   BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
int
sbi_register_dev(bt_private * priv)
{
    int ret = BT_STATUS_SUCCESS;
    u8 reg;
    u8 chiprev;
    struct sdio_mmc_card *card = priv->bt_dev.card;
    struct sdio_func *func;

    ENTER();

    if (!card || !card->func) {
        PRINTM(ERROR, "BT: Error: card or function is NULL!\n");
        goto failed;
    }
    func = card->func;
    priv->hotplug_device = &func->dev;
    if (fw_name == NULL)
        fw_name = DEFAULT_FW_NAME;

    /* Initialize the private structure */
    strncpy(priv->bt_dev.name, "bt_sdio0", sizeof(priv->bt_dev.name));
    priv->bt_dev.ioport = 0;
    priv->bt_dev.fn = func->num;

    sdio_claim_host(func);
    ret = sdio_claim_irq(func, sd_interrupt);
    if (ret) {
        PRINTM(FATAL, "BT: sdio_claim_irq failed: ret=%d\n", ret);
        goto release_host;
    }
    ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
    if (ret) {
        PRINTM(FATAL, "BT: %s: cannot set SDIO block size\n", __FUNCTION__);
        goto release_irq;
    }

    /* read Revision Register to get the chip revision number */
    chiprev = sdio_readb(func, CARD_REVISION_REG, &ret);
    if (ret) {
        PRINTM(FATAL, "BT: cannot read CARD_REVISION_REG\n");
        goto release_irq;
    }
    priv->adapter->chip_rev = chiprev;
    PRINTM(INFO, "revision=%#x\n", chiprev);

    /* 
     * Read the HOST_INTSTATUS_REG for ACK the first interrupt got
     * from the bootloader. If we don't do this we get a interrupt
     * as soon as we register the irq. 
     */
    reg = sdio_readb(func, HOST_INTSTATUS_REG, &ret);
    if (ret < 0)
        goto release_irq;

    /* Read the IO port */
    reg = sdio_readb(func, IO_PORT_0_REG, &ret);
    if (ret < 0)
        goto release_irq;
    else
        priv->bt_dev.ioport |= reg;

    reg = sdio_readb(func, IO_PORT_1_REG, &ret);
    if (ret < 0)
        goto release_irq;
    else
        priv->bt_dev.ioport |= (reg << 8);

    reg = sdio_readb(func, IO_PORT_2_REG, &ret);
    if (ret < 0)
        goto release_irq;
    else
        priv->bt_dev.ioport |= (reg << 16);

    PRINTM(INFO, "BT: SDIO FUNC%d IO port: 0x%x\n", priv->bt_dev.fn,
           priv->bt_dev.ioport);
#define SDIO_INT_MASK       0x3F
    /* Set Host interrupt reset to read to clear */
    reg = sdio_readb(func, HOST_INT_RSR_REG, &ret);
    if (ret < 0)
        goto release_irq;
    sdio_writeb(func, reg | SDIO_INT_MASK, HOST_INT_RSR_REG, &ret);
    if (ret < 0)
        goto release_irq;
    /* Set auto re-enable */
    reg = sdio_readb(func, CARD_MISC_CFG_REG, &ret);
    if (ret < 0)
        goto release_irq;
    sdio_writeb(func, reg | AUTO_RE_ENABLE_INT, CARD_MISC_CFG_REG, &ret);
    if (ret < 0)
        goto release_irq;

    sdio_set_drvdata(func, card);
    sdio_release_host(func);

    LEAVE();
    return BT_STATUS_SUCCESS;
  release_irq:
    sdio_release_irq(func);
  release_host:
    sdio_release_host(func);
  failed:

    LEAVE();
    return BT_STATUS_FAILURE;
}
Example #27
0
static int ks7010_sdio_probe(struct sdio_func *func,
			     const struct sdio_device_id *device)
{
	struct ks_wlan_private *priv;
	struct ks_sdio_card *card;
	struct net_device *netdev;
	unsigned char byte;
	int ret;

	priv = NULL;
	netdev = NULL;

	card = kzalloc(sizeof(*card), GFP_KERNEL);
	if (!card)
		return -ENOMEM;

	card->func = func;

	sdio_claim_host(func);

	ret = sdio_set_block_size(func, KS7010_IO_BLOCK_SIZE);
	DPRINTK(5, "multi_block=%d sdio_set_block_size()=%d %d\n",
		func->card->cccr.multi_block, func->cur_blksize, ret);

	ret = sdio_enable_func(func);
	DPRINTK(5, "sdio_enable_func() %d\n", ret);
	if (ret)
		goto err_free_card;

	/* interrupt disable */
	sdio_writeb(func, 0, INT_ENABLE, &ret);
	if (ret)
		goto err_free_card;
	sdio_writeb(func, 0xff, INT_PENDING, &ret);
	if (ret)
		goto err_disable_func;

	/* setup interrupt handler */
	ret = sdio_claim_irq(func, ks_sdio_interrupt);
	if (ret)
		goto err_disable_func;

	sdio_release_host(func);

	sdio_set_drvdata(func, card);

	DPRINTK(5, "class = 0x%X, vendor = 0x%X, device = 0x%X\n",
		func->class, func->vendor, func->device);

	/* private memory allocate */
	netdev = alloc_etherdev(sizeof(*priv));
	if (!netdev) {
		dev_err(&card->func->dev, "ks7010 : Unable to alloc new net device\n");
		goto err_release_irq;
	}
	if (dev_alloc_name(netdev, "wlan%d") < 0) {
		dev_err(&card->func->dev,
			"ks7010 :  Couldn't get name!\n");
		goto err_free_netdev;
	}

	priv = netdev_priv(netdev);

	card->priv = priv;
	SET_NETDEV_DEV(netdev, &card->func->dev);	/* for create sysfs symlinks */

	/* private memory initialize */
	priv->ks_sdio_card = card;

	priv->dev_state = DEVICE_STATE_PREBOOT;
	priv->net_dev = netdev;
	priv->firmware_version[0] = '\0';
	priv->version_size = 0;
	priv->last_doze = jiffies;
	priv->last_wakeup = jiffies;
	memset(&priv->nstats, 0, sizeof(priv->nstats));
	memset(&priv->wstats, 0, sizeof(priv->wstats));

	/* sleep mode */
	atomic_set(&priv->sleepstatus.doze_request, 0);
	atomic_set(&priv->sleepstatus.wakeup_request, 0);
	atomic_set(&priv->sleepstatus.wakeup_request, 0);

	trx_device_init(priv);
	hostif_init(priv);
	ks_wlan_net_start(netdev);

	ks7010_init_defaults(priv);

	ret = ks7010_upload_firmware(card);
	if (ret) {
		dev_err(&card->func->dev,
			"ks7010: firmware load failed !! return code = %d\n",
			 ret);
		goto err_free_netdev;
	}

	/* interrupt setting */
	/* clear Interrupt status write (ARMtoSD_InterruptPending FN1:00_0024) */
	sdio_claim_host(func);
	ret = ks7010_sdio_writeb(priv, INT_PENDING, 0xff);
	sdio_release_host(func);
	if (ret)
		DPRINTK(1, " error : INT_PENDING\n");

	/* enable ks7010sdio interrupt */
	byte = (INT_GCR_B | INT_READ_STATUS | INT_WRITE_STATUS);
	sdio_claim_host(func);
	ret = ks7010_sdio_writeb(priv, INT_ENABLE, byte);
	sdio_release_host(func);
	if (ret)
		DPRINTK(1, " err : INT_ENABLE\n");

	DPRINTK(4, " enable Interrupt : INT_ENABLE=%02X\n", byte);
	priv->dev_state = DEVICE_STATE_BOOT;

	priv->wq = create_workqueue("wq");
	if (!priv->wq) {
		DPRINTK(1, "create_workqueue failed !!\n");
		goto err_free_netdev;
	}

	INIT_DELAYED_WORK(&priv->rw_dwork, ks7010_rw_function);
	ks7010_card_init(priv);

	ret = register_netdev(priv->net_dev);
	if (ret)
		goto err_free_netdev;

	return 0;

 err_free_netdev:
	free_netdev(priv->net_dev);
	card->priv = NULL;
 err_release_irq:
	sdio_claim_host(func);
	sdio_release_irq(func);
 err_disable_func:
	sdio_disable_func(func);
 err_free_card:
	sdio_release_host(func);
	sdio_set_drvdata(func, NULL);
	kfree(card);

	return -ENODEV;
}
Example #28
0
static int iwm_sdio_probe(struct sdio_func *func,
			  const struct sdio_device_id *id)
{
	struct iwm_priv *iwm;
	struct iwm_sdio_priv *hw;
	struct device *dev = &func->dev;
	int ret;

	/* check if TOP has already initialized the card */
	sdio_claim_host(func);
	ret = sdio_enable_func(func);
	if (ret) {
		dev_err(dev, "wait for TOP to enable the device\n");
		sdio_release_host(func);
		return ret;
	}

	ret = sdio_set_block_size(func, IWM_SDIO_BLK_SIZE);

	sdio_disable_func(func);
	sdio_release_host(func);

	if (ret < 0) {
		dev_err(dev, "Failed to set block size: %d\n", ret);
		return ret;
	}

	iwm = iwm_if_alloc(sizeof(struct iwm_sdio_priv), dev, &if_sdio_ops);
	if (IS_ERR(iwm)) {
		dev_err(dev, "allocate SDIO interface failed\n");
		return PTR_ERR(iwm);
	}

	hw = iwm_private(iwm);
	hw->iwm = iwm;

	iwm_debugfs_init(iwm);

	sdio_set_drvdata(func, hw);

	hw->func = func;
	hw->blk_size = IWM_SDIO_BLK_SIZE;

	hw->isr_wq = create_singlethread_workqueue(KBUILD_MODNAME "_sdio");
	if (!hw->isr_wq) {
		ret = -ENOMEM;
		goto debugfs_exit;
	}

	INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker);

	ret = iwm_if_add(iwm);
	if (ret) {
		dev_err(dev, "add SDIO interface failed\n");
		goto destroy_wq;
	}

	dev_info(dev, "IWM SDIO probe\n");

	return 0;

 destroy_wq:
	destroy_workqueue(hw->isr_wq);
 debugfs_exit:
	iwm_debugfs_exit(iwm);
	iwm_if_free(iwm);
	return ret;
}
/**
 *  @brief This function registers the device.
 *
 *  @param priv    A pointer to bt_private structure
 *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
int
sbi_register_dev(bt_private *priv)
{
	int ret = BT_STATUS_SUCCESS;
	u8 reg;
	u8 chiprev;
	struct sdio_mmc_card *card = priv->bt_dev.card;
	struct sdio_func *func;
	u8 host_intstatus_reg = HOST_INTSTATUS_REG;
	u8 card_revision_reg = CARD_REVISION_REG;
	u8 io_port_0_reg = IO_PORT_0_REG;
	u8 io_port_1_reg = IO_PORT_1_REG;
	u8 io_port_2_reg = IO_PORT_2_REG;

	ENTER();

	if (!card || !card->func) {
		PRINTM(ERROR, "BT: Error: card or function is NULL!\n");
		goto failed;
	}
	func = card->func;
	priv->hotplug_device = &func->dev;

	/* Initialize the private structure */
	strncpy(priv->bt_dev.name, "bt_sdio0", sizeof(priv->bt_dev.name));
	priv->bt_dev.ioport = 0;
	priv->bt_dev.fn = func->num;

	sdio_claim_host(func);
	ret = sdio_claim_irq(func, sd_interrupt);
	if (ret) {
		PRINTM(FATAL, ": sdio_claim_irq failed: ret=%d\n", ret);
		goto release_host;
	}
	ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
	if (ret) {
		PRINTM(FATAL, ": %s: cannot set SDIO block size\n", __func__);
		goto release_irq;
	}

	/* read Revision Register to get the chip revision number */
	chiprev = sdio_readb(func, card_revision_reg, &ret);
	if (ret) {
		PRINTM(FATAL, ": cannot read CARD_REVISION_REG\n");
		goto release_irq;
	}
	priv->adapter->chip_rev = chiprev;
	PRINTM(INFO, "revision=%#x\n", chiprev);

	/*
	 * Read the HOST_INTSTATUS_REG for ACK the first interrupt got
	 * from the bootloader. If we don't do this we get a interrupt
	 * as soon as we register the irq.
	 */
	reg = sdio_readb(func, host_intstatus_reg, &ret);
	if (ret < 0)
		goto release_irq;

	/* Read the IO port */
	reg = sdio_readb(func, io_port_0_reg, &ret);
	if (ret < 0)
		goto release_irq;
	else
		priv->bt_dev.ioport |= reg;

	reg = sdio_readb(func, io_port_1_reg, &ret);
	if (ret < 0)
		goto release_irq;
	else
		priv->bt_dev.ioport |= (reg << 8);

	reg = sdio_readb(func, io_port_2_reg, &ret);
	if (ret < 0)
		goto release_irq;
	else
		priv->bt_dev.ioport |= (reg << 16);

	PRINTM(INFO, ": SDIO FUNC%d IO port: 0x%x\n", priv->bt_dev.fn,
	       priv->bt_dev.ioport);

	sdio_set_drvdata(func, card);
	sdio_release_host(func);

	LEAVE();
	return BT_STATUS_SUCCESS;
release_irq:
	sdio_release_irq(func);
release_host:
	sdio_release_host(func);
failed:

	LEAVE();
	return BT_STATUS_FAILURE;
}
static int wl1251_sdio_probe(struct sdio_func *func,
			     const struct sdio_device_id *id)
{
	int ret;
	struct wl1251 *wl;
	struct ieee80211_hw *hw;

	hw = wl1251_alloc_hw();
	if (IS_ERR(hw))
		return PTR_ERR(hw);

	wl = hw->priv;

	sdio_claim_host(func);
	ret = sdio_enable_func(func);
	if (ret)
		goto release;

	sdio_set_block_size(func, 512);
	sdio_release_host(func);

	SET_IEEE80211_DEV(hw, &func->dev);
	wl->if_priv = func;
	wl->if_ops = &wl1251_sdio_ops;
	wl->set_power = wl1251_sdio_set_power;

	if (wl12xx_board_data != NULL) {
		wl->set_power = wl12xx_board_data->set_power;
		wl->irq = wl12xx_board_data->irq;
		wl->use_eeprom = wl12xx_board_data->use_eeprom;
	}

	if (wl->irq) {
		ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
		if (ret < 0) {
			wl1251_error("request_irq() failed: %d", ret);
			goto disable;
		}

		set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
		disable_irq(wl->irq);

		wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
		wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;

		wl1251_info("using dedicated interrupt line");
	} else {
		wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
		wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;

		wl1251_info("using SDIO interrupt");
	}

	ret = wl1251_init_ieee80211(wl);
	if (ret)
		goto out_free_irq;

	sdio_set_drvdata(func, wl);
	return ret;

out_free_irq:
	if (wl->irq)
		free_irq(wl->irq, wl);
disable:
	sdio_claim_host(func);
	sdio_disable_func(func);
release:
	sdio_release_host(func);
	wl1251_free_hw(wl);
	return ret;
}