SD/MMC驱动移植
虽然u-boot已经成功从SD卡启动,但是目前阶段,不论是IC读取SD卡中的8K代码,还是从SD卡搬运u-boot到RAM中运行,都是IROM内部代码操作SD卡的,并不是u-boot实现的。
u-boot本身对SD/MMC支持的已经很完善,本节将实现此部分移植。
1、在/home/eric/Documents/u-boot-2013.04-rc1/drivers/mmc下新建文件s3c6410_sdhci.c
/*
* Samsung S3C6410 SD/MMC driver
* Based on sdhci.c
*/
#include <common.h>
#include <malloc.h>
#include <sdhci.h>
#include <asm/arch/s3c6410.h>
#ifdef CONFIG_MMC_CHANNEL
#define MMC_CHANNEL CONFIG_MMC_CHANNEL
#else
#define MMC_CHANNEL 0
#endif
#define ELFIN_HSMMC_BASE 0x7C200000
#define MMC_REGS_BASE (ELFIN_HSMMC_BASE + 0x100000*MMC_CHANNEL)
static void sdhc_set_gpio()
{
u32 reg;
#if (MMC_CHANNEL == 0)
reg = readl(GPGCON) & 0xf0000000;
writel(reg | 0x02222222, GPGCON);
reg = readl(GPGPUD) & 0xfffff000;
writel(reg, GPGPUD);
#elif (MMC_CHANNEL == 1)
writel(0x00222222, GPHCON0);
writel(0x00000000, GPHCON1);
reg = readl(GPHPUD) & 0xfffff000;
writel(reg, GPHPUD);
#else
printf("#####err: SDMMC channel is not defined!\n");
#endif
}
int s3c_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks)
{
struct sdhci_host *host = NULL;
host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
if (!host) {
printf("#####err: sdhci_host malloc fails!\n");
return 1;
}
sdhc_set_gpio();
host->name = "Samsung Host Controller";
host->ioaddr = (void *)regbase;
host->quirks = quirks;
host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
if (quirks & SDHCI_QUIRK_REG32_RW)
host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
else
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
host->host_caps = MMC_MODE_HC;
add_sdhci(host, max_clk, min_clk);
return 0;
}
int board_mmc_init(bd_t *bis)
{
return s3c_sdhci_init(MMC_REGS_BASE, 52000000, 400000, 0);
}
2、修改/home/eric/Documents/u-boot-2013.04-rc1/drivers/mmc/sdhci.c
167行:屏蔽mask |= SDHCI_INT_DATA_END; 防止数据读写超时
mask = SDHCI_INT_RESPONSE;
if (!(cmd->resp_type & MMC_RSP_PRESENT))
flags = SDHCI_CMD_RESP_NONE;
else if (cmd->resp_type & MMC_RSP_136)
flags = SDHCI_CMD_RESP_LONG;
else if (cmd->resp_type & MMC_RSP_BUSY) {
flags = SDHCI_CMD_RESP_SHORT_BUSY;
//mask |= SDHCI_INT_DATA_END; //eric++ 2017-11-11
} else
flags = SDHCI_CMD_RESP_SHORT;
注:如果不做修改,执行mmc read 的时候,将出错:
SMDK6410 # mmc read 50000000 0 10
MMC read: dev # 0, block # 0, count 16 … Timeout for status update!
mmc fail to send stop cmd
0 blocks read: ERROR
3、修改/home/eric/Documents/u-boot-2013.04-rc1/drivers/mmc/sdhci.c,添加mmc->b_max = 1024;
490行:
if (host->host_caps)
mmc->host_caps |= host->host_caps;
mmc->b_max = 1024; //eric++ 2017-11-11
sdhci_reset(host, SDHCI_RESET_ALL);
mmc_register(mmc);
4、u-boot-2013.04-rc1/include/configs/smdk6410.h 中添加 SD卡驱动宏定义
84行:
/*
* SD/MMC 驱动移植,eric++2017-11-11
*/
#define CONFIG_MMC
#define CONFIG_GENERIC_MMC
#define CONFIG_CMD_MMC
#define CONFIG_MMC_SDMA
#define CONFIG_SDHCI
#define CONFIG_S3C6410_SDHCI
#define SDHCI_DEFAULT_BOUNDRAY_SIZE (512*1024)
5、u-boot-2013.04-rc1/drivers/mmc/mmc.c初始化部分添加容量打印函数,,方便上电的时候就可以查看SD容量
1304行:
printf("%s: %d,", m->name, m->block_dev.dev);
//为了正常获取SD卡容量,先将mmc初始化
mmc_init(m);
print_size(m->capacity, "\n"); //eric++打印SD卡容量
6、编译,启动,进行测试
U-Boot 2013.04-rc1 (Nov 11 2017 - 11:29:34) for SMDK6410
CPU: S3C6410@533MHz
Fclk = 533MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode)
Board: SMDK6410
DRAM: 128 MiB
WARNING: Caches not enabled
Flash: *** failed ***
NAND: 256 MiB
MMC: Samsung Host Controller: 0,3.6 GiB
In: serial
Out: serial
Err: serial
Net: CS8900-0
Hit any key to stop autoboot: 0
NAND read: device 0 offset 0x60000, size 0x1c0000
1835008 bytes read: OK
Wrong Image Format for bootm command
ERROR: can't get kernel image!
MMC: Samsung Host Controller: 0,3.6 GiB;u-boot已经成功识别MMC,以及容量大小;
用mmcinfo命令测试一下,可以获取MMC的详细信息:
SMDK6410 # mmcinfo
Device: Samsung Host Controller
Manufacturer ID: 2
OEM: 544d
Name: SA04G
Tran Speed: 50000000
Rd Block Len: 512
SD version 2.0
High Capacity: Yes
Capacity: 3.6 GiB
Bus Width: 4-bit
SMDK6410 #