sd/mmc初始化

[cpp] view plaincopyprint?

1.首先分析 sd/mmc 初始化:
// board.c
puts ("SD/MMC: ");
mmc_exist = mmc_initialize(gd->bd);
///
int mmc_initialize(bd_t *bis)
{
struct mmc *mmc;
int err;
//初始化一个双链表结构体变量。
INIT_LIST_HEAD(&mmc_devices);
//当前设备节点,还没放入到mmc结构中
cur_dev_num = 0;

if (board_mmc_init(bis) < 0)
cpu_mmc_init(bis);
//---------------------------------------------------------------------
/*
int cpu_mmc_init(bd_t *bis)
{
#ifdef CONFIG_S3C_HSMMC
setup_hsmmc_clock(); //配置mmc0~mmc3的时钟源
setup_hsmmc_cfg_gpio();
return smdk_s3c_hsmmc_init();
#else
return 0;
#endif
}
*/
---------
void setup_hsmmc_clock(void)
{
u32 tmp;
u32 clock;
u32 i;

/* MMC0 clock src = SCLKMPLL */
tmp = CLK_SRC4_REG & ~(0x0000000f);
CLK_SRC4_REG = tmp | 0x00000006;
/* MMC0 clock div */
tmp = CLK_DIV4_REG & ~(0x0000000f);
//根据时钟变化,同步SD卡的时钟。
clock = get_MPLL_CLK()/1000000;
for(i=0; i<0xf; i++)
{
if((clock / (i+1)) <= 50) {
CLK_DIV4_REG = tmp | i<<0;
break;
}
}
//同时也初始化ch2通道的时钟。
#ifdef USE_MMC2
/* MMC2 clock src = SCLKMPLL */
tmp = CLK_SRC4_REG & ~(0x00000f00);
CLK_SRC4_REG = tmp | 0x00000600;

/* MMC2 clock div */
tmp = CLK_DIV4_REG & ~(0x00000f00);
CLK_DIV4_REG = tmp | i<<8;
#endif

*/
------------------------------
//接着设置mmc gpio口的方向
void setup_hsmmc_cfg_gpio(void)
{
ulong reg;
//GPG0 就是一个通道0的接口定义
/* MMC channel 0 */
/* 7 pins will be assigned - GPG0[0:6] = CLK, CMD, CDn, DAT[0:3] */
reg = readl(GPG0CON) & 0xf0000000;
//设置为SD接口模式,定义了4bitdata。cmd clk ,cd
writel(reg | 0x02222222, GPG0CON);
reg = readl(GPG0PUD) & 0xffffc000;
//上啦使能,硬件io口需要强制上拉
writel(reg | 0x00002aaa, GPG0PUD);
writel(0x00003fff, GPG0DRV);

#ifdef USE_MMC2
/* MMC channel 2 */
/* 7 pins will be assigned - GPG2[0:6] = CLK, CMD, CDn, DAT[0:3] */
reg = readl(GPG2CON) & 0xf0000000;
writel(reg | 0x02222222, GPG2CON);
reg = readl(GPG2PUD) & 0xffffc000;
writel(reg | 0x00002aaa, GPG2PUD);
writel(0x00003fff, GPG2DRV);

*/
-----------------------------

[cpp] view plaincopyprint?

int smdk_s3c_hsmmc_init(void)
{
#ifdef USE_MMC0 //emmc
err = s3c_hsmmc_initialize(0);

#endif
#ifdef USE_MMC2 //sd
err = s3c_hsmmc_initialize(2);
#endif


[cpp] view plaincopyprint?

static int s3c_hsmmc_initialize(int channel)
{
struct mmc *mmc;
//定义了4个通道结构体
mmc = &mmc_channel[channel];
//名称分别是s3c_hsmmc0~3
sprintf(mmc->name, "S3C_HSMMC%d", channel);
//获取host
mmc->priv = &mmc_host[channel];
//命令函数
mmc->send_cmd = s3c_hsmmc_send_command;
//通过core层传递过来的参数,配置host寄存器(时钟,总线宽度等)
mmc->set_ios = s3c_hsmmc_set_ios;
//------------------------------>
mmc->init = s3c_hsmmc_init;
//------------------------------------>
//mmc工作电压范围
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
//mmc总线4bit模式,clk 52Hz。 hs模式
mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS;
#if defined(USE_MMC0_8BIT) || defined(USE_MMC2_8BIT)
mmc->host_caps |= MMC_MODE_8BIT;
#endif
最小工作平率
mmc->f_min = 400000;
mmc->f_max = 52000000;

mmc_host[channel].clock = 0;
//系统物理DMA地址
switch(channel) {
case 0:
mmc_host[channel].ioaddr = (void *)ELFIN_HSMMC_0_BASE;
break;

case 2:
mmc_host[channel].ioaddr = (void *)ELFIN_HSMMC_2_BASE;
break;

default:
printk("mmc err: not supported channel %d\n", channel);
}

return mmc_register(mmc);
}

//把mmc这个设备放入链表中
int mmc_register(struct mmc *mmc)
{
/* Setup the universal parts of the block interface just once */
mmc->block_dev.if_type = IF_TYPE_MMC;
//注意这里,分配当前mmc节点为 cur_dev_num ,第一个位 0,第2个位1。
mmc->block_dev.dev = cur_dev_num++;
mmc->block_dev.removable = 1;

/*-----------------------------------------------*
mmc->block_dev.block_read = mmc_bread;
mmc->block_dev.block_write = mmc_bwrite;
*-----------------------------------------------*/
INIT_LIST_HEAD(&mmc->link);

list_add_tail(&mmc->link, &mmc_devices);

return 0;
}
static int s3c_hsmmc_init(struct mmc *mmc)
{
struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
//重设host时钟为0,
sdhci_reset(host, SDHCI_RESET_ALL);

host->version = readw(host->ioaddr + SDHCI_HOST_VERSION);
sdhci_init(host);

sdhci_change_clock(host, 400000);

return 0;
}
时钟全部初始化完成,返回


[cpp] view plaincopyprint?

===============================================
//根据节点 0 找到mmc的结构
这里为什么是只定义0,是因为,当宏定义打开通道2时
//,设备只有一个,mmc->block_dev.dev =0++;所以找链表时,就是0 了。
//定义了4个通道结构体 mmc = &mmc_channel[2];
//如果定义 0 和2, 则会mmc = &mmc_channel[0] mmc = &mmc_channel[2],
//然后一个一个放入链表,dev+1,找通道2时,必须改 find_mmc_device(1);
mmc = find_mmc_device(0);
-------------------------------------------

[cpp] view plaincopyprint?

<pre class="cpp" name="code">struct mmc *find_mmc_device(int dev_num)
{
struct mmc *m;
struct list_head *entry;

list_for_each(entry, &mmc_devices) {
m = list_entry(entry, struct mmc, link);
//根据节点,来获取mmc结构
if (m->block_dev.dev == dev_num)
return m;
}

printf("MMC Device %d not found\n", dev_num);

return NULL;
}
====================================

//获取mmc结构后,开始进入mmc_init
if (mmc) {
err = mmc_init(mmc);
至此对sd/mmc初始化部分分析完成。
====================================================


[cpp] view plaincopyprint?

修改:
以前是从NAND flash启动,现在是从emmc启动,修改启动模式:
/include/configs/smdkv210signle.h
//#define CFG_FASTBOOT_NANDBSP //关闭 nand flash启动模式
#define CFG_FASTBOOT_SDMMCBSP //打开 sd/mmc启动模式

#define USE_MMC0 //支持 emmc (占用了通道0)
#define USE_MMC2 //支持sd (占用了通道2)

修改 /drivers/mmc/mmc.c 使它支持 emmc 和sd

int mmc_initialize(bd_t *bis)
{
struct mmc *mmc;
int err;

INIT_LIST_HEAD(&mmc_devices);
cur_dev_num = 0;

if (board_mmc_init(bis) < 0)
cpu_mmc_init(bis);

#if defined(DEBUG_S3C_HSMMC)
print_mmc_devices(',');
#endif

#if ( defined(USE_MMC0 ) && defined(USE_MMC2 ) )
//emmc
mmc = find_mmc_device(0);
if (mmc) {
err = mmc_init(mmc);
if (err)
err = mmc_init(mmc);
if (err) {
printf("Card init fail!\n");
return err;
}
}
printf("emmc %ldMB\n", (mmc->capacity/(1024*1024/(mmc->read_bl_len))));
//sd
mmc = find_mmc_device(1);
if (mmc) {
err = mmc_init(mmc);
if (err)
err = mmc_init(mmc);
if (err) {
printf("Card init fail!\n");
return err;
}
}
printf(" sd %ldMB\n", (mmc->capacity/(1024*1024/((mmc->read_bl_len)))));

return 0;
}
#else
mmc = find_mmc_device(0);
if (mmc) {
err = mmc_init(mmc);
if (err)
err = mmc_init(mmc);
if (err) {
printf("Card init fail!\n");
return err;
}
}
printf("%ldMB\n", (mmc->capacity/(1024*1024/(mmc->read_bl_len))));
return 0;
#endif

mmc->read_bl_len :这里要说下此变量,这是emmc 里CSD[80]所定义的,指明了此emmc的块大小,对于SD卡分区格式来说,只支持512 bety 块大小。如果 mmc->read_bl_len =1024
的话,对于整个分区体系来说是不支持的,会造成分区不完全。所以后续代码需要修改。

----------------------------------------------------------------------
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值