📄 fs_sdmmc_dev.c
字号:
/**********************************************************************************************
***********************************************************************************************
** COPYRIGHT (c) 2004 BY ROCK-CHIP FUZHOU
** -- ALL RIGHTS RESERVED --
**
** File Name: fs_sdmmc_dev.c
** Author: XUESHAN LIN
** Created: 29th SEP 2004
** Revision: 1.00
**
**-----------------------------------------------------------------------
** Modified: Xiebangwang
** Description: 增加对Ver2.00 or later SD Memory Card 的兼容性,目前完全兼容MMC/SD/SDHC
** Revision: 2.00
** Date: 2008-02-16
**
**********************************************************************************************
**********************************************************************************************/
#include "arm.h"
#include "../inc/fs_comm.h"
#if defined(BOARD)
#if(SD_CARD_EN)
#define _IN_SD_
#include "fs_sdmmc_dev.h"
#define SDMMC_FAT_CACHE_COUNT 16
#define SDMMC_FDT_CACHE_COUNT 4
#define SDMMC_DATA_CACHE_COUNT 2
#define SD_DMA_TRAN_EN 0
#define READ_BLOCK_LEN_OFFSET 16
#define READ_BLOCK_LEN_MASK 0x000F0000
#define CSIZE_MULT_OFFSET 15
#define CSIZE_MULT_MASK 0x00038000
#define SDMMC_DATABUF_1_TX_WIDTH_MASK 0x3
#define SDMMC_DATABUF_2_TX_WIDTH_MASK 0x30
#define SDMMC_DATABUF_SWAP_MASK 0x300
#define SDMMC_MMU_SWAP_MASK 0x3FF
uint8 SdFatCacheBuf[SDMMC_FAT_CACHE_COUNT][512];
uint8 SdFdtCacheBuf[SDMMC_FDT_CACHE_COUNT][512];
uint8 SdDataCacheBuf[SDMMC_DATA_CACHE_COUNT][512];
FS_CACHE_DATA SD_FatCacheData[SDMMC_FAT_CACHE_COUNT];
FS_CACHE_DATA SD_FdtCacheData[SDMMC_FDT_CACHE_COUNT];
FS_CACHE_DATA SD_DataCacheData[SDMMC_DATA_CACHE_COUNT];
FS_CACHE SdFatCache = {SD_FatCacheData, 0, SDMMC_FAT_CACHE_COUNT};
FS_CACHE SdFdtCache = {SD_FdtCacheData, 0, SDMMC_FDT_CACHE_COUNT};
FS_CACHE SdDataCache = {SD_DataCacheData, 0, SDMMC_DATA_CACHE_COUNT};
uint32 SDTotSec; //SD卡总扇区数
uint32 SDBytsPerSec; //SD卡每扇区字节数
uint32 SDCardInsert; //SD卡每扇区字节数
uint32 SDCardChange;
uint32 SdmmcCardType;
uint32 SdmmcCardRca;
uint32 CardIntStatus;
uint32 MMC_Divider = 1;
uint32 SD_Divider = 0;
static uint32 prevMMC_Divider = 1;
static uint32 prevSD_Divider = 0;
int SdmmcGetStatus(void);
int SdmmcInit(void);
int SdmmcReadSec(uint32 LBA, uint32 SecCount, void *buf);
int SdmmcWriteSec(uint32 LBA, uint32 SecCount, void *buf);
int SdmmcIoCtl(uint32 cmd, uint32 arg, void *buf);
int SdmmcMediumInit(void);
int SdmmcReadMSecs(unsigned long LBA, unsigned int count, void *buf);
int Sdmmc_send_cmd(unsigned long cmd_abbr, unsigned long arg);
int SdmmcWriteMSecs(unsigned long LBA, unsigned int count, void *buf);
void SdmmcCacheInit(void);
int SdmmcChkInsert(void);
void SysSdmmcChkInsert(void* msg);
void SdmmcSetFrequency(void);
int SdmmcInsertState(void);
int SdmmcChkBusy(void);
#define SDMMC_READ_BUF_COUNT 8
static uint32 SdmmcPrevPBA = 0xFFFFFFFF;
static uint32 SdmmcReadBuf[SDMMC_READ_BUF_COUNT][128];
const FS_DEVICE_TYPE FS_SdmmcDevice =
{
"E:\\",
"SD CARD",
SdmmcGetStatus,
SdmmcReadSec,
SdmmcWriteSec,
SdmmcIoCtl,
SdmmcMediumInit,
&SdFatCache,
&SdFdtCache,
&SdDataCache
};
void Sdmmc_delay(unsigned long count)
{
int i;
for (i = 0;i < count; i++)
{
;
}
}
/***************************************************************************
函数描述:延时
入口参数:
出口参数:
调用函数:
***************************************************************************/
void FS_Delay10cyc(uint32 count)
{
uint16 i;
while (count --)
for (i = 0; i < 3; i++);
}
/*********************************************************************************
* Copyright (C),2007, Fuzhou Rockchip Co.,Ltd.
* Function name : SdmmcIsr()
* Author: ZhenFu Fang
* Description: SD MMC 卡中断处理
* Calls:
* Input:
* Return:
* Remark:
* History:
* <author> <time> <version> <desc>
* FZF 2007-6-21 19:30 1.0 ORG
*
*********************************************************************************/
void SdmmcIsrProc(void)
{
unsigned long rdata;
rdata = ReadReg32(SDMMC_SD_INT);
if (SDMMC_CMD_RESP_TX_INT_STAT_YES == (rdata & SDMMC_CMD_RESP_TX_INT_STAT_YES))
{
/* Clear corresponding interrupt flag */
WriteReg32(SDMMC_SD_INT, (ReadReg32(SDMMC_SD_INT) & (~SDMMC_CMD_RESP_TX_INT_STAT_YES)));
CardIntStatus |= CMD_RESP_INT;
}
if (SDMMC_DATA_TX_INT_STAT_YES == (rdata & SDMMC_DATA_TX_INT_STAT_YES))
{
/* Clear corresponding interrupt flag */
WriteReg32(SDMMC_SD_INT, (ReadReg32(SDMMC_SD_INT) & (~SDMMC_DATA_TX_INT_STAT_YES)));
CardIntStatus |= DATA_TX_INT;
}
if (SDMMC_HOST_CARD_DETECT_INT_STAT_YES == (rdata & SDMMC_HOST_CARD_DETECT_INT_STAT_YES))
{
//CardIntStatus |= CARD_DET_INT;
CardIntStatus |= CARD_DET_INT;//modify by xbw @2008-02-16
WriteReg32(SDMMC_SD_INT, ReadReg32(SDMMC_SD_INT) & (~SDMMC_HOST_CARD_DETECT_INT_STAT_YES));
rdata = ReadReg32(SDMMC_SD_CARDA);
if (rdata & SDMMC_CARD_DETECT_SIGNAL_HIGH)
{
SDCardInsert = FALSE;
WriteReg32(SDMMC_SD_CARDA,
SDMMC_CARD_SEL_DIS |
SDMMC_CARD_POWER_CTRL_SIGNAL_DIS |
SDMMC_CARD_DETECT_INT_EN);
}
else
{
SDCardInsert = TRUE;
}
}
}
int SdmmcGetStatus(void)
{
return(0);
}
int SdmmcIoCtl(uint32 cmd, uint32 arg, void *buf)
{
uint32 *rbuf;
rbuf = (uint32 *)buf;
switch (cmd)
{
case IO_CTL_GET_CAPACITY:
*rbuf = ((uint32)SDTotSec * SDBytsPerSec) >> 9;
break;
case IO_CTL_GET_MEDIUM_START_SEC:
*rbuf = 0;
break;
case IO_CTL_GET_MEDIUM_STATUS:
if (SdmmcChkInsert() == TRUE)
*rbuf = MEDIUM_STATUS_RDY;
else
*rbuf = MEDIUM_STATUS_NOON;
break;
case IO_CTL_MEDIUM_CHANGE:
SdmmcChkInsert();
*rbuf = SDCardChange;
SDCardChange = 0;
break;
case IO_CTL_FLUSH_CACHE:
SdmmcCacheInit();
break;
default:
break;
}
return(0);
}
void SdmmcCacheInit(void)
{
uint32 i;
FS_CACHE_DATA *pCache;
pCache = SdFatCache.pCacheData;
for (i = 0; i < SDMMC_FAT_CACHE_COUNT; i++)
{
pCache->flag = 0;
pCache->pBuffer = &SdFatCacheBuf[i][0];
pCache->SectorNo = 0xFFFFFFFF;
pCache++;
}
pCache = SdFdtCache.pCacheData;
for (i = 0; i < SDMMC_FDT_CACHE_COUNT; i++)
{
pCache->flag = 0;
pCache->pBuffer = &SdFdtCacheBuf[i][0];
pCache->SectorNo = 0xFFFFFFFF;
pCache++;
}
pCache = SdDataCache.pCacheData;
for (i = 0; i < SDMMC_DATA_CACHE_COUNT; i++)
{
pCache->flag = 0;
pCache->pBuffer = &SdDataCacheBuf[i][0];
pCache->SectorNo = 0xFFFFFFFF;
pCache++;
}
}
int SdmmcMediumInit(void)
{
int err;
IOMUX_SetSDPort(SD_SD_TYPE);
SdmmcCacheInit();
err = SdmmcInit();
if (err != SUCCEED)
{
Scu_ClockDisable(SDMMC_CLOCK);
}
SDCardChange = 0;
return(err);
}
/*******************************************************************************************
*函数描述:读SD卡CSD数据
*入口参数:无
*出口参数:buf=数据指针
*调用函数:无
* History:
* <author> <time> <version> <desc>
* LXS,FZF 1.0 适用于 SD Memory Card Ver1.0
*
* Xiebangwang 2008-2-18 2.0 增加对SDHC的兼容
*
*********************************************************************************************/
void SdmmcReadCsd(unsigned long *buf)
{
uint32 c_size_mult;
uint32 mult;
if (SUCCEED == Sdmmc_send_cmd(MMC_SEND_CSD, SdmmcCardRca))
{
#if (SDMMC_ISR_PROC_EN == 0)
Sdmmc_delay(10000);
#endif
buf[3] = ReadReg32(SDMMC_SD_RESA3);
buf[2] = ReadReg32(SDMMC_SD_RESA2);
buf[1] = ReadReg32(SDMMC_SD_RESA1);
buf[0] = ReadReg32(SDMMC_SD_RESA0);
if (SdmmcCardType == HC_SD_CARD)
{
//计算SDHC 卡容量块长度和总块数
SDBytsPerSec = 512;
SDTotSec = (((buf[1] & 0xffff0000) >> 16) + 1) << 10;
}
else
{
//计算SD/MMC卡的块长度和总块数
SDBytsPerSec = 1 << ((buf[2] & READ_BLOCK_LEN_MASK) >> READ_BLOCK_LEN_OFFSET);
c_size_mult = (buf[1] & CSIZE_MULT_MASK) >> CSIZE_MULT_OFFSET;
mult = 1 << (c_size_mult + 2);
SDTotSec = (((buf[2] & 0x3ff) << 2) + ((buf[1] & 0xc0000000) >> 30) + 1) * mult;
}
}
}
/**********************************************************************************************************
*函数描述:SD卡动态检测
*入口参数:无
*出口参数:SUCCEED成功, 其它值为失败
*调用函数:
* History:
* <author> <time> <version> <desc>
* LXS,FZF 1.0 插卡开机,静态检测卡。
*
* Xiebangwang 2007-12-15 1.1 增加SD卡动态检测
*
* Xiebangwang 2008-01-25 1.2 修改SD卡动态检测机制,改为加载与初始化分开
*
**********************************************************************************************************/
int SdmmcChkInsert(void)
{
uint32 rdata;
uint32 InsertState;
FS_VOLUME *pVolume;
rdata = GPIO_GetPinLevel(SD_DETECT_PIN);
pVolume = (FS_VOLUME *)(FS_FindDeviceName(&FS_SdmmcDevice)); // 获取卷信息
#if (SDCheckInsetLevel == 0)
if (rdata == 1)
#else
if (rdata == 0)
#endif
{
InsertState = FALSE;
SDTotSec = 0;
pVolume->FatInfo.Valid = 0; //若SD卡拔出,把fatInfo标志请零
//关闭SD卡Clock
Scu_ClockDisable(SDMMC_CLOCK);
}
else
{
InsertState = TRUE;
}
if (InsertState != SDCardInsert)
{
SDCardInsert = InsertState;
if (InsertState == TRUE)
{
SdmmcMediumInit();
pVolume->FatInfo.Valid = 1;//若SD插入,把fatInfo标志设置为1
}
SDCardChange = 1;
}
return(SDCardInsert);
}
/***************************************************************************
函数描述:使用IO口(PA7),中断检测,对SD卡进行动态检测
入口参数:无
出口参数:SUCCEED成功, 其它值为失败
调用函数:
***************************************************************************/
void SysSdmmcChkInsert(void* msg)
{
SdmmcChkInsert();
}
/*********************************************************************************************************
*函数描述:SD Memory Card初始化
*入口参数:无
*出口参数: 0--初始化成功; 1--失败
*调用函数:Scu_ModuleReset, Scu_ClockEnable, Sdmmc_delay , GPIO_SetPinDirection, GPIO_GetPinLevel,
WriteReg32, ReadReg32 Sdmmc_send_cmd
*
* History:
* <author> <time> <version> <desc>
* LXS,FZF 1.0 适用于 SD Memory Card Ver1.0
*
* Xiebangwang 2008-01-25 1.1 修改命令、响应以及数据三者间的延时长度
*
* Xiebangwang 2008-02-18 2.0 增加对Ver2.00 or later SD Memory Card的兼容
*
*********************************************************************************************************/
int SdmmcInit(void)
{
int i;
unsigned long rdata;
unsigned long error;
unsigned long SdCsd[4];
UINT32 freq;
UINT32 identify_divider;
Scu_ModuleReset(SDMMC_RESET, TRUE);
Sdmmc_delay(100);//10000
Scu_ModuleReset(SDMMC_RESET, FALSE);
Scu_ClockEnable(SDMMC_CLOCK);
SdmmcPrevPBA = 0xFFFFFFFF;
#if (SDMMC_ISR_PROC_EN == 0)
Sdmmc_delay(100);
#endif
GPIO_SetPinDirection(SD_DETECT_PIN, GPIO_IN);
rdata = GPIO_GetPinLevel(SD_DETECT_PIN);
#if (SDCheckInsetLevel == 0)
if (rdata == 1)
#else
if (rdata == 0)
#endif
{
SDCardInsert = FALSE;
return(1);
}
else
{
SDCardInsert = TRUE;
}
freq = Pll_get_apb_freq();
if (freq >= 60000)
{
identify_divider = 0xA6; //最高66Mhz
}
else if (freq >= 50000)
{
identify_divider = 0x96;
}
else if (freq >= 30000)
{
identify_divider = 0x80;
}
else
{
identify_divider = 0x50;
}
WriteReg32(SDMMC_SD_CTRL, (SDMMC_CARD_POWER_CTRL_CPU |
SDMMC_CARD_DETECT_FUNC_MECH |
SDMMC_CARD_CLK_RUN |
SDMMC_CARD_CLK_DIVIDER(identify_divider))); //the frequency range of 100KHz-400KHz
WriteReg32(SDMMC_SD_CARDA, (SDMMC_CARD_SEL_EN |
SDMMC_CARD_POWER_CTRL_SIGNAL_EN |
SDMMC_CARD_DETECT_INT_EN));
WriteReg32(SDMMC_SD_INT, (SDMMC_CMD_RESP_TX_INT_STAT_NO |
SDMMC_DATA_TX_INT_STAT_NO |
SDMMC_HOST_CARD_DETECT_INT_STAT_NO |
SDMMC_CMD_RESP_TX_INT_EN |
SDMMC_DATA_TX_INT_EN |
SDMMC_HOST_CARD_DETECT_INT_EN));
/* Delay */
#if (SDMMC_ISR_PROC_EN == 0)
Sdmmc_delay(100);
#endif
//确保使用CMD8前,卡处于Idle state
if (Sdmmc_send_cmd(MMC_GO_IDLE_STATE, 0x0000))
return (111);
#if (SDMMC_ISR_PROC_EN == 0)
Sdmmc_delay(100);
#endif
/***********************************************************************************************/
/*1. Ver2.00 or later SD Memory Card*/
/* Send CMD8 to check High Capacity SD CARD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -