×
单片机 > 单片机程序设计 > 详情

mini2440 sd卡加载过程详解

发布时间:2024-05-18 发布时间:
|

最近在研究wifi模组, 是sdio接口的, 而手头刚好有一块mini2440,了解了一下sdio加载的过程, 发现和sd卡加载的过程是类似的。


这里用mini2440的内核源码, 来剖析一下sd卡的加载过程:


首先, mini2440内核加载的时候, 就会指定一部分设备初始化列表:


//---------------------------- arch/arm/mach-s3c2440/mach-mini2440.c ----------------------------//

/* devices we initialise */

static struct platform_device *mini2440_devices[] __initdata = {

&s3c_device_usb,

&s3c_device_rtc,

&s3c_device_lcd,

&s3c_device_wdt,

&s3c_device_i2c0,

&s3c_device_iis,

&mini2440_device_eth,

&s3c24xx_uda134x,

&s3c_device_nand,

&s3c_device_sdi, // sd设备

&s3c_device_usbgadget,

};

/* MMC/SD */

static struct s3c24xx_mci_pdata mini2440_mmc_cfg = {

.gpio_detect = S3C2410_GPG(8), // 插入检测引脚

.gpio_wprotect = S3C2410_GPH(8), // 写保护引脚

.set_power = NULL,

.ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34, // 有效电压范围是3.2~3.3V, 3.3~3.4V

};

static void __init mini2440_machine_init(void)

{

s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;

platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));

}

来看看s3c_device_sdi的定义:

//---------------------------- arch/arm/plat-s3c24xx/devs.c ----------------------------//

/* SDI */

static struct resource s3c_sdi_resource[] = {

[0] = {

.start = S3C24XX_PA_SDI,

.end = S3C24XX_PA_SDI + S3C24XX_SZ_SDI - 1,

.flags = IORESOURCE_MEM,

},

[1] = {

.start = IRQ_SDI,

.end = IRQ_SDI,

.flags = IORESOURCE_IRQ,

}

};

struct platform_device s3c_device_sdi = {

.name = "s3c2410-sdi",

.id = -1,

.num_resources = ARRAY_SIZE(s3c_sdi_resource),

.resource = s3c_sdi_resource,

};

有些人会奇怪, 我们这里不是在讲解2440吗, 为什么这里是s3c2410-sdi, 别急, 往下看:

//---------------------------- arch/arm/mach-s3c2440/mach-mini2440.c ----------------------------//

static void __init mini2440_machine_init(void)

{

s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;

platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));

}

//---------------------------- arch/arm/plat-s3c24xx/s3c244x.c ----------------------------//

void __init s3c244x_map_io(void)

{

iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));

/* rename any peripherals used differing from the s3c2410 */

s3c_device_sdi.name = "s3c2440-sdi"; // 重命名为s3c2440-sdi

s3c_device_i2c0.name = "s3c2440-i2c";

s3c_device_nand.name = "s3c2440-nand";

s3c_device_usbgadget.name = "s3c2440-usbgadget";

}

理解了吧?

接下来讲sd驱动的加载:


//---------------------------- drivers/mmc/host/s3cmci.c ----------------------------//

static struct platform_device_id s3cmci_driver_ids[] = {

{

.name = "s3c2410-sdi",

.driver_data = 0,

}, {

.name = "s3c2412-sdi",

.driver_data = 1,

}, {

.name = "s3c2440-sdi",

.driver_data = 1, // 下面会用到!!!

},

{ }

};

static struct platform_driver s3cmci_driver = {

.driver = {

.name = "s3c-sdi",

.owner = THIS_MODULE,

.pm = s3cmci_pm_ops,

},

.id_table = s3cmci_driver_ids,

.probe = s3cmci_probe,

.remove = __devexit_p(s3cmci_remove),

.shutdown = s3cmci_shutdown,

};

static int __init s3cmci_init(void)

{

return platform_driver_register(&s3cmci_driver);

}

module_init(s3cmci_init);

驱动和设备匹配上的话,就会调用驱动的probe函数:

static int __devinit s3cmci_probe(struct platform_device *pdev)

{

struct s3cmci_host *host;

struct mmc_host *mmc;

is2440 = platform_get_device_id(pdev)->driver_data; // 是否是2440, 这里就用到上面提到的driver_data,

mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev); // 分配mmc_host结构体

for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) { // SDCLK SDCMD DATA0~DATA3

ret = gpio_request(i, dev_name(&pdev->dev)); // 申请gpio资源

if (ret) {

dev_err(&pdev->dev, "failed to get gpio %dn", i);

for (i--; i >= S3C2410_GPE(5); i--)

gpio_free(i);

goto probe_free_host;

}

}

host = mmc_priv(mmc); // 获取private域

host->mmc = mmc;

host->pdev = pdev;

host->is2440 = is2440;

host->pdata = pdev->dev.platform_data; // 即上面提到的mini2440_mmc_cfg

if (!host->pdata) {

pdev->dev.platform_data = &s3cmci_def_pdata;

host->pdata = &s3cmci_def_pdata;

}

if (is2440) {

host->sdiimsk = S3C2440_SDIIMSK;

host->sdidata = S3C2440_SDIDATA;

host->clk_div = 1;

} else {

host->sdiimsk = S3C2410_SDIIMSK;

host->sdidata = S3C2410_SDIDATA;

host->clk_div = 2;

}

// 申请内存

host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); // 这里会读取IORESOURCE_MEM域

host->mem = request_mem_region(host->mem->start,

resource_size(host->mem), pdev->name);

host->base = ioremap(host->mem->start, resource_size(host->mem));

host->irq = platform_get_irq(pdev, 0); // 这里会读取IORESOURCE_IRQ域, 返回start地址

if (host->irq == 0) {

dev_err(&pdev->dev, "failed to get interrupt resouce.n");

ret = -EINVAL;

goto probe_iounmap;

}

// 申请中断,该中断为读写SD卡数据时所产生的中断

if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) {

dev_err(&pdev->dev, "failed to request mci interrupt.n");

ret = -ENOENT;

goto probe_iounmap;

}

// 禁止上面所申请的中断

disable_irq(host->irq);

host->irq_state = false;

if (!host->pdata->no_detect) { // 如果SD控制器具有检测SD卡插拔状态的功能

ret = gpio_request(host->pdata->gpio_detect, "s3cmci detect"); // 申请插入检测io

host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);

if (host->irq_cd >= 0) {

if (request_irq(host->irq_cd, s3cmci_irq_cd, // 注册插入检测中断处理函数, 申请中断,当有SD卡插入或拔出时,则进入该中断

IRQF_TRIGGER_RISING |

IRQF_TRIGGER_FALLING,

DRIVER_NAME, host)) {

dev_err(&pdev->dev,

"can't get card detect irq.n");

ret = -

[1] [2] [3]
mini2440sd卡加载过程

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机CO2检测显示程序解析