⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftsdc010.c

📁 SD卡驱动程序,是基于GM8180的体系的完整代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	cid->ManufactureYear = ((cid_word[0] & 0x0000F000) >> 12) + SD_DEFAULT_YEAR_CODE;	return TRUE;}uint sd_read_timeout_cycle(uint clock, sd_csd_t *csd){#if 1 //ivan for 100ms maximux from document "ProdManualIndGradeSDv1.0[1].pdf" chapter A-2	return clock/10; // /10;#else	uint ret, total, per;	per = 1000000000 / clock;	total = (csd->TAAC_u + (csd->NSAC_u * 100 * per)) * 100;	if (total > (100 * 1000 * 1000))		total = 100 * 1000 * 1000;	ret = total / per;	return ret;#endif}uint sd_block_size_convert(uint size){	uint ret = 0;	while (size >= 2) {		size >>= 1;		ret++;	}	return ret;}int sd_select_card(sd_card_t *info){	uint status;	/* send CMD7 with valid RCA to select */	if (!sdc_send_cmd(SD_SELECT_CARD_CMD | SDC_CMD_REG_NEED_RSP, ((uint)info->RCA) << 16, &status))		return FALSE;	if (!sd_check_err(status))		return FALSE;	return TRUE;}int sd_set_transfer_state(sd_card_t *info){	uint state;	int count = 0;	while (count++ < SD_CARD_STATE_CHANGE_RETRY_COUNT) {		if (!sd_get_card_state(info, &state))			return FALSE;		switch (state) {		case SD_IDLE_STATE:		case SD_READY_STATE:		case SD_IDENT_STATE:			printk("%s() error\n", __func__);			return FALSE;		case SD_DIS_STATE:			if (!sd_operation_complete(info, SD_STBY_STATE))				return FALSE;			break;		case SD_TRAN_STATE:			return TRUE;		case SD_DATA_STATE:			if (sd_operation_complete(info, SD_TRAN_STATE))				return TRUE;			if (sd_err_code != ERR_NO_ERROR)				return FALSE;			if (!sd_stop_transmission())				return FALSE;			break;		case SD_RCV_STATE:			if (sd_operation_complete(info, SD_TRAN_STATE))				return TRUE;			if (sd_err_code != ERR_NO_ERROR)				return FALSE;			if (!sd_stop_transmission())				return FALSE;			break;		case SD_PRG_STATE:			if (!sd_operation_complete(info, SD_TRAN_STATE))				return FALSE;			break;		case SD_STBY_STATE:			if (!sd_select_card(info))				return FALSE;		}	}	P_DEBUG("%s() error\n", __func__);	return FALSE;}uint sd_write_timeout_cycle(uint clock, sd_csd_t *CSD){#if 1 //ivan for 250ms maximux from document	return clock/4;	//ijsung hack#else	uint ret, total, pre;	pre = 1000000000 / clock;	total = CSD->WriteSpeedFactor * 100 * (CSD->TAAC_u + (CSD->NSAC_u * 100 * pre));	if (total > (100 * 1000 * 1000))		total = 100 * 1000 * 1000;	ret = total / pre;	return ret;#endif}//CMD8//CMD8 should be added in the identification state, just after reset commandstatic int SD_SendInterfaceConditionCmd(uint arg){    uint Response;    if(!sdc_send_cmd(SD_SEND_IF_COND_CMD | SDC_CMD_REG_NEED_RSP, arg, &Response)){	printk("CMD8: Card does not support SPEC 2.0 or voltage is not supported!\n");	printk("If your card is not support SPEC 2.0, don't care this command error message!\n");	return FALSE;    }    if( Response != arg )	return FALSE;        return TRUE;}int sd_card_identify(sd_card_t *info){	uint rca, status, cid[4];	/* reset all cards */	if (!sdc_send_cmd(SD_GO_IDLE_STATE_CMD, 0, NULL))		return FALSE;	udelay(1000);	//for SD 2.0, execute CMD8 first to determine the voltage supported by the card	SD_SendInterfaceConditionCmd((0x1 << 8)|( 0xAA << 0) );	/* Do operating voltage range validation */	/* get OCR register */	if (!sd_get_ocr(info, SDC_OCR, (uint *) &info->OCR))		return FALSE;	/* ckeck the operation conditions */	if ((info->OCR & SDC_OCR) == 0) {		sd_err_code = ERR_OUT_OF_VOLF_RANGE;		return FALSE;	}	/* send CMD2 to get CID register */	if (!sdc_send_cmd(SD_ALL_SEND_CID_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, 0, cid))		return FALSE;	if (info->CardType == MEMORY_CARD_TYPE_SD) {		/* send CMD3 to get RCA register */		if (!sdc_send_cmd(SD_SEND_RELATIVE_ADDR_CMD | SDC_CMD_REG_NEED_RSP, 0, &rca))			return FALSE;		info->RCA = (ushort) (rca >> 16);	} else {		/* so far, we only support one interface, so we can give RCA any value */		info->RCA = 0x1;		/* send CMD3 to set RCA register */		if (!sdc_send_cmd(SD_SEND_RELATIVE_ADDR_CMD | SDC_CMD_REG_NEED_RSP, (info->RCA << 16), &status))			return FALSE;		if (!sd_check_err(status))			return FALSE;	}	return TRUE;}int sd_card_init(sd_card_t *info){	uint clock;	P_DEBUG("--> %s\n", __func__);	if ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_INSERT) != SDC_CARD_INSERT)		return FALSE;	sd_err_code = ERR_NO_ERROR;	/* At first, set card type to SD */	info->CardType = MEMORY_CARD_TYPE_SD;	/* set memory card type */	sdc_set_card_type(info->CardType);	/* start card idenfication process */	if (!sd_card_identify(info)) {		printk("this is not SD card\n");		sd_err_code = ERR_NO_ERROR;		info->CardType = MEMORY_CARD_TYPE_MMC;		/* set memory card type */		sdc_set_card_type(info->CardType);		if (!sd_card_identify(info))			return FALSE;	}	/* get CSD */	if (!sd_set_card_standby(info))		return FALSE;	/* send CMD9 to get CSD register */	if (!sdc_send_cmd(SD_SEND_CSD_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, ((uint) info->RCA) << 16, info->CSDWord))		return FALSE;	sd_csd_parse(&info->CSD, info->CSDWord);#if 0	if (info->CSD.ReadBlockLength != SD_SECTOR_SIZE) {		printk("Sector size is mis-matched (SD CSD report=0x%X,SD_SECTOR_SIZE=0x%X)\n", info->CSD.ReadBlockLength, SD_SECTOR_SIZE);		return FALSE;	}#else	if (info->CSD.ReadBlockLength != SD_SECTOR_SIZE) {		//printk("Sector size is mis-matched (SD CSD report=0x%X,SD_SECTOR_SIZE=0x%X)\n", info->CSD.ReadBlockLength, SD_SECTOR_SIZE);		printk("Sector size (SD CSD report=0x%X)\n", info->CSD.ReadBlockLength);		info->CSD.ReadBlockLength = SD_SECTOR_SIZE;	}#endif	/* get CID */	/* send CMD10 to get CID register */	if (!sdc_send_cmd(SD_SEND_CID_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, ((uint) info->RCA) << 16, info->CIDWord))		return FALSE;	sd_cid_parse(&info->CID, info->CIDWord);	/* Set card bus clock. sdc_set_bus_clock() will give the real card bus clock has been set. */	clock = sdc_set_bus_clock(info, info->CSD.TransferSpeed);	info->ReadAccessTimoutCycle = sd_read_timeout_cycle(clock, &(info->CSD));	info->WriteAccessTimoutCycle = sd_write_timeout_cycle(clock, &(info->CSD));	/* set bus width */	if (!sdc_set_bus_width(info))		return FALSE;	/* check write protect */	info->WriteProtect = ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_LOCK) == SDC_STATUS_REG_CARD_LOCK) ? TRUE : FALSE;	if(info->WriteProtect == TRUE)		printk("SD/MMC Card is Write Protected\n");	info->ActiveState = TRUE;	P_DEBUG("<-- %s\n", __func__);	return TRUE;}int sd_card_insert(sd_card_t *info){	P_DEBUG("--> %s\n", __func__);	/* reset host interface controller */	sdc_reset();	/* turn on clock using default clock*/	SDC_W_REG(SDC_CLOCK_CTRL_REG, SDC_R_REG(SDC_CLOCK_CTRL_REG)&0xff);	if (!sd_card_init(info)) {		printk("root initialize failed\n");		return FALSE;	}	/* set interrupt mask register */	SDC_W_REG(SDC_INT_MASK_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);	P_DEBUG("<-- %s\n", __func__);	return TRUE;}/* Free IRQ and DMA resources */void sd_free(sd_dev_t *dev){	//john	release_region(FTSDC_VA_BASE, 0x48); /* return ioport */	if(SD_MODE != AUTO_DETECT)		free_irq(FTSDC_IRQ, dev); /* return Hotswapping irq */#ifdef CONFIG_FTSDC010_USE_APBDMA //CONFIG_FTSDC010_USE_APBDMA	fa_free_apb_dma(SD_DMA_CHANNEL);	sd_card_info.DMAEnable = FALSE;#endif#ifdef CONFIG_FTSDC010_USE_AHBDMA	fa_free_ahb_dma(SD_DMA_CHANNEL);	sd_card_info.DMAEnable = FALSE;#endif}int sd_card_remove(sd_card_t *info){	sd_err_code = ERR_NO_ERROR;	info->ActiveState = FALSE;	info->WriteProtect = FALSE;	info->RCA = 0;	/* reset host interface controller */	sdc_reset();	/* set interrupt mask register */	SDC_W_REG(SDC_INT_MASK_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);	sd_err_code = ERR_CARD_NOT_EXIST;	/* turn off clock */	SDC_W_REG(SDC_CLOCK_CTRL_REG, SDC_R_REG(SDC_CLOCK_CTRL_REG) | 0x100);	return TRUE;}irqreturn_t sd_hotswap_interrupt_handler(int irq, void *dev_id, struct pt_regs *dummy){	uint status;	sd_dev_t *dev = dev_id;	P_DEBUG("--> %s, irq=%d\n", __func__, irq);	/* When the card is inserted or removed, we must delay a short time to make sure */	/* the SDC_STATUS_REG_CARD_INSERT bit of status register is stable */	udelay(1000);	status = SDC_R_REG(SDC_STATUS_REG);	if ((status & SDC_STATUS_REG_CARD_CHANGE) == SDC_STATUS_REG_CARD_CHANGE) {		SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);		if ((status & SDC_STATUS_REG_CARD_INSERT) == SDC_CARD_INSERT) {			printk("Card Insert\n");			error_flag = 0;						if(SD_MODE != AUTO_DETECT)				{						dev->card_state = SD_CARD_INSERT;							sd_card_insert(&sd_card_info);			}else				sys_kill(mpid,SIGUSR1);								} else {						printk("Card Remove\n");			if(SD_MODE != AUTO_DETECT)				{					dev->card_state = SD_CARD_REMOVE;				sd_card_remove(&sd_card_info);			}else				sys_kill(mpid,SIGUSR2);									/* remove all current transfers as I/O error*/#if 0 //def CONFIG_FTSDC010_USE_APBDMA //ASYNC			spin_lock_irqsave(&io_request_lock, status);			INIT_REQUEST;			while(!QUEUE_EMPTY)				end_request(0);			bh_busy=0;			spin_unlock_irqrestore(&io_request_lock, status);#endif			}	} else if ((status & SDC_STATUS_REG_DATA_TIMEOUT) == SDC_STATUS_REG_DATA_TIMEOUT) {		SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);		#if 0 //def CONFIG_FTSDC010_USE_APBDMA //ASYNC		printk("Data timeout. Retry.\n");		sd_clustered_bh(2);#else	printk("Data timeout. Retry.\n");#endif	}	//P_DEBUGG("card state=%d\n", dev->card_state);	P_DEBUG("<-- %s\n", __func__);	return IRQ_HANDLED;}#if 0 //def CONFIG_FTSDC010_USE_APBDMA//#define A320_SD_USE_ASYNC_DMAstatic inline int wait_completion(int doWait, int doSet){	int retry=0;	if(doWait) {		/* make sure SDC has completed its job */wait_again:		if (!sd_wait_transfer_state(&sd_card_info)) {				if(retry++ < 10) {				goto wait_again;			}else {				printk("%s: wait transfer state failed.\n",__func__);				return 0;			}		}		retry=0;	}	if(doSet) {set_again:		if(!sd_set_transfer_state(&sd_card_info)) {			if(retry++ < 10) {				goto set_again;			}else {				printk("%s: set transfer state failed.\n",__func__);				return 0;			}		}	}	return 1;}/* erase */static int sd_erase(uint sector, uint sector_nr){	uint status;	printk("%s: erase %d sectors from %d\n",__func__,sector_nr, sector);	if(!sdc_send_cmd(SD_ERASE_SECTOR_START_CMD | SDC_CMD_REG_NEED_RSP, sector*SD_SECTOR_SIZE, &status)) {		printk("%s: SD_ERASE_SECTOR_START_CMD error\n", __func__);		return -1;	}	if(!sdc_send_cmd(SD_ERASE_SECTOR_END_CMD | SDC_CMD_REG_NEED_RSP, (sector+sector_nr)*SD_SECTOR_SIZE, &status)) {		printk("%s: SD_ERASE_SECTOR_END_CMD error\n", __func__);		return -2;	}	if(!sdc_send_cmd(SD_ERASE_CMD | SDC_CMD_REG_NEED_RSP, 0, &status)) {		printk("%s: SD_ERASE_CMD error\n", __func__);		return -3;	}	if(!wait_completion(1, 1)) {		printk("%s: wait_completion failed\n",__func__);		return -4;	}	printk("%s: erase complete\n",__func__);	return 0;}static int sdc_config_multi_transfer(int isWrite, uint sector, uint sector_nr){	static int last_operation=READ;	static sd_card_t * info = &sd_card_info;	uint status, retry=0;	sector+=sector_offset;again:	//If last operation is write, wait for its completion	if(!wait_completion(1 /*last_operation*/, 1))		printk("%s: wait_completion failed\n",__func__);	last_operation=isWrite;	if (!sdc_set_block_size(SD_SECTOR_SIZE))		return FALSE;#if 0	/* Check DMA cycles */	status=*(volatile unsigned *)(priv->channel_base+APBDMA_DMA_CYCLE_0x8);	if(status) {		printk("%s: ERROR: Unfinished DMA!!(%d left)\n",__func__, status);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -