/**
* @brief 	Scatter list data  transfer function.
* @param 	sd[in]: Card information.
* @param 	sector[in]: Start sector.
* @param 	sg[in]: Scatter list pointer.
* @param 	ln[in]: List number.
* @return 	Actual sectors by reading/ERROR_ID(<0).
*/ 
static int gp_sdcard_transfer_scatter(gpSDInfo_t *sd, unsigned long sector, struct scatterlist *sg, unsigned int ln, int write)
{
	int ret;
	int pin_handle;
	/* ----- Check card status ----- */
	if((gp_sdcard_ckinsert(sd)==0)||(sd->handle_dma==0))
		return -ENXIO;
	/* ----- Get pin handle ----- */
	pin_handle = gp_board_pin_func_request((sd->device_id==0)?GP_PIN_SD0:GP_PIN_SD1, GP_BOARD_WAIT_FOREVER);
	if(pin_handle<0)
	{
		DERROR("SD%d: can't get pin handle\n", sd->device_id);
		return -EIO;
	}
	if(write==0)
	{
		ret = gp_sdcard_read_scatter(sd, sector, sg, ln);
	}
	else
	{
		/* ----- Check write protect ----- */
		if(sd->sd_func->is_write_protected()==1)
			ret = -EROFS;
		else
			ret = gp_sdcard_write_scatter(sd, sector, sg, ln);
	}	
	gp_board_pin_func_release(pin_handle);
	return ret;
}
Beispiel #2
0
/**
* @brief 	SD suspend function.
* @param 	pdev[in]: Platform device pointer.
* @param 	state[in]: Suspend event.
* @return 	SUCCESS/ERROR_ID.
*/
static int gp_sd_suspend(struct platform_device *pdev, pm_message_t state)
{
	int i ;
	DEBUG("SD suspend\n");
	for(i = 0; i < SD_NUM; i++)
	{
		gpSDInfo_t *sd = &sd_info[i];
		/* diable sd clock */
		if( (sd->present==1) && (gp_sdcard_ckinsert(sd)==1) )
		{
			gp_sdcard_carduninit(sd);
		}
	}
	return 0;
}
Beispiel #3
0
/**
* @brief 	SD card open.
* @param 	dev[in]: Block device pointer.
* @param 	mode[in]: Mode.
* @return 	SUCCESS/ERROR_ID.
 */
static int gp_sdcard_open(struct block_device *dev, fmode_t mode)
{
	gpSDInfo_t *sd = dev->bd_disk->private_data;

	if(gp_sdcard_ckinsert(sd)==0)
		return -ENXIO;
	/* ----- Check write protect ----- */
	if((mode&FMODE_WRITE)&&(gp_sdcard_ckwp(sd)==1))
	{
		DEBUG("Read only card\n");
		return -EROFS;
	}
	sd->users++;
	//DEBUG("[%s]: user %d, status %d\n",__FUNCTION__,sd->users,sd->status);
	return 0;
}
Beispiel #4
0
/**
* @brief 	Request thread function.
* @param 	d[in]: Private data.
* @return 	SUCCESS/ERROR_ID.
*/
static int gp_sdcard_queue_thread(void *d)
{
	gpSDInfo_t *sd = d;
	struct request_queue *q = sd->queue;

	current->flags |= PF_MEMALLOC;

	down(&sd->thread_sem);
	do
	{
		struct request *req = NULL;
		if(sd->queue==NULL)
			continue;
		spin_lock_irq(q->queue_lock);
		set_current_state(TASK_INTERRUPTIBLE);
		if (!blk_queue_plugged(q))
			req = blk_fetch_request(q);
		sd->req = req;
		spin_unlock_irq(q->queue_lock);

		if (!req)
		{
			if (kthread_should_stop())
			{
				set_current_state(TASK_RUNNING);
				break;
			}
			up(&sd->thread_sem);
			schedule();
			down(&sd->thread_sem);
			continue;
		}
		set_current_state(TASK_RUNNING);
		if((gp_sdcard_ckinsert(sd)==0))
		{
			spin_lock_irq(&sd->lock);
			__blk_end_request_all(req, -ENXIO);
			spin_unlock_irq(&sd->lock);
			sd->fremove = 1;
			continue;
		}
		if(gp_sdcard_xfer_request(sd, req)<0 && (gp_sdcard_inner_card(sd)!=1))
			sd->fremove = 1;
	} while (1);
	up(&sd->thread_sem);
	return 0;
}
/**
* @brief 	Timer function for check card insert.
* @param 	arg[in]: Private data.
* @return 	None.
*/ 
static void gp_sdcard_timer_fn(unsigned long arg)
{
	gpSDInfo_t* sd = (gpSDInfo_t*)arg;
	int insert = gp_sdcard_ckinsert(sd);
	/* ----- Card status change ----- */
	if( sd->present ^ insert)
	{
		if(insert==0)
		{
			sd->present = 0;	
			sd->cnt = 0;
			sd->users = 0;
			DEBUG("Card Remove\n");
			sd->sd_func->set_power(0);
			schedule_work(&sd->uninit);		
		}
		else
		{
			sd->cnt ++;
			if(sd->cnt>=SD_DEBOUNCE)
			{
				sd->present = 0;	
				sd->cnt = 0;
				sd->users = 0;			
				DEBUG("Card insert\n");
				sd->sd_func->set_power(1);
				schedule_work(&sd->init);
			}
			else
			{
				sd->timer.expires = jiffies + HZ/100;		/* 10ms */	
				add_timer(&sd->timer);
			}
		}
	}
	/* ----- Card status not change ----- */
	else
	{
		sd->timer.expires = jiffies + SD_CD_POLL;
		add_timer(&sd->timer);	
		sd->cnt = 0;
	}	
}
Beispiel #6
0
/**
* @brief 	Scatter list data  transfer function.
* @param 	sd[in]: Card information.
* @param 	sector[in]: Start sector.
* @param 	sg[in]: Scatter list pointer.
* @param 	ln[in]: List number.
* @return 	Actual sectors by reading/ERROR_ID(<0).
*/
static int gp_sdcard_transfer_scatter(gpSDInfo_t *sd, unsigned long sector, struct scatterlist *sg, unsigned int ln, int write)
{
	int ret;
	int pin_handle;
	int pin_id;
	/* ----- Check card status ----- */
	if(gp_sdcard_ckinsert(sd)==0)
	{
		sd->fremove = 1;
		return -ENXIO;
	}
#ifdef PIN_REQUEST_FUNCTION
	if(sd->device_id == 0)
		pin_id = GP_PIN_SD0;
	else if(sd->device_id == 1)
		pin_id = GP_PIN_SD1;
	else
		pin_id = GP_PIN_SD2;
	/* ----- Get pin handle ----- */
	pin_handle = gp_board_pin_func_request( pin_id, GP_BOARD_WAIT_FOREVER);
	if(pin_handle<0)
	{
		DERROR("[%d]: can't get pin handle\n", sd->device_id);
		return -EBUSY;
	}
#endif
	if(write==0)
	{
		ret = gp_sdcard_read_scatter(sd, sector, sg, ln);
	}
	else
	{
		/* ----- Check write protect ----- */
		if(sd->sd_func->is_write_protected()==1)
			ret = -EROFS;
		else
			ret = gp_sdcard_write_scatter(sd, sector, sg, ln);
	}
#ifdef PIN_REQUEST_FUNCTION
	gp_board_pin_func_release(pin_handle);
#endif
	return ret;
}
Beispiel #7
0
/**
* @brief 	Timer function for check card insert.
* @param 	arg[in]: Private data.
* @return 	None.
*/
static void gp_sdcard_timer_fn(unsigned long arg)
{

	gpSDInfo_t* sd = (gpSDInfo_t*)arg;

	int insert = gp_sdcard_ckinsert(sd);
	/* ----- Card status change ----- */
	if( (sd->present ^ insert)||(sd->fremove))
	{
		if((insert==0)||(sd->fremove))
		{
			sd->cnt = 0;
			DEBUG("[%d]:Card Remove\n",sd->device_id);
			sd->sd_func->set_power(0);
			schedule_work(&sd->uninit);
		}
		else
		{
			sd->cnt ++;
			if(sd->cnt>=SD_DEBOUNCE)
			{
				sd->present = 0;
				sd->cnt = 0;
				DEBUG("[%d]:Card insert\n",sd->device_id);
				sd->sd_func->set_power(0); /* chris: enable power in identify, need to set power at first */
				schedule_work(&sd->init);
			}
			else
			{
				sd->timer.expires = jiffies + HZ/100;		/* 10ms */
				add_timer(&sd->timer);
			}
		}
	}
	/* ----- Card status not change ----- */
	else
	{
		sd->timer.expires = jiffies + SD_CD_POLL;
		add_timer(&sd->timer);
		sd->cnt = 0;
	}
}
Beispiel #8
0
/**
* @brief 	SD resume function.
* @param 	pdev[in]: Platform device pointer.
* @param 	state[in]: Suspend event.
* @return 	SUCCESS/ERROR_ID.
*/
static int gp_sd_resume(struct platform_device *pdev)
{
	int i;
	DEBUG("SD resume\n");
	for(i = 0; i < SD_NUM; i++)
	{
		gpSDInfo_t *sd = &sd_info[i];
		/* enable sd clock */
		if( (sd->present==1) && (gp_sdcard_ckinsert(sd)==1) )
		{
			if(gp_sdcard_inner_card(sd))
			{
				int pin_handle;
				int pin_id;

				if(sd->device_id == 0)
					pin_id = GP_PIN_SD0;
				else if(sd->device_id == 1)
					pin_id = GP_PIN_SD1;
				else
					pin_id = GP_PIN_SD2;

				pin_handle = gp_board_pin_func_request( pin_id, GP_BOARD_WAIT_FOREVER);
				if(pin_handle<0)
				{
					DERROR("[%d]: can't get pin handle\n", sd->device_id);
					return -1;
				}
				gp_sdcard_cardinit(sd);
				gp_board_pin_func_release(pin_handle);

			}
			else
				sd->fremove = 1;
		}
	}
	return 0;
}
Beispiel #9
0
/**
* @brief 	Request service function.
* @param 	sd[in]: Card information.
* @param 	req[in]: Start sector.
* @return 	SUCCESS/ERROR_ID.
*/
static int gp_sdcard_xfer_request(gpSDInfo_t *sd, struct request *req)
{
	int ret = 1;

	while (ret)
	{
		unsigned int ln;
		unsigned int retry = 0;

		ln = blk_rq_map_sg(sd->queue, req, sd->sg);

#if 0	/* This is used for usb disk check */
		{
			bool do_sync = (rq_is_sync(req) && rq_data_dir(req) == WRITE);
			if (do_sync)
			{
				DEBUG("[Jerry] detect do write sync\n");
			}
		}
#endif
		while(1)
		{
			ret = gp_sdcard_transfer_scatter(sd, blk_rq_pos(req), sd->sg, ln, rq_data_dir(req));
			/* ----- Re-try procedure ----- */
			if(ret<0)
			{
				unsigned int cid[4];
				unsigned int capacity;
				if((retry>=SD_RETRY)||(gp_sdcard_ckinsert(sd)==0)||sd->fremove)
					goto out_error;
				/* ----- Re-initialize sd card ----- */
				memcpy(cid, sd->CID, sizeof(cid));
				capacity = sd->capacity;
				if(gp_sdcard_cardinit(sd)!=0)
				{
					DERROR("[%d]: Re-initialize fail\n",sd->device_id);
					goto out_error;
				}
				else if((cid[0]!=sd->CID[0])||(cid[1]!=sd->CID[1])||(cid[2]!=sd->CID[2])||(cid[3]!=sd->CID[3])||(capacity!=sd->capacity))
				{
					DERROR("[%d]: Different card insert\n",sd->device_id);
					goto out_error;
				}
				retry ++;
			}
			else
				break;
		}
		/* ----- End of request ----- */
		spin_lock_irq(&sd->lock);
		ret = __blk_end_request(req, 0, ret<<9);
		spin_unlock_irq(&sd->lock);
	}
	return 1;
out_error:
	spin_lock_irq(&sd->lock);
	DEBUG("[%d]: txrx fail %d\n", sd->device_id, ret);
	__blk_end_request_all(req, ret);;
	spin_unlock_irq(&sd->lock);
	return -ENXIO;
}