/**
* @brief 	SD driver exit function.
* @return 	None.
*/
static void __exit gp_sdcard_exit(void)
{
	int i;
	/* ----- Free all alloc memory ----- */
	for (i = 0; i < SD_NUM; i++) 
	{
		gpSDInfo_t *sd = sd_info + i;
		/* ----- Free gendisk structure ----- */
		if (sd->gd) 
		{
			del_gendisk(sd->gd);
			/* ----- Free request ----- */
			if (sd->queue) 
			{
				blk_cleanup_queue(sd->queue);
			}
			/* ----- Then terminate our worker thread -----*/
			kthread_stop(sd->thread);
			if (sd->sg)
				kfree(sd->sg);
			sd->sg = NULL;
			put_disk(sd->gd);
		}
		/* ----- free dma channel ----- */
		if(sd->handle_dma)
			gp_apbdma0_release(sd->handle_dma);
	}
	unregister_blkdev(sd_major, "sdcard");
	gp_sdio_exit();
	kfree(sd_info);
}
/**
* @brief 	Card un-initial function.
* @param 	work[in]: Work structure.
* @return 	None.
*/ 
static void gp_sdcard_work_uninit(struct work_struct *work)
{
	gpSDInfo_t* sd = container_of(work, gpSDInfo_t,uninit);
	
	if(sd->card_type == SDIO)
	{
		gp_sdio_remove_device();
		gp_board_pin_func_release(sd->pin_handle);
	}
	else
	{
		/* ----- Stop new requests from getting into the queue ----- */
		del_gendisk(sd->gd);
		/* ----- Then terminate our worker thread ----- */
		kthread_stop(sd->thread);
		if (sd->sg)
			kfree(sd->sg);
		sd->sg = NULL;
		blk_cleanup_queue (sd->queue);
		put_disk(sd->gd);
		/* ----- free dma channel ----- */
		if(sd->handle_dma)
			gp_apbdma0_release(sd->handle_dma);
		sd->handle_dma = 0;
	}
	/* ----- Uninitial SD controller ----- */
	gpHalSDUninit(sd->device_id);
	sd->users = 0;
	sd->timer.expires = jiffies + SD_CD_POLL;
	add_timer(&sd->timer);
}
Beispiel #3
0
/**
* @brief 	SD module clean up function.
* @param 	sd[in]: Card information.
* @return 	None.
*/
static void gp_sdcard_cleanup(gpSDInfo_t* sd)
{
	/* ----- Stop new requests from getting into the queue ----- */
	if(sd->gd)
		del_gendisk(sd->gd);
	/* ----- Then terminate our worker thread ----- */
	if(sd->thread)
	{
		kthread_stop(sd->thread);
		sd->thread = NULL;
	}

	/* ----- Empty the queue ----- */
	if(sd->queue)
	{
		unsigned long flags;
		spin_lock_irqsave(&sd->lock, flags);
		sd->queue->queuedata = NULL;
		blk_start_queue(sd->queue);
		spin_unlock_irqrestore(&sd->lock, flags);
	}

	if (sd->sg)
		kfree(sd->sg);
	sd->sg = NULL;
	/* ----- free dma channel ----- */
	if(sd->handle_dma)
		gp_apbdma0_release(sd->handle_dma);
	sd->handle_dma = 0;
}
/**
* @brief 	SD card release.
* @param 	dev[in]: Block device pointer.
* @param 	mode[in]: Mode.
* @return 	SUCCESS/ERROR_ID.
*/
static int gp_sdcard_release(struct gendisk *gd, fmode_t mode)
{
	gpSDInfo_t *sd = gd->private_data;
	sd->users--;
	if(sd->users==0)
	{
		gp_apbdma0_release(sd->handle_dma);
		sd->handle_dma = 0;
	}
	return 0;
}
Beispiel #5
0
/**
* @brief 	Card initial function.
* @param 	work[in]: Work structure.
* @return 	None.
*/
static void gp_sdcard_work_init(struct work_struct *work)
{
	gpSDInfo_t* sd = container_of(work, gpSDInfo_t,init);
	int pin_handle;
	int ret = 0,i=0;
	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);
		goto init_work_end;
	}
    /* ----- chris: Set Pin state for SD before power on ----- */
    sd->sd_func->set_power(1);
	/* ----- chris: delay 250ms after card power on ----- */
	msleep(250);
	/* ----- Initial SD card ----- */
	ret = gp_sdcard_cardinit(sd);
	if (ret != 0)
	{
		DERROR("[%d]: initial fail\n",sd->device_id);
		gp_board_pin_func_release(pin_handle);
		goto init_work_end;
	}
	gp_board_pin_func_release(pin_handle);

	if(sd->present==1)
	{
		if(sd->card_type == SDIO)
		{
			sd->pin_handle = gp_board_pin_func_request(pin_id, GP_BOARD_WAIT_FOREVER);
			if(sd->pin_handle<0)
			{
				DERROR("[%d]: can't get pin handle\n", sd->device_id);
				goto init_work_end;
			}
			DEBUG("SDIO card detected\n");
			gp_sdio_insert_device(sd->device_id, sd->RCA);
		}
		else
		{
			unsigned int cnt =0;
			/* ----- Wait 30 second for all process close handle ----- */
			while((sd->users)&&cnt<120)
			{
				msleep(250);
				cnt++;
			}
			if(sd->users)
			{
				DERROR("Some handle do not free\n");
			}
			if(sd->status)
			{
				gp_sdcard_blk_put(sd);
				sd->status = 0;
			}
			sd->handle_dma = gp_apbdma0_request(1000);
			if(sd->handle_dma==0)
				goto init_work_end;
			sd->queue = blk_init_queue(gp_sdcard_request, &sd->lock);
			if(sd->queue==NULL)
			{
				DERROR("NO MEMORY: queue\n");
				goto fail_queue;
			}
			blk_queue_ordered(sd->queue, QUEUE_ORDERED_DRAIN, NULL);
			queue_flag_set_unlocked(QUEUE_FLAG_NONROT, sd->queue);
			blk_queue_logical_block_size(sd->queue, 512);
			blk_queue_max_sectors(sd->queue, SD_MAX_SECTORS );
			blk_queue_max_phys_segments(sd->queue, SD_MAX_PHY_SEGMENTS);
			blk_queue_max_hw_segments(sd->queue, SD_MAX_HW_SEGMENTS);
			blk_queue_max_segment_size(sd->queue, SD_MAX_PHY_SEGMENTS_SIZE);
			/* ----- Initial scatter list ----- */
			sd->sg = kmalloc(sizeof(struct scatterlist) *SD_MAX_PHY_SEGMENTS, GFP_KERNEL);
			if (!sd->sg)
			{
				DERROR("NO MEMORY: queue\n");
				goto fail_thread;
			}
			sg_init_table(sd->sg, SD_MAX_PHY_SEGMENTS);
			init_MUTEX(&sd->thread_sem);
			/* ----- Enable thread ----- */
			sd->thread = kthread_run(gp_sdcard_queue_thread, sd, "sd-qd");
			if (IS_ERR(sd->thread))
			{
				goto fail_thread;
			}
			sd->queue->queuedata = sd;
			/* ----- Check SD card for GP special header ----- */
			if(gp_sdcard_parse_header(sd)<0)
			{
				goto fail_gd;
			}
			/* ----- Setup gendisk structure ----- */
			sd->gd = alloc_disk(SD_MINORS);
			if (sd->gd==NULL)
			{
				DERROR("NO MEMORY: gendisk\n");
				blk_cleanup_queue(sd->queue);
				goto fail_gd;
			}
			/* ----- Set gendisk structure ----- */
			sd->gd->major = sd_major;
			sd->gd->first_minor = sd->device_id*SD_MINORS;
			sd->gd->fops = &gp_sdcard_ops;
			sd->gd->queue = sd->queue;
			sd->gd->private_data = sd;
			snprintf (sd->gd->disk_name, 32, "sdcard%c", sd->device_id + 'a');
			/* ----- Set GP partition ----- */
			if(sd->partition.activity)
			{
				set_capacity(sd->gd,0);
				add_disk(sd->gd);
				for(i=0;i<MAX_SD_PART;i++)
				{
					if(sd->partition.capacity[i]==0)
						continue;
					gp_add_partition(sd->gd,i+1,sd->partition.offset[i],sd->partition.capacity[i],ADDPART_FLAG_WHOLEDISK);
				}
			}
			/* ----- Normal Setting ----- */
			else
			{
				set_capacity(sd->gd,sd->capacity);
				add_disk(sd->gd);
			}
		}
		//DEBUG("Initial success\n");
		goto init_work_end;
	}
	else
	{
		DERROR("Initial fail\n");
		goto init_work_end;
	}
fail_gd:
	/* ----- Then terminate our worker thread ----- */
	kthread_stop(sd->thread);
	sd->thread = NULL;
fail_thread:
	if (sd->sg)
		kfree(sd->sg);
	sd->sg = NULL;
	blk_cleanup_queue (sd->queue);
	sd->queue = NULL;
fail_queue:
	if(sd->handle_dma)
		gp_apbdma0_release(sd->handle_dma);
	sd->handle_dma = 0;
	/* ----- For re-initialize ----- */
	sd->present = 0;
init_work_end:
	sd->timer.expires = jiffies + SD_CD_POLL;
	add_timer(&sd->timer);
}