예제 #1
0
파일: sd_hal.c 프로젝트: FHV-S1-FFPST/BOSS
uint32_t
identifyCard( void )
{
	// NOTE: see OMAP35x.pdf page 3164, starterware and sd_spec 2.0

	uint8_t hcsFlag = 0;

	memset( &cardInfo, 0, sizeof( CARD_INFO ) );

	// send GO_IDLE_STATE
	if ( sendCmd0() )
	{
		// an error occured sending CMD0
		return 1;
	}

	// cmd5 is reserved for I/O cards: SDIO. will return 0 if it is SDIO
	if ( 0 == sendCmd5() )
	{
		return 1;
	}

	// send GO_IDLE_STATE again
	if ( sendCmd0() )
	{
		// an error occured sending CMD0
		return 1;
	}

	// send SEND_IF_COND
	if ( 0 == sendCmd8() )
	{
		// NOTE: it is an SD card compliant with standard 2.0 or later

		uint32_t rsp0 = MMCHS_RSP10 & 0x0000FFFF;
		uint32_t supportedVoltage = rsp0 & 0xFFF;
		if ( supportedVoltage != 0x1AA )
		{
			// NOT supported:
			return 1;
		}

		hcsFlag = TRUE;
	}

	while ( 1 )
	{
		// send SD_SEND_OP_COND
		// NOTE: sd_spec 2.0 page 26: While repeating ACMD41, the host shall not issue another command except CMD0. => other sources say repeat CMD55 too
		if ( 0 == sendACmd41( hcsFlag ) )
		{
			// if card is busy, repeat again, otherwise card is identified
			if ( ! isCardBusy() )
			{
				// NOTE: it is a SD card compliant with standard 1.x

				// store ocr in card-info
				cardInfo.ocr = MMCHS_RSP10;
				// check if card is high-capacity or not (HCR-bit in OCR at position 30)
				cardInfo.highCap = ( cardInfo.ocr & ( 1 << 30 ) ) ? 1 : 0;

				goto cardIdentified;
			}
		}
		// no response => its no SD meory card
		else
		{
			break;
		}
	}

	// NOTE: at this point we are a MMC card - we don't support them
	return 1;

cardIdentified:
	// send ALL_SEND_CID
	if ( sendCmd2() )
	{
		return 1;
	}

	// store card-info just returned by CMD2 in RSP10-76
	cardInfo.raw_cid[ 0 ] = MMCHS_RSP10;
	cardInfo.raw_cid[ 1 ] = MMCHS_RSP32;
	cardInfo.raw_cid[ 2 ] = MMCHS_RSP54;
	cardInfo.raw_cid[ 3 ] = MMCHS_RSP76;

	// send SEND_RELATIVE_ADDR to ask card to publish new realtive address
	if ( sendCmd3() )
	{
		return 1;
	}

	// store RCA just returned by CMD3
	cardInfo.rca = ( MMCHS_RSP10 & 0xFFFF0000 ) >> 16;

	// send SEND_CSD: request card-specific data
	if ( sendCmd9() )
	{
		return 1;
	}

	// store card-specific data just returned by CMD9 in RSP10-76
	cardInfo.raw_csd[ 0 ] = MMCHS_RSP10;
	cardInfo.raw_csd[ 1 ] = MMCHS_RSP32;
	cardInfo.raw_csd[ 2 ] = MMCHS_RSP54;
	cardInfo.raw_csd[ 3 ] = MMCHS_RSP76;

	if ( SD_CARD_CSD_VERSION( cardInfo ) )
	{
		cardInfo.tranSpeed = SD_CARD1_TRANSPEED(cardInfo);
		cardInfo.blkLen = 1 << (SD_CARD1_RDBLKLEN(cardInfo));
		cardInfo.size = SD_CARD1_SIZE(cardInfo);
		cardInfo.nBlks = cardInfo.size / cardInfo.blkLen;
	}
	else
	{
		cardInfo.tranSpeed = SD_CARD0_TRANSPEED(cardInfo);
		cardInfo.blkLen = 1 << (SD_CARD0_RDBLKLEN(cardInfo));
		cardInfo.nBlks = SD_CARD0_NUMBLK(cardInfo);
		cardInfo.size = SD_CARD0_SIZE(cardInfo);
	}

	// send SELECT/DESELECT_CARD to select card - now in transfer mode
	if ( sendCmd7() )
	{
		return 1;
	}

	// NOTE: at this point the card is initialized, identified and ready to be used

	// send block length only in case of standard capacity-card, send it ONCE after selection
	if ( ! cardInfo.highCap )
	{
		// send block length
		if ( sendCmd16() )
		{
			// an error occured during sending the command, return immediately
			return 1;
		}
	}

	// request SCR - will be transmitted throug a data-read!
	if ( sendACmd51() )
	{
		return 1;
	}

	uint8_t scrBuffer[ 8 ];
	memset( scrBuffer, 0, 8 );

	// SCR is transmitted in 8 bytes through a data-read
	if ( readTransferBuffer( 8, scrBuffer ) )
	{
		return 1;
	}

	cardInfo.raw_scr[ 0 ] = ( scrBuffer[ 3 ] << 24 ) | ( scrBuffer[ 2 ] << 16 ) | ( scrBuffer[ 1 ] << 8 ) | ( scrBuffer[ 0 ] );
	cardInfo.raw_scr[ 1 ] = ( scrBuffer[ 7 ] << 24 ) | ( scrBuffer[ 6 ] << 16 ) | ( scrBuffer[ 5 ] << 8 ) | ( scrBuffer[ 4 ] );

	cardInfo.sd_ver = SD_CARD_VERSION( cardInfo );
	cardInfo.busWidth = SD_CARD_BUSWIDTH( cardInfo );

	return 0;
}
예제 #2
0
unsigned int MMCSDCardInit(mmcsdCtrlInfo *ctrl)
{

    mmcsdCardInfo *card = ctrl->card;
    unsigned int retry = 0xFFFF;
    unsigned int status = 0;
    unsigned int khz;
    mmcsdCmd cmd;

    memset(ctrl->card, 0, sizeof(mmcsdCardInfo));

    card->ctrl = ctrl;

	/* CMD0 - reset card */
	status = MMCSDCardReset(ctrl);

	if (status == 0)
	{
		card->error = 1;
		return 0;
	}
	//mmc card initialization


    ctrl->card->cardType = MMCSD_CARD_MMC;
    //open drain для команд инициализации
    HWREG(ctrl->memBase + MMCHS_CON) |= MMCHS_CON_OD;

    //Set SD_SYSCTL[25] SRC
    //bit to 0x1 and wait until it returns to 0x0
    HWREG(ctrl->memBase + MMCHS_SYSCTL) |= MMCHS_SYSCTL_SRC;
    while(!(HWREG(ctrl->memBase + MMCHS_SYSCTL) & MMCHS_SYSCTL_SRC));
    while(HWREG(ctrl->memBase + MMCHS_SYSCTL) & MMCHS_SYSCTL_SRC);

   /* CMD1 - SEND_OP_COND */
    retry = RETRY; //с потолка
    cmd.idx = SD_CMD(1);
    cmd.flags = 0;
    cmd.arg = 0x40ff8080;/////карта больше 2 Гб?
    cmd.rsp[0] = 0;
do{
	status = ctrl->cmdSend(ctrl, &cmd);
	if (status == 0) {
    	card->error = 1;
    	return status; //если нет ответа, можно выходить
	}
	//добавил задержку для кривой eMMC СОТА
	delay(10);

} while (!(cmd.rsp[0] & ((unsigned int)BIT(31))) && retry--);

	if (0xffffffff == retry) //карта до 2 Гб?
	{
		retry = RETRY; //c потолка
        cmd.arg = 0x00ff8080; //волшебная цыфорка
		do{
			status = ctrl->cmdSend(ctrl, &cmd);
			if (status == 0) {
		    	card->error = 1;
		    	return status; //если нет ответа, можно выходить
			}
			//добавил задержку для кривой eMMC СОТА
			delay(10);
		} while (!(cmd.rsp[0] & ((unsigned int)BIT(31))) && retry--);

	}
	if (0xffffffff == retry) {
    	card->error = 1;
		return 0;
	}

	//сохраняем OCR
    card->ocr = cmd.rsp[0];
    card->highCap = (card->ocr & SD_OCR_HIGH_CAPACITY) ? 1 : 0;

   /* CMD2 - ALL_SEND_CID */
    cmd.idx = SD_CMD(2);
    cmd.flags = SD_CMDRSP_136BITS;
    cmd.arg = 0;
	status = ctrl->cmdSend(ctrl, &cmd);
	if (status == 0) {
    	card->error = 1;
    	return status; //если нет ответа, можно выходить
	}

	//Сохраняем CID карты
    memcpy(card->raw_cid, cmd.rsp, 16);

  /* CMD3 - SET_RELATIVE_ADDR */
    cmd.idx = SD_CMD(3);
    cmd.flags = 0;
    cmd.arg = 2 << 16;
	status = ctrl->cmdSend(ctrl, &cmd);
	if (status == 0) {
    	card->error = 1;
    	return status; //если нет ответа, можно выходить
	}

    card->rca = 2; //тупо

    //вырубаем open drain для команд инициализации
    HWREG(ctrl->memBase + MMCHS_CON) &= ~MMCHS_CON_OD;


    /* Send CMD9, to get the card specific data */
     cmd.idx = SD_CMD(9);
     cmd.flags = SD_CMDRSP_136BITS;
     cmd.arg = card->rca << 16;

		status = ctrl->cmdSend(ctrl, &cmd);
		if (status == 0) {
	    	card->error = 1;
	    	return status; //если нет ответа, можно выходить
		}

     memcpy(card->raw_csd, cmd.rsp, 16);

     card->sd_ver =  SD_CARD_CSD_VERSION(card);
     card->tranSpeed = SD_CARD0_TRANSPEED(card);

     //Меняем тактовую частоту на повыше
     //если где-то еще используется - запихнуть в функцию
     switch (card->tranSpeed & 0x00000007) {
     case 0:
    	 khz = 100e3;
    	 break;
     case 1:
      	 khz = 1000e3;
       	 break;
     case 2:
       	 khz = 10000e3;
      	 break;
     case 3:
       	 khz = 100000e3;
      	 break;
     default:
         UARTPuts("TRAN_SPEED incorrect value read", -1);
         card->error = 1;
    	 return 0;
     }
     switch ((card->tranSpeed) >> 3) {
     case 1:
    	 ctrl->opClk = 1 * khz;
    	 break;
     case 2:
    	 ctrl->opClk = 1.2 * khz;
    	 break;
     case 3:
    	 ctrl->opClk = 1.3 * khz;
    	 break;
     case 4:
    	 ctrl->opClk = 1.5 * khz;
    	 break;
     case 5:
    	 ctrl->opClk = 2 * khz;
    	 break;
     case 6:
    	 ctrl->opClk = 2.6 * khz;
    	 break;
     case 7:
    	 ctrl->opClk = 3 * khz;
    	 break;
     case 8:
    	 ctrl->opClk = 3.5 * khz;
    	 break;
     case 9:
    	 ctrl->opClk = 4 * khz;
    	 break;
     case 10:
    	 ctrl->opClk = 4.5 * khz;
    	 break;
     case 11:
    	 ctrl->opClk = 5.2 * khz;
    	 break;
     case 12:
    	 ctrl->opClk = 5.5 * khz;
    	 break;
     case 13:
    	 ctrl->opClk = 6 * khz;
    	 break;
     case 14:
    	 ctrl->opClk = 7 * khz;
    	 break;
     case 15:
    	 ctrl->opClk = 8 * khz;
    	 break;
     default:
         UARTPuts("TRAN_SPEED incorrect value read", -1);
         card->error = 1;
    	 return 0;
     }
     status = ctrl->busFreqConfig(ctrl, ctrl->opClk);

     if (status != 0) //эта функция возвращает ноль при успехе
     {
    	 card->error = 1;
         UARTPuts("HS MMC/SD TRAN_SPEED freqval set failed\n\r", -1);
         return 0;
     }

    //если спецификация вер. 4.0 и выше
     if (card->sd_ver > 3)
	 {
         /* Send CMD7 select card */
          cmd.idx = SD_CMD(7);
          cmd.flags = 0; //ответ R1
          cmd.arg = card->rca << 16;

  		status = ctrl->cmdSend(ctrl, &cmd);
 		if (status == 0) {
 			card->error = 1;
 			return status;
 		}

#if 0 //говнокод
 		if ((cmd.rsp[0] & BIT(25))) //если карта залочена стираем нафиг с нее все
 		{
 			//устанавливаем длину блока 1 байт
 	        /* Send CMD16 */
 	        cmd.idx = SD_CMD(16);
 	        cmd.flags = 0; //ответ R1
 	        cmd.arg = 1; //1 байт длина блока
 	   		status = ctrl->cmdSend(ctrl, &cmd);
 	 		if (status == 0) {
 	 			card->error = 1;
 	 			return status;
 	 		}

 	  		dataBuffer[0] = BIT(3); //Force-erase bit
 	  		dataBuffer[1] = 0; //Force-erase bit
 	  		dataBuffer[2] = 0; //Force-erase bit
 	  		dataBuffer[3] = BIT(3); //Force-erase bit

#ifdef CACHE
		  /* Invalidate the data cache. */
 			CacheDataCleanBuff((unsigned int)dataBuffer, 4);
#endif
 			ctrl->xferSetup(ctrl, 0/*0 - WRITE*/, dataBuffer, 1, 1); //Achtung! посылка одного байта
 			cmd.idx = SD_CMD(42);
 			cmd.flags = SD_CMDRSP_WRITE | SD_CMDRSP_DATA | (ctrl->dmaEnable << SD_CMDRSP_DMAEN_OFFSET);
 			cmd.arg = 0;
 			cmd.nblks = 1;
 			cmd.data = (signed char*)dataBuffer;
 			status = ctrl->cmdSend(ctrl, &cmd);
 	 		if (status == 0) {
 	 			card->error = 1;
 	 			return status;
 	 		}

 			status = ctrl->xferStatusGet(ctrl);

// 			if (status == 0) return 0;

 			//проверяем статус карты
 	        cmd.idx = SD_CMD(13);
 	        cmd.flags = 0; //ответ R1
 	        cmd.arg = card->rca << 16; //1 байт длина блока
 	   		status = ctrl->cmdSend(ctrl, &cmd);
 	 		if (status == 0) {
 	 			card->error = 1;
 	 			return status;
 	 		}


			//ждем пока карта не снимет busy!
	        while (!(HWREG(ctrl->memBase + MMCHS_PSTATE) & (unsigned int)BIT(20)));

 			//возвращаем длину блока в нормальное состояние
 	        /* Send CMD16 */
 	        cmd.idx = SD_CMD(16);
 	        cmd.flags = 0; //ответ R1
 	        cmd.arg = 512; //512 байт длина блока
 	   		status = ctrl->cmdSend(ctrl, &cmd);
 	 		if (status == 0) {
 	 			card->error = 1;
 	 			return status;
 	 		}
	  		while(1);
 		}
#endif

    	 //надо затянуть EXT_CSD
		  ctrl->xferSetup(ctrl, 1, dataBuffer, 512, 1);
		  cmd.idx = SD_CMD(8);
		  cmd.flags = SD_CMDRSP_READ | SD_CMDRSP_DATA | (ctrl->dmaEnable << SD_CMDRSP_DMAEN_OFFSET);
		  cmd.arg = 0;
		  cmd.nblks = 1;
		  cmd.data = (signed char*)dataBuffer;
		  status = ctrl->cmdSend(ctrl, &cmd);
	 		if (status == 0) {
	 			card->error = 1;
	 			return status;
	 		}

		  status = ctrl->xferStatusGet(ctrl);
	 		if (status == 0) {
	 			card->error = 1;
	 			return status;
	 		}
#ifdef CACHE
		  /* Invalidate the data cache. */
		  CacheDataInvalidateBuff((unsigned int)dataBuffer, DATA_RESPONSE_WIDTH);
#endif
	}
     else
     {
    	 UARTPuts("Old Slowpoke eMMC card\n\r", -1);
     }

     //разное определение размера карты для highCap карт  и обычных карт
     if (!(card->highCap))
     { //не факт, что работает для !highCap
		 card->blkLen = 1 << (SD_CARD0_RDBLKLEN(card));
		 card->size = SD_CARD0_SIZE(card);
		 card->nBlks = card->size / card->blkLen;

    /* Set data block length to 512 (for byte addressing cards) */
		 if (card->blkLen != 512)
		 {
			 cmd.idx = SD_CMD(16);
			 cmd.flags = 0; //resp R1
			 cmd.arg = 512;
			 status = ctrl->cmdSend(ctrl, &cmd);

		 		if (status == 0) {
		 			card->error = 1;
		 			return status;
		 		}
			 else
			 {
				 card->blkLen = 512;
			 }

		 }
     }
     else //highcap - берем sector size из EXT_CSD
     {
		  //надо сохранить нужную инфу из EXT_CSD на будущее
		  //пока только SEC_COUNT
		 card->blkLen = 512;
		 card->nBlks = (dataBuffer[212] << 0) |
				  (dataBuffer[213] << 8) |
				  (dataBuffer[214] << 16) |
				  (dataBuffer[215] << 24);
		 card->size = card->nBlks; //для highcap карты размер в секторах
     }
     card->busWidth = 1;
#if 0 //деселект рабочий но забили на него - карта у нас одна
     //deselect card
     /* Send CMD7 select card */
    cmd.idx = SD_CMD(7);
    cmd.flags = SD_CMDRSP_NONE; //ответ R1
    cmd.arg = 0; //rca = 0
	status = ctrl->cmdSend(ctrl, &cmd);
		if (status == 0) return status;
#endif
	//end emmc initialization
    return 1;
}