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

📄 ftsdc010.c

📁 SD卡驱动程序,是基于GM8180的体系的完整代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		parm.size = size >> 4;		parm.burst = TRUE;		parm.irq = APBDMA_TRIGGER_IRQ_WITH_ERROR;		fa_set_apb_dma_params(SD_DMA_CHANNEL, &parm);		if (dma_buf)			consistent_sync(__va(dma_buf), size, DMA_TO_DEVICE);		else			consistent_sync(buf, size, DMA_TO_DEVICE);		#ifndef CONFIG_FTSDC010_USE_APBDMA_POLL		/* Set up time out timer */		init_timer(&to_timer);		to_timer.expires = timeout;		to_timer.function = sdc_apbdma_timeout_handler;		to_timer.data = (unsigned long) info;		add_timer(&to_timer);		/* Start DMA */		fa_apb_dma_start(SD_DMA_CHANNEL);		interruptible_sleep_on(&sd_dma_queue);		//wait_event_interruptible_timeout(sd_dma_queue, !fa_apb_dma_get_cycle(SD_DMA_CHANNEL), SDC_TIMEOUT_BASE*((size+511)>>9));		//wait_event_interruptible_timeout(sd_dma_queue,fa_apb_dma_get_status(SD_DMA_CHANNEL) != INT_DMA_TRIGGER, SDC_TIMEOUT_BASE*((size+511)>>9));		/* clean up the timeout timer */		del_timer_sync(&to_timer);		#else		/* Start DMA */		fa_apb_dma_start(SD_DMA_CHANNEL);		while( (i=fa_apb_dma_get_status(SD_DMA_CHANNEL)) == 0 ) {			if ( time_after(jiffies, timeout) ) {				sd_time_out=1;				break;			}		}		if ( sd_time_out == 1 ) {			P_DEBUG("SD_Rx: APB DMA Tx Time-out\n");			sd_err_code = ERR_DATA_TIMEOUT_ERROR;		}		else if ( i&INT_DMA_ERROR ) {			P_DEBUG(KERN_ERR "SD_Tx: APB DMA Error\n");			sd_err_code = ERR_APBDMA_RSP_ERROR;		}		else if ( i&INT_DMA_TRIGGER ) {			P_DEBUG("SD_Tx: APB DMA Finish\n");		}		#endif		if ( sd_err_code == ERR_DATA_TIMEOUT_ERROR ) {			printk("SD_Tx: APB DMA Tx Time-out\n");			//printk("dest=%x,size=%x\n",buf,size);		}				/* Stop DMA */		fa_apb_dma_stop(SD_DMA_CHANNEL);		fa_apb_dma_reset(SD_DMA_CHANNEL);		P_DEBUG("DMA Read sleep_on()\n");	}	else#endif /* #ifdef CONFIG_FTSDC010_USE_APBDMA */#ifdef CONFIG_FTSDC010_USE_AHBDMA	if (info->DMAEnable) {		P_DEBUG("%s:size=%d, buf=%p) - DMA Write\n", __func__, size,buf );		if (dma_buf)			parm.src = dma_buf;		else			parm.src = __pa(buf);				fa_set_ahb_dma_src_params(SD_DMA_CHANNEL, parm.src, AHBDMA_MASTER_0, 2, 0);		fa_set_ahb_dma_dst_params(SD_DMA_CHANNEL, FTSDC_PA_BASE + SDC_DATA_WINDOW_REG, AHBDMA_MASTER_0, 2, 2);		fa_set_ahb_dma_transfer_bs(SD_DMA_CHANNEL, 1); //set burst		fa_set_ahb_dma_transfer_params2(SD_DMA_CHANNEL, AHBDMA_MASTER_0, size, 1);				fa_ahb_dma_init(SD_DMA_CHANNEL, 7);		fa_ahb_dma_add_auto(SD_DMA_CHANNEL, size);		if (dma_buf)			consistent_sync(__va(dma_buf), size, DMA_TO_DEVICE);		else			consistent_sync(buf, size, DMA_TO_DEVICE);		/* Set up time out timer */		init_timer(&to_timer);		to_timer.expires = timeout;		to_timer.function = sdc_ahbdma_timeout_handler;		to_timer.data = (unsigned long) info;		add_timer(&to_timer);		/* Start DMA */		fa_ahb_dma_start(SD_DMA_CHANNEL);		//interruptible_sleep_on(&sd_dma_queue);		wait_event_interruptible_timeout(sd_dma_queue, fa_ahb_dma_all_done(SD_DMA_CHANNEL), SDC_TIMEOUT_BASE*((size+511)>>9));		/* clean up the timeout timer */		del_timer_sync(&to_timer);		/* Stop DMA */		fa_ahb_dma_stop(SD_DMA_CHANNEL);		fa_ahb_dma_reset(SD_DMA_CHANNEL);		P_DEBUG("DMA Read sleep_on()\n");	}	else#endif	{		while (size > 0) {			if (!sdc_check_tx_ready())				return FALSE;			/* write data from FIFO */			if (size >= (SDC_WRITE_FIFO_LEN << 2))				count = SDC_WRITE_FIFO_LEN;			else				count = (size >> 2) ;			/* write data from FIFO */			for (i = 0; i < count; i++, buf++)				SDC_W_REG(SDC_DATA_WINDOW_REG, *buf);			size -= (count << 2);		}	}	return sdc_check_data_crc();}void sdc_config_transfer(sd_card_t *SDCard, uint len, uint size, uint rw, uint timeout){	/* write timeout */	SDC_W_REG(SDC_DATA_TIMER_REG, timeout * 2);	/* set data length */	SDC_W_REG(SDC_DATA_LEN_REG, len);	/* set data block */	if (SDCard->DMAEnable) {		P_DEBUG("%s() transfer DMA mode\n", __func__);		SDC_W_REG(SDC_DATA_CTRL_REG, sd_block_size_convert(size) | SDC_DATA_CTRL_REG_DMA_EN | rw | SDC_DATA_CTRL_REG_DATA_EN);	} else {		P_DEBUG("%s() transfer nonDMA mode\n", __func__);		SDC_W_REG(SDC_DATA_CTRL_REG, sd_block_size_convert(size) | rw | SDC_DATA_CTRL_REG_DATA_EN);	}}/* Note: This funciton may be called by interrupt handler */void sdc_reset(void){	uint ret;	unsigned long delay = jiffies + (HZ/10)*3;	//Delay 300ms	/* reset host interface */	SDC_W_REG(SDC_CMD_REG, SDC_CMD_REG_SDC_RST);	/* loop, until the reset bit is clear */	do {		ret = SDC_R_REG(SDC_CMD_REG);	} while ((ret & SDC_CMD_REG_SDC_RST) != 0);	#if 0	udelay(1000);	#else	while(time_before(jiffies, delay));	#endif}/* * SD card operation */void sd_endian_change(uint *dt, int len){	uint ul;	for(; len > 0; len--, dt++)	{		ul = *dt;		((unchar *)dt)[0] = ((unchar *)&ul)[3];		((unchar *)dt)[1] = ((unchar *)&ul)[2];		((unchar *)dt)[2] = ((unchar *)&ul)[1];		((unchar *)dt)[3] = ((unchar *)&ul)[0];	}}int sd_get_ocr(sd_card_t *info, uint hocr, uint *cocr){	uint status;	int count = 0;	do {		if (info->CardType == MEMORY_CARD_TYPE_SD) {			/* send CMD55 to indicate to the card that the next command is an application specific command */			if (!sdc_send_cmd(SD_APP_CMD | SDC_CMD_REG_NEED_RSP, ((uint) info->RCA) << 16, &status))				return FALSE;			if (!sd_check_err(status))				return FALSE;				/* send ACMD41 to get OCR register */			if (!sdc_send_cmd(SD_APP_OP_COND | SDC_CMD_REG_APP_CMD | SDC_CMD_REG_NEED_RSP, (uint) hocr, (uint *) cocr))				return FALSE;		} else {			/* send CMD1 to get OCR register */			if (!sdc_send_cmd(SD_MMC_OP_COND | SDC_CMD_REG_NEED_RSP, (uint) hocr, (uint *) cocr))				return FALSE;		}		if (count++ > SD_CARD_GET_OCR_RETRY_COUNT) {			sd_err_code = ERR_SD_CARD_IS_BUSY;			printk("%s : ERR_SD_CARD_IS_BUSY\n", __func__);			return FALSE;		}		udelay(1000);	/* According to spec, at most 1 msec or 74 clock cycles */	} while ((*cocr & SD_OCR_BUSY_BIT) != SD_OCR_BUSY_BIT);	return TRUE;}int sd_get_scr(sd_card_t *info, uint *scr){	uint status;	if (!sd_set_transfer_state(info))		return FALSE;	if (!sdc_set_block_size(8))		return FALSE;	sdc_config_transfer(info, 8, 8, SDC_DATA_CTRL_REG_DATA_READ, 0xFFFFFFFF);	/* send CMD55 to indicate to the card that the next command is an application specific command */	if (!sdc_send_cmd(SD_APP_CMD | SDC_CMD_REG_NEED_RSP, ((uint) info->RCA) << 16, &status))		return FALSE;	if (!sd_check_err(status))		return FALSE;	/* send ACMD51 to get SCR */	if (!sdc_send_cmd(SD_SEND_SCR_CMD | SDC_CMD_REG_APP_CMD | SDC_CMD_REG_NEED_RSP, 0, &status))		return FALSE;	if (!sd_check_err(status))		return FALSE;	if (!sdc_read_block(info, 8, (uint *) scr))		return FALSE;	if (!sdc_check_data_end())		return FALSE;	sd_endian_change(scr, 2);	return TRUE;}int sd_check_err(uint status){	if (status & SD_STATUS_ERROR_BITS) {		sd_err_code = ERR_SD_CARD_STATUS_ERROR;		printk("%s() ERR_SD_CARD_STATUS_ERROR %X\n", __func__, status);		return FALSE;	}	sd_err_code = ERR_NO_ERROR;	return TRUE;}int sd_get_card_state(sd_card_t *info, uint *ret){	uint status;	/* send CMD13 to get card status */	if (!sdc_send_cmd(SD_SEND_STATUS_CMD | SDC_CMD_REG_NEED_RSP, ((uint) info->RCA) << 16, &status))		return FALSE;	if (!sd_check_err(status))		return FALSE;	*ret = (status & SD_STATUS_CURRENT_STATE) >> SD_STATUS_CURRENT_STATE_LOC;	return TRUE;}int sd_operation_complete(sd_card_t *info, uint finish){	uint state;	int count = 0;	while (count++ < SD_CARD_WAIT_OPERATION_COMPLETE_RETRY_COUNT) {		if (!sd_get_card_state(info, &state))			return FALSE;		if (state == finish)			return TRUE;	}	P_DEBUG("%s() error\n", __func__);	return FALSE;}int sd_stop_transmission(void){	uint status;	/* send CMD12 to stop transmission */	if (!sdc_send_cmd(SD_STOP_TRANSMISSION_CMD | SDC_CMD_REG_NEED_RSP, 0, &status))		return FALSE;	if (!sd_check_err(status))		return FALSE;	return TRUE;}int sd_set_card_standby(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:			return sd_operation_complete(info, SD_STBY_STATE);		case SD_TRAN_STATE:			if (!sdc_send_cmd(SD_SELECT_CARD_CMD, 0, NULL))				return FALSE;			break;		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:			return TRUE;		}	}	P_DEBUG("%s() error\n", __func__);	return FALSE;}uint two_power(uint n){	uint pow = 1;	for (; n > 0; n--)		pow <<= 1;	return pow;}int sd_csd_parse(sd_csd_t *csd, uint *csd_word){	sd_csd_bit_t *csd_bit;	SD_CSD_BIT_Struct_V2 *CSDPtr2;	uint mult, blocks;	if ((csd_word[0] & 0x00000001) != 1) {		sd_err_code = ERR_CSD_REGISTER_ERROR;		printk("%s() ERR_CSD_REGISTER_ERROR\n", __func__);		return FALSE;	}	csd_bit = (sd_csd_bit_t *) csd_word;	csd->CSDStructure = csd_bit->CSD_STRUCTURE;	csd->MMCSpecVersion = csd_bit->MMC_SPEC_VERS;	csd->TAAC_u = TAAC_TimeValueTable_u[csd_bit->TAAC_TimeValue] * TAAC_TimeUnitTable[csd_bit->TAAC_TimeUnit] / 10;	csd->NSAC_u = csd_bit->NSAC * 100;	csd->TransferSpeed = TRANS_SPEED_RateUintTable[csd_bit->TRAN_SPEED_RateUnit] * TRANS_SPEED_TimeValueTable_u[csd_bit->TRAN_SPEED_TimeValue] / 10;	csd->CardCmdClass = csd_bit->CCC;	//added by FTC_mingfeng, for compatible with SD1.0, SD1.0 < 512 bytes and SD2.0 = 512 bytes	csd->ReadBlockLength = two_power((csd_bit->READ_BL_LEN>9)?9:csd_bit->READ_BL_LEN);	csd->ReadBlockPartial = csd_bit->READ_BL_PARTIAL;	csd->WriteBlockMisalign = csd_bit->WRITE_BLK_MISALIGN;	csd->ReadBlockMisalign = csd_bit->READ_BLK_MISALIGN;	csd->DSRImplemant = csd_bit->DSR_IMP;	if(sd_card_info.OCR & SD_OCR_STATUS_BIT ){		//high capacity support	    CSDPtr2 = (SD_CSD_BIT_Struct_V2 *)csd_word;	    blocks = ( CSDPtr2->C_SIZE_1 + 1 ) << 10;	}	else{	    mult = 1 << (csd_bit->C_SIZE_MULT + 2);	    //added by FTC_mingfeng, for compatible with SD1.0, SD1.0 IP must <= 512 bytes and SD2.0 = 512 bytes	    blocks = (((csd_bit->C_SIZE_1 | (csd_bit->C_SIZE_2 << 2)) + 1) * mult) << (csd_bit->READ_BL_LEN - 9);	}	csd->BlockNumber = blocks;	csd->MemorySize = (blocks >> 14) * (csd->ReadBlockLength >> 6); // size > 2G can't show, use MB unit//	printk("MemorySize=%d MB,ReadBlockLength=%d,BlockNumber=%d\n",csd->MemorySize,csd->ReadBlockLength,csd->BlockNumber);//	printk("C_SIZE_1=%d,C_SIZE_2=%d\n",csd_bit->C_SIZE_1,csd_bit->C_SIZE_2);//	printk("C_SIZE_1=%d,C_SIZE_2=%d\n",CSDPtr2->C_SIZE_1,CSDPtr2->C_SIZE_2);//	csd->MemorySize = blocks * csd->ReadBlockLength;	//for SD 2.0, the following four are 'don't care'	csd->VDDReadMin_u = VDD_CURR_MIN_Table_u[csd_bit->VDD_R_CURR_MIN];	csd->VDDReadMax_u = VDD_CURR_MAX_Table_u[csd_bit->VDD_R_CURR_MAX];	csd->VDDWriteMin_u = VDD_CURR_MIN_Table_u[csd_bit->VDD_W_CURR_MIN];	csd->VDDWriteMax_u = VDD_CURR_MAX_Table_u[csd_bit->VDD_W_CURR_MAX];	csd->EraseBlkEnable = csd_bit->ERASE_BLK_ENABLE;	csd->EraseSectorSize = csd_bit->ERASE_SECTOR_SIZE + 1;	csd->WriteProtectGroupSize = csd_bit->WP_GRP_SIZE + 1;	csd->WriteProtectGroupEnable = csd_bit->WP_GRP_ENABLE;	csd->WriteSpeedFactor = two_power(csd_bit->R2W_FACTOR);	//added by FTC_mingfeng, for compatible with SD1.0, SD1.0 < 512 bytes and SD2.0 = 512 bytes	csd->WriteBlockLength = two_power((csd_bit->WRITE_BL_LEN>9)?9:csd_bit->WRITE_BL_LEN);	csd->WriteBlockPartial = csd_bit->WRITE_BL_PARTIAL;	csd->CopyFlag = csd_bit->COPY;	csd->PermanentWriteProtect = csd_bit->PERM_WRITE_PROTECT;	csd->TemporaryWriteProtect = csd_bit->TMP_WRITE_PROTECT;	if (csd_bit->FILE_FORMAT_GRP == 0)		csd->FileFormat = csd_bit->FILE_FORMAT;	else		csd->FileFormat = FILE_FORMAT_RESERVED;	return TRUE;}int sd_cid_parse(sd_cid_t *cid, uint *cid_word){	unchar *ptr;	int i;	if ((cid_word[0] & 0x00000001) != 1)	{		sd_err_code = ERR_CID_REGISTER_ERROR;		printk("%s() ERR_CID_REGISTER_ERROR\n", __func__);		return FALSE;	}	cid->ManufacturerID = (cid_word[3] & 0xFF000000) >> 24;	cid->ApplicationID = (cid_word[3] & 0x00FFFF00) >> 8;	ptr = (unchar *) cid_word;	ptr += 15 - 3;	for (i = 0; i < 6; i++, ptr--)		cid->ProductName[i] = *ptr;	cid->ProductName[6] = '\0'	;	cid->ProductRevisionLow = (cid_word[1] & 0x00F00000) >> 20;	cid->ProductRevisionHigh = (cid_word[1] & 0x000F0000) >> 16;	cid->ProductSerialNumber = ((cid_word[1] & 0x0000FFFF) << 16) + ((cid_word[0] & 0xFFFF0000) >> 16);	cid->ManufactureMonth = ((cid_word[0] & 0x00000F00) >> 8);

⌨️ 快捷键说明

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