static ssize_t cbp_reset_store(struct kobject *kobj, struct kobj_attribute *attr,
			   const char *buf, size_t n)
{
	unsigned long val;

	if (strict_strtoul(buf, 10, &val))
		return -EINVAL;

	if (val < 0)
		return -EINVAL;

	if (val){
		//sys_reset_cbp();
		//c2k_modem_reset_platform();
		c2k_reset_modem();
		
		LOGPRT(LOG_INFO,  "AP reset CBP.\n");
	}
	else{
		LOGPRT(LOG_ERR,  "%s: reset cbp use value 1.\n", __func__);
	}

	return n;
}
static int modem_detect_host(const char *host_id)
{
	/* HACK!!!
	 * Rely on mmc->class_dev.class set in mmc_alloc_host
	 * Tricky part: a new mmc hook is being (temporary) created
	 * to discover mmc_host class.
	 * Do you know more elegant way how to enumerate mmc_hosts?
	 */
	struct mmc_host *mmc = NULL;
	struct class_dev_iter iter;
	struct device *dev;
	int ret = -1;
#if 1
	printk("[C2K] before alloc host\n");
	mmc = mmc_alloc_host(0, NULL);
	if (!mmc){
		printk("[C2K] mmc_aloc_host error\n");
		ret =  -ENOMEM;
		goto out;
	}

	printk("[C2K] mmc_aloc_host success\n");
	BUG_ON(!mmc->class_dev.class);
	class_dev_iter_init(&iter, mmc->class_dev.class, NULL, NULL);
	for (;;) {
		dev = class_dev_iter_next(&iter);
		if (!dev) {
			printk("[C2K] class dev iter next failed\n");
			LOGPRT(LOG_ERR,  "%s: %d\n", __func__, __LINE__);
			break;
		} else {
			struct mmc_host *host = container_of(dev,
				struct mmc_host, class_dev);
			if (dev_name(&host->class_dev) &&
				strcmp(dev_name(&host->class_dev),
					host_id))
				continue;
			ret = 0;
			break;
		}
	}
	mmc_free_host(mmc);
#endif
	//ret = 0;
out:
	return ret;
}
static void modem_detect(struct work_struct *work)
{
	struct cbp_reset *cbp_rst_ind = NULL;
	int ret;
	int level = 0;

	LOGPRT(LOG_NOTICE,  "%s %d .\n",__func__,__LINE__);
	cbp_rst_ind = container_of(work, struct cbp_reset, reset_work);
#ifdef CONFIG_EVDO_DT_VIA_SUPPORT
	if((cbp_rst_ind->host == NULL)){/*for first detection and ipoh*/
         LOGPRT(LOG_NOTICE,  "%s %d modem_detect_card.\n",__func__,__LINE__);
        ret = modem_detect_card(cbp_rst_ind);
		if (ret){
			LOGPRT(LOG_ERR,  "%s: modem detect failed.\n", __func__);
		}
	}
	else{/*for device reset*/
		level = !!c2k_gpio_get_value(cbp_rst_ind->rst_ind_gpio);
		if(level == cbp_rst_ind->rst_ind_polar){
			LOGPRT(LOG_NOTICE,  "%s %d power on sdio host\n", __func__, __LINE__);
		c2k_wake_host(0);
            c2k_wake_host(1);
		}
		else{
			LOGPRT(LOG_NOTICE,  "%s %d power off sdio host\n", __func__, __LINE__);
			//c2k_gpio_direction_output(GPIO_C2K_MDM_PWR_EN, 1);
			modem_reset_handler();
			c2k_wake_host(0);
		}
	}
#else

	level = !!c2k_gpio_get_value(cbp_rst_ind->rst_ind_gpio);
	if(level == cbp_rst_ind->rst_ind_polar){
		LOGPRT(LOG_NOTICE,  "%s %d power on sdio host\n", __func__, __LINE__);
		c2k_wake_host(0);
		c2k_wake_host(1);
	}
	else{
		LOGPRT(LOG_NOTICE,  "%s %d power off sdio host\n", __func__, __LINE__);
		//c2k_gpio_direction_output(GPIO_C2K_MDM_PWR_EN, 1);
		modem_reset_handler();
		c2k_wake_host(0);
	}

#endif


}
static irqreturn_t c2k_wdt_isr(int irq, void *data)
{
	unsigned long flags;
	struct cbp_platform_data *cdata = &cbp_data;
	
	LOGPRT(LOG_ERR,  "%s: receive c2k wdt interrupt, prepare to reset c2k...!\n", __func__);
	dump_c2k_iram();
	//wake_lock_timeout(&cmdata->wlock, MDM_RST_LOCK_TIME * HZ);
    modem_notify_event(MDM_EVT_NOTIFY_WDT);

	spin_lock_irqsave(&cdata->modem->status_lock, flags);
	cdata->modem->status = MD_OFF;
	spin_unlock_irqrestore(&cdata->modem->status_lock, flags);

	atomic_set(&cdata->modem->tx_fifo_cnt, TX_FIFO_SZ);
	wake_up(&cdata->modem->wait_tx_done_q);
	
	return IRQ_HANDLED;
}
static ssize_t cbp_jtag_store(struct kobject *kobj, struct kobj_attribute *attr,
			   const char *buf, size_t n)
{
	unsigned long val;

	if (strict_strtoul(buf, 10, &val))
		return -EINVAL;

	if (val < 0)
		return -EINVAL;

	if (val){
		//sys_reset_cbp();
		//c2k_modem_reset_platform();
		jtag_mode = val;
		enable_c2k_jtag(val);
		
		LOGPRT(LOG_INFO,  "set cbp jtag to mode %d.\n", jtag_mode);
	}

	return n;
}
void gpio_irq_cbp_rst_ind(void)
{
	int level = 0;
	unsigned long flags;
	struct cbp_platform_data *cdata = &cbp_data;

	level = !!c2k_gpio_get_value(cbp_rst_ind->rst_ind_gpio);
	if(level != cbp_rst_ind->rst_ind_polar){/*1:cbp reset happened*/
		if (cdata->modem){
			LOGPRT(LOG_INFO,  "%s: set md off.\n", __func__);
			spin_lock_irqsave(&cdata->modem->status_lock, flags);
			cdata->modem->status = MD_OFF;
			spin_unlock_irqrestore(&cdata->modem->status_lock, flags);
		}
#ifdef CONFIG_EVDO_DT_VIA_SUPPORT
		wake_up(&cbp_flow_ctrl->wait_q);
		wake_up(&cbp_data_ack->wait_q);
#else
		atomic_set(&cdata->modem->tx_fifo_cnt, TX_FIFO_SZ);
		wake_up(&cdata->modem->wait_tx_done_q);
#endif
	}
	queue_work(cbp_rst_ind->reset_wq, &cbp_rst_ind->reset_work);
}
//static int __devinit cbp_probe(struct platform_device *pdev)
static int cbp_probe(struct platform_device *pdev)
{
	struct cbp_platform_data *plat = pdev->dev.platform_data;
	int ret = -1;
	
	/* must have platform data */
	if (!plat) {
		LOGPRT(LOG_ERR,  "%s: no platform data!\n", __func__);
		ret = -EINVAL;
		goto out;
	}
#if 0
	if(plat->bus && !strcmp(plat->bus,"sdio")){
		if(plat->detect_host){
			ret = plat->detect_host(plat->host_id);
			if(ret){
				LOGPRT(LOG_ERR,  "%s: host %s dectect failed!\n", __func__, plat->host_id);
				goto out;
			}
		}
		else{
			LOGPRT(LOG_ERR,  "%s: bus %s have no dectect function!\n", __func__, plat->bus);
			goto out;
		}
	}
	else{
		LOGPRT(LOG_ERR,  "%s: unknow bus!\n", __func__);
		goto out;
	}
#endif

	if(GPIO_C2K_VALID(plat->gpio_data_ack)){
		cbp_data_ack = kzalloc(sizeof(struct cbp_wait_event), GFP_KERNEL);
		if (!cbp_data_ack){
			ret = -ENOMEM;
			LOGPRT(LOG_ERR,  "%s %d kzalloc cbp_data_ack failed \n",__func__, __LINE__);
			goto err_kzalloc_cbp_data_ack;    
		}

		init_waitqueue_head(&cbp_data_ack->wait_q);
		atomic_set(&cbp_data_ack->state, MODEM_ST_UNKNOW);
		cbp_data_ack->wait_gpio = plat->gpio_data_ack;
		cbp_data_ack->wait_polar = plat->gpio_data_ack_polar;
		LOGPRT(LOG_ERR,  "cbp_data_ack->wait_gpio=%d\n",cbp_data_ack->wait_gpio);
		LOGPRT(LOG_ERR,  "cbp_data_ack->wait_polar=%d\n",cbp_data_ack->wait_polar);
		
		c2k_gpio_irq_mask(plat->gpio_data_ack);
		c2k_gpio_direction_input_for_irq(plat->gpio_data_ack);
		c2k_gpio_set_irq_type(plat->gpio_data_ack, IRQF_TRIGGER_FALLING);
		ret = c2k_gpio_request_irq(plat->gpio_data_ack, gpio_irq_data_ack, 
				IRQF_SHARED | IRQF_TRIGGER_FALLING, DRIVER_NAME "(data_ack)", cbp_data_ack);
		c2k_gpio_irq_unmask(plat->gpio_data_ack);
		if (ret < 0) {
			LOGPRT(LOG_ERR,  "%s: %d fail to request irq for data_ack!!\n", __func__, __LINE__);
			goto err_req_irq_data_ack;
		}
		plat->cbp_data_ack = cbp_data_ack;
		plat->data_ack_wait_event = data_ack_wait_event;
		plat->data_ack_enable =true;
	}

	if(GPIO_C2K_VALID(plat->gpio_flow_ctrl)){
		cbp_flow_ctrl = kzalloc(sizeof(struct cbp_wait_event), GFP_KERNEL);
		if (!cbp_flow_ctrl){
			ret = -ENOMEM;
			LOGPRT(LOG_ERR,  "%s %d kzalloc cbp_flow_ctrl failed \n",__func__, __LINE__);
			goto err_kzalloc_cbp_flow_ctrl;    
		}

		init_waitqueue_head(&cbp_flow_ctrl->wait_q);
		atomic_set(&cbp_flow_ctrl->state, FLOW_CTRL_DISABLE);
		cbp_flow_ctrl->wait_gpio = plat->gpio_flow_ctrl;
		cbp_flow_ctrl->wait_polar = plat->gpio_flow_ctrl_polar;
		LOGPRT(LOG_ERR,  "cbp_flow_ctrl->wait_gpio=%d\n",cbp_flow_ctrl->wait_gpio);
		LOGPRT(LOG_ERR,  "cbp_flow_ctrl->wait_polar=%d\n",cbp_flow_ctrl->wait_polar);
		
		c2k_gpio_irq_mask(plat->gpio_flow_ctrl);
		c2k_gpio_direction_input_for_irq(plat->gpio_flow_ctrl);
		//c2k_gpio_set_irq_type(plat->gpio_flow_ctrl, IRQ_TYPE_LEVEL_LOW |IRQ_TYPE_LEVEL_HIGH);
		c2k_gpio_set_irq_type(plat->gpio_flow_ctrl, IRQF_TRIGGER_FALLING);
		ret = c2k_gpio_request_irq(plat->gpio_flow_ctrl, gpio_irq_flow_ctrl, 
				IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
				DRIVER_NAME "(flow_ctrl)", cbp_flow_ctrl);
		c2k_gpio_irq_unmask(plat->gpio_flow_ctrl);
		if (ret < 0) {
			LOGPRT(LOG_ERR,  "%s: %d fail to request irq for flow_ctrl!!\n", __func__, __LINE__);
			goto err_req_irq_flow_ctrl;
		}
		
		plat->cbp_flow_ctrl= cbp_flow_ctrl;
		plat->flow_ctrl_wait_event = flow_ctrl_wait_event;
		plat->flow_ctrl_enable = true;
	}
	
	
	if(GPIO_C2K_VALID(plat->gpio_rst_ind)){
		cbp_rst_ind = kzalloc(sizeof(struct cbp_reset), GFP_KERNEL);
		if (!cbp_rst_ind){
			ret = -ENOMEM;
			LOGPRT(LOG_ERR,  "%s %d kzalloc cbp_rst_ind failed \n",__func__, __LINE__);
			goto err_kzalloc_cbp_rst_ind;    
		}

		cbp_rst_ind->name = "cbp_rst_ind_wq";
		cbp_rst_ind->reset_wq = create_singlethread_workqueue(cbp_rst_ind->name);
		if (cbp_rst_ind->reset_wq == NULL) {
			ret = -ENOMEM;
			LOGPRT(LOG_ERR,  "%s %d error creat rst_ind_workqueue \n",__func__, __LINE__);
			goto err_create_work_queue;
		}
		INIT_WORK(&cbp_rst_ind->reset_work, modem_detect);
		cbp_rst_ind->rst_ind_gpio = plat->gpio_rst_ind;
		cbp_rst_ind->rst_ind_polar = plat->gpio_rst_ind_polar;
		cbp_rst_ind->host = NULL;
#if 0		
		c2k_gpio_irq_mask(plat->gpio_rst_ind);
		c2k_gpio_direction_input_for_irq(plat->gpio_rst_ind);
		c2k_gpio_set_irq_type(plat->gpio_rst_ind, IRQF_TRIGGER_FALLING |IRQF_TRIGGER_RISING);
		ret = c2k_gpio_request_irq(plat->gpio_rst_ind, gpio_irq_cbp_rst_ind, 
			IRQF_SHARED |IRQF_TRIGGER_FALLING |IRQF_TRIGGER_RISING, 
			DRIVER_NAME "(rst_ind)", cbp_rst_ind);
		c2k_gpio_irq_unmask(plat->gpio_rst_ind);
		if (ret < 0) {
			LOGPRT(LOG_ERR,  "%s: %d fail to request irq for rst_ind!!\n", __func__, __LINE__);
			goto err_req_irq_rst_ind;
		}
#endif
		plat->rst_ind_enable = true;
	}

		cbp_excp_ind = kzalloc(sizeof(struct cbp_exception), GFP_KERNEL);
		if (!cbp_excp_ind){
			ret = -ENOMEM;
			LOGPRT(LOG_ERR,  "%s %d kzalloc cbp_rst_ind failed \n",__func__, __LINE__);
			goto err_kzalloc_cbp_excp_ind;	 
		}

		cbp_excp_ind->name = "cbp_excp_ind_wq";
		cbp_excp_ind->excp_wq = create_singlethread_workqueue(cbp_excp_ind->name);
		if (cbp_excp_ind->excp_wq == NULL) {
			ret = -ENOMEM;
			LOGPRT(LOG_ERR,  "%s %d error creat rst_ind_workqueue \n",__func__, __LINE__);
			goto err_create_excp_work_queue;
		}
		//Todo: workqueue function need to be implemented
		//INIT_WORK(&cbp_excp_ind->excp_work, modem_detect);
		INIT_WORK(&cbp_excp_ind->excp_work, modem_detect_for_excp);
		cbp_excp_ind->host = NULL;

#ifndef CONFIG_EVDO_DT_VIA_SUPPORT
	if (GPIO_C2K_VALID(plat->gpio_cp_exception)){
		cbp_excp_ind->excp_ind_gpio = plat->gpio_cp_exception;
		
		c2k_gpio_irq_mask(plat->gpio_cp_exception);
		c2k_gpio_set_irq_type(plat->gpio_cp_exception, IRQF_TRIGGER_FALLING);
		ret = c2k_gpio_request_irq(plat->gpio_cp_exception, gpio_irq_cbp_excp_ind, 
				IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
				DRIVER_NAME "(c2k EE)", cbp_excp_ind);
		c2k_gpio_irq_unmask(plat->gpio_cp_exception);
		if (ret < 0) {
			LOGPRT(LOG_ERR,  "%s: %d fail to request irq for flow_ctrl!!\n", __func__, __LINE__);
			goto err_req_irq_excp;
		}
	}
	plat->c2k_wdt_irq_id = get_c2k_wdt_irq_id();
	LOGPRT(LOG_INFO, "get c2k wdt irq id %d\n", plat->c2k_wdt_irq_id);
#if 1
	if (plat->c2k_wdt_irq_id)
		ret = request_irq(plat->c2k_wdt_irq_id, c2k_wdt_isr, IRQF_TRIGGER_NONE, "C2K_CCCI", plat);
	else
		LOGPRT(LOG_ERR,  "%s: %d fail to get wdt irq id!!\n", __func__, __LINE__);
#endif
#endif

	if((GPIO_C2K_VALID(plat->gpio_ap_wkup_cp)) && (GPIO_C2K_VALID(plat->gpio_cp_ready)) &&
		(GPIO_C2K_VALID(plat->gpio_cp_wkup_ap))  && (GPIO_C2K_VALID(plat->gpio_ap_ready))){
		sdio_tx_handle.gpio_wake = plat->gpio_ap_wkup_cp;
		sdio_tx_handle.gpio_ready = plat->gpio_cp_ready;
		sdio_tx_handle.polar = plat->gpio_sync_polar;
		ret = asc_tx_register_handle(&sdio_tx_handle);
		if(ret){
			LOGPRT(LOG_ERR,  "%s %d asc_tx_register_handle failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}
		ret = asc_tx_add_user(sdio_tx_handle.name, &sdio_tx_user);
		if(ret){
			LOGPRT(LOG_ERR,  "%s %d asc_tx_add_user failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}

		sdio_rx_handle.gpio_wake = plat->gpio_cp_wkup_ap;
		sdio_rx_handle.gpio_ready = plat->gpio_ap_ready;
		sdio_rx_handle.polar = plat->gpio_sync_polar;
		ret = asc_rx_register_handle(&sdio_rx_handle);
		if(ret){
			LOGPRT(LOG_ERR,  "%s %d asc_rx_register_handle failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}
		ret = asc_rx_add_user(sdio_rx_handle.name, &sdio_rx_user);
		if(ret){
			LOGPRT(LOG_ERR,  "%s %d asc_rx_add_user failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}
		plat->ipc_enable = true;
		plat->tx_handle = &sdio_tx_handle;
	}
	
	ret = plat->cbp_setup(plat);
	if(ret){
		LOGPRT(LOG_ERR,  "%s: host %s setup failed!\n", __func__, plat->host_id);
		goto err_ipc;
	}
	cbp_power_kobj = c2k_kobject_add("power");
	if (!cbp_power_kobj){
		LOGPRT(LOG_ERR,  "error c2k_kobject_add!\n");
		ret = -ENOMEM;
		goto err_create_kobj;
	}
	LOGPRT(LOG_INFO,  " cbp initialized on host %s successfully, bus is %s !\n", plat->host_id, plat->bus);
	return sysfs_create_group(cbp_power_kobj, &g_power_attr_group);
	
err_create_kobj:
	plat->cbp_destroy();
err_ipc:
#if 0
	if(GPIO_C2K_VALID(plat->gpio_rst_ind)){
		free_irq(c2k_gpio_to_irq(plat->gpio_rst_ind), cbp_rst_ind);
	}
err_req_irq_rst_ind:
	if(GPIO_C2K_VALID(plat->gpio_rst_ind)){
	}
#endif

#ifndef CONFIG_EVDO_DT_VIA_SUPPORT
err_req_irq_excp:
	if(GPIO_C2K_VALID(plat->gpio_cp_exception)){
		destroy_workqueue(cbp_excp_ind->excp_wq);
	}
#endif
err_create_excp_work_queue:
		kfree(cbp_excp_ind);
err_kzalloc_cbp_excp_ind:

	if(GPIO_C2K_VALID(plat->gpio_rst_ind)){
		destroy_workqueue(cbp_rst_ind->reset_wq);
	}
err_create_work_queue:
	if(GPIO_C2K_VALID(plat->gpio_rst_ind)){
		kfree(cbp_rst_ind);
	}
err_kzalloc_cbp_rst_ind:
	if(GPIO_C2K_VALID(plat->gpio_flow_ctrl)){
		free_irq(c2k_gpio_to_irq(plat->gpio_flow_ctrl), cbp_flow_ctrl);
	}
err_req_irq_flow_ctrl:
	if(GPIO_C2K_VALID(plat->gpio_flow_ctrl)){
		kfree(cbp_flow_ctrl);
	}
err_kzalloc_cbp_flow_ctrl:
	if(GPIO_C2K_VALID(plat->gpio_data_ack)){
		free_irq(c2k_gpio_to_irq(plat->gpio_data_ack), cbp_data_ack);
	}
err_req_irq_data_ack:
	if(GPIO_C2K_VALID(plat->gpio_data_ack)){
		kfree(cbp_data_ack);
	}
err_kzalloc_cbp_data_ack:
out:
	return ret;
}
Example #8
0
//static int __devinit cbp_probe(struct platform_device *pdev)
static int cbp_probe(struct platform_device *pdev)
{
	struct cbp_platform_data *plat = pdev->dev.platform_data;
	int ret = -1;
	
	/* must have platform data */
	if (!plat) {
		LOGPRT(LOG_ERR,  "%s: no platform data!\n", __func__);
		ret = -EINVAL;
		goto out;
	}
	
	if(plat->bus && !strcmp(plat->bus,"sdio")){
		if(plat->detect_host){
			ret = plat->detect_host(plat->host_id);
			if(ret){
				LOGPRT(LOG_ERR,  "%s: host %s dectect failed!\n", __func__, plat->host_id);
				goto out;
			}
		}
		else{
			LOGPRT(LOG_ERR,  "%s: bus %s have no dectect function!\n", __func__, plat->bus);
			goto out;
		}
	}
	else{
		LOGPRT(LOG_ERR,  "%s: unknow bus!\n", __func__);
		goto out;
	}

	if((GPIO_OEM_VALID(plat->gpio_sd_select)) && (GPIO_OEM_VALID(plat->gpio_mc3_enable))){
		ret = oem_gpio_request(plat->gpio_mc3_enable, DRIVER_NAME"(MC3_EN_N)");
		if(ret < 0){
			LOGPRT(LOG_ERR,  "%s: %d fail to requset MC3_EN_N gpio %d ret =%d!!\n",
				__func__, __LINE__, plat->gpio_mc3_enable,ret);
			goto out;
		}
		ret = oem_gpio_request(plat->gpio_sd_select, DRIVER_NAME"(SD_SEL_N)");
		if(ret < 0){
			LOGPRT(LOG_ERR,  "%s: %d fail to requset SD_SEL_N gpio %d ret =%d!!\n", 
				__func__, __LINE__, plat->gpio_sd_select,ret);
			goto err_req_sd_sel;
		}
		oem_gpio_direction_output(GPIO_VIATEL_MC3_EN_N, 0); //MC3_EN_N
		oem_gpio_direction_output(GPIO_VIATEL_SD_SEL_N, 0); //SD_SEL_N
	}

	if(GPIO_OEM_VALID(plat->gpio_data_ack)){
		cbp_data_ack = kzalloc(sizeof(struct cbp_wait_event), GFP_KERNEL);
		if (!cbp_data_ack){
			ret = -ENOMEM;
			LOGPRT(LOG_ERR,  "%s %d kzalloc cbp_data_ack failed \n",__func__, __LINE__);
			goto err_kzalloc_cbp_data_ack;    
		}

		init_waitqueue_head(&cbp_data_ack->wait_q);
		atomic_set(&cbp_data_ack->state, MODEM_ST_UNKNOW);
		cbp_data_ack->wait_gpio = plat->gpio_data_ack;
		cbp_data_ack->wait_polar = plat->gpio_data_ack_polar;
		LOGPRT(LOG_ERR,  "cbp_data_ack->wait_gpio=%d\n",cbp_data_ack->wait_gpio);
		LOGPRT(LOG_ERR,  "cbp_data_ack->wait_polar=%d\n",cbp_data_ack->wait_polar);
		ret = oem_gpio_request(plat->gpio_data_ack, DRIVER_NAME "(data_ack)");
		if(ret < 0){
			LOGPRT(LOG_ERR,  "%s: %d fail to requset data_ack gpio %d ret =%d!!\n", 
				__func__, __LINE__, plat->gpio_data_ack, ret);
			goto err_req_data_ack;
		}
		oem_gpio_irq_mask(plat->gpio_data_ack);
		oem_gpio_direction_input_for_irq(plat->gpio_data_ack);
		oem_gpio_set_irq_type(plat->gpio_data_ack, IRQF_TRIGGER_FALLING);
		ret = oem_gpio_request_irq(plat->gpio_data_ack, gpio_irq_data_ack, 
				IRQF_SHARED | IRQF_TRIGGER_FALLING, DRIVER_NAME "(data_ack)", cbp_data_ack);
		oem_gpio_irq_unmask(plat->gpio_data_ack);
		if (ret < 0) {
			LOGPRT(LOG_ERR,  "%s: %d fail to request irq for data_ack!!\n", __func__, __LINE__);
			goto err_req_irq_data_ack;
		}
		plat->cbp_data_ack = cbp_data_ack;
		plat->data_ack_wait_event = data_ack_wait_event;
		plat->data_ack_enable =true;
	}

	if(GPIO_OEM_VALID(plat->gpio_flow_ctrl)){
		cbp_flow_ctrl = kzalloc(sizeof(struct cbp_wait_event), GFP_KERNEL);
		if (!cbp_flow_ctrl){
			ret = -ENOMEM;
			LOGPRT(LOG_ERR,  "%s %d kzalloc cbp_flow_ctrl failed \n",__func__, __LINE__);
			goto err_kzalloc_cbp_flow_ctrl;    
		}

		init_waitqueue_head(&cbp_flow_ctrl->wait_q);
		atomic_set(&cbp_flow_ctrl->state, FLOW_CTRL_DISABLE);
		cbp_flow_ctrl->wait_gpio = plat->gpio_flow_ctrl;
		cbp_flow_ctrl->wait_polar = plat->gpio_flow_ctrl_polar;
		LOGPRT(LOG_ERR,  "cbp_flow_ctrl->wait_gpio=%d\n",cbp_flow_ctrl->wait_gpio);
		LOGPRT(LOG_ERR,  "cbp_flow_ctrl->wait_polar=%d\n",cbp_flow_ctrl->wait_polar);
		ret = oem_gpio_request(plat->gpio_flow_ctrl, DRIVER_NAME "(flow_ctrl)");
		if(ret < 0){
			LOGPRT(LOG_ERR,  "%s: %d fail to requset flow_ctrl gpio %d ret =%d!!\n", 
				__func__, __LINE__, plat->gpio_flow_ctrl, ret);
			goto err_req_flow_ctrl;
		}
		oem_gpio_irq_mask(plat->gpio_flow_ctrl);
		oem_gpio_direction_input_for_irq(plat->gpio_flow_ctrl);
		//oem_gpio_set_irq_type(plat->gpio_flow_ctrl, IRQ_TYPE_LEVEL_LOW |IRQ_TYPE_LEVEL_HIGH);
		oem_gpio_set_irq_type(plat->gpio_flow_ctrl, IRQF_TRIGGER_FALLING);
		ret = oem_gpio_request_irq(plat->gpio_flow_ctrl, gpio_irq_flow_ctrl, 
				IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
				DRIVER_NAME "(flow_ctrl)", cbp_flow_ctrl);
		oem_gpio_irq_unmask(plat->gpio_flow_ctrl);
		if (ret < 0) {
			LOGPRT(LOG_ERR,  "%s: %d fail to request irq for flow_ctrl!!\n", __func__, __LINE__);
			goto err_req_irq_flow_ctrl;
		}
		
		plat->cbp_flow_ctrl= cbp_flow_ctrl;
		plat->flow_ctrl_wait_event = flow_ctrl_wait_event;
		plat->flow_ctrl_enable = true;
	}
	
	
	if(GPIO_OEM_VALID(plat->gpio_rst_ind)){
		cbp_rst_ind = kzalloc(sizeof(struct cbp_reset), GFP_KERNEL);
		if (!cbp_rst_ind){
			ret = -ENOMEM;
			LOGPRT(LOG_ERR,  "%s %d kzalloc cbp_rst_ind failed \n",__func__, __LINE__);
			goto err_kzalloc_cbp_rst_ind;    
		}

		cbp_rst_ind->name = "cbp_rst_ind_wq";
		cbp_rst_ind->reset_wq = create_singlethread_workqueue(cbp_rst_ind->name);
		if (cbp_rst_ind->reset_wq == NULL) {
			ret = -ENOMEM;
			LOGPRT(LOG_ERR,  "%s %d error creat rst_ind_workqueue \n",__func__, __LINE__);
			goto err_create_work_queue;
		}
		INIT_WORK(&cbp_rst_ind->reset_work, modem_detect);
		cbp_rst_ind->rst_ind_gpio = plat->gpio_rst_ind;
		cbp_rst_ind->rst_ind_polar = plat->gpio_rst_ind_polar;
		cbp_rst_ind->host = NULL;
#if 0		
		ret = oem_gpio_request(plat->gpio_rst_ind, DRIVER_NAME "(rst_ind)");
		if(ret < 0){
			LOGPRT(LOG_ERR,  "%s: %d fail to requset rst_ind gpio %d ret =%d!!\n", 
				__func__, __LINE__, plat->gpio_rst_ind, ret);
			goto err_req_rst_ind;
		}

		oem_gpio_irq_mask(plat->gpio_rst_ind);
		oem_gpio_direction_input_for_irq(plat->gpio_rst_ind);
		oem_gpio_set_irq_type(plat->gpio_rst_ind, IRQF_TRIGGER_FALLING |IRQF_TRIGGER_RISING);
		ret = oem_gpio_request_irq(plat->gpio_rst_ind, gpio_irq_cbp_rst_ind, 
			IRQF_SHARED |IRQF_TRIGGER_FALLING |IRQF_TRIGGER_RISING, 
			DRIVER_NAME "(rst_ind)", cbp_rst_ind);
		oem_gpio_irq_unmask(plat->gpio_rst_ind);
		if (ret < 0) {
			LOGPRT(LOG_ERR,  "%s: %d fail to request irq for rst_ind!!\n", __func__, __LINE__);
			goto err_req_irq_rst_ind;
		}
#endif
		plat->rst_ind_enable = true;
	}

	if((GPIO_OEM_VALID(plat->gpio_ap_wkup_cp)) && (GPIO_OEM_VALID(plat->gpio_cp_ready)) &&
		(GPIO_OEM_VALID(plat->gpio_cp_wkup_ap))  && (GPIO_OEM_VALID(plat->gpio_ap_ready))){
		sdio_tx_handle.gpio_wake = plat->gpio_ap_wkup_cp;
		sdio_tx_handle.gpio_ready = plat->gpio_cp_ready;
		sdio_tx_handle.polar = plat->gpio_sync_polar;
		ret = asc_tx_register_handle(&sdio_tx_handle);
		if(ret){
			LOGPRT(LOG_ERR,  "%s %d asc_tx_register_handle failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}
		ret = asc_tx_add_user(sdio_tx_handle.name, &sdio_tx_user);
		if(ret){
			LOGPRT(LOG_ERR,  "%s %d asc_tx_add_user failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}

		sdio_rx_handle.gpio_wake = plat->gpio_cp_wkup_ap;
		sdio_rx_handle.gpio_ready = plat->gpio_ap_ready;
		sdio_rx_handle.polar = plat->gpio_sync_polar;
		ret = asc_rx_register_handle(&sdio_rx_handle);
		if(ret){
			LOGPRT(LOG_ERR,  "%s %d asc_rx_register_handle failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}
		ret = asc_rx_add_user(sdio_rx_handle.name, &sdio_rx_user);
		if(ret){
			LOGPRT(LOG_ERR,  "%s %d asc_rx_add_user failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}
		plat->ipc_enable = true;
		plat->tx_handle = &sdio_tx_handle;
	}
	
	ret = plat->cbp_setup(plat);
	if(ret){
		LOGPRT(LOG_ERR,  "%s: host %s setup failed!\n", __func__, plat->host_id);
		goto err_ipc;
	}
	cbp_power_kobj = viatel_kobject_add("power");
	if (!cbp_power_kobj){
		LOGPRT(LOG_ERR,  "error viatel_kobject_add!\n");
		ret = -ENOMEM;
		goto err_create_kobj;
	}
	LOGPRT(LOG_INFO,  " cbp initialized on host %s successfully, bus is %s !\n", plat->host_id, plat->bus);
	return sysfs_create_group(cbp_power_kobj, &g_power_attr_group);
	
err_create_kobj:
	plat->cbp_destroy();
err_ipc:
#if 0
	if(GPIO_OEM_VALID(plat->gpio_rst_ind)){
		free_irq(oem_gpio_to_irq(plat->gpio_rst_ind), cbp_rst_ind);
	}
err_req_irq_rst_ind:
	if(GPIO_OEM_VALID(plat->gpio_rst_ind)){
		oem_gpio_free(plat->gpio_rst_ind);
	}
#endif
err_req_rst_ind:
	if(GPIO_OEM_VALID(plat->gpio_rst_ind)){
		destroy_workqueue(cbp_rst_ind->reset_wq);
	}
err_create_work_queue:
	if(GPIO_OEM_VALID(plat->gpio_rst_ind)){
		kfree(cbp_rst_ind);
	}
err_kzalloc_cbp_rst_ind:
	if(GPIO_OEM_VALID(plat->gpio_flow_ctrl)){
		free_irq(oem_gpio_to_irq(plat->gpio_flow_ctrl), cbp_flow_ctrl);
	}
err_req_irq_flow_ctrl:
	if(GPIO_OEM_VALID(plat->gpio_flow_ctrl)){
		oem_gpio_free(plat->gpio_flow_ctrl);
	}
err_req_flow_ctrl:
	if(GPIO_OEM_VALID(plat->gpio_flow_ctrl)){
		kfree(cbp_flow_ctrl);
	}
err_kzalloc_cbp_flow_ctrl:
	if(GPIO_OEM_VALID(plat->gpio_data_ack)){
		free_irq(oem_gpio_to_irq(plat->gpio_data_ack), cbp_data_ack);
	}
err_req_irq_data_ack:
	if(GPIO_OEM_VALID(plat->gpio_data_ack)){
		oem_gpio_free(plat->gpio_data_ack);
	}
err_req_data_ack:
	if(GPIO_OEM_VALID(plat->gpio_data_ack)){
		kfree(cbp_data_ack);
	}
err_kzalloc_cbp_data_ack:
	if((GPIO_OEM_VALID(plat->gpio_sd_select)) && (GPIO_OEM_VALID(plat->gpio_mc3_enable))){
		oem_gpio_free(plat->gpio_sd_select);
	}
err_req_sd_sel:
	if((GPIO_OEM_VALID(plat->gpio_sd_select)) && (GPIO_OEM_VALID(plat->gpio_mc3_enable))){
		oem_gpio_free(plat->gpio_mc3_enable);
	}
out:
	return ret;
}