日期:2014-05-16 浏览次数:20764 次
我的经历:
看了某些大神的说明,我胆怯地进入了drivers/mmc/host/,看过我之前的文章知道我用的是s3c2440。
看驱动时,我首先会找s3c字样,于是我注意到sdhci-s3c.c和s3cmci.c。
看了一下Kconfig
config MMC_S3C
tristate "Samsung S3C SD/MMC Card Interface support"
depends on ARCH_S3C2410
help
This selects a driver for the MCI interface found in
Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
If you have a board based on one of those and a MMC/SD
slot, say Y or M here.
If unsure, say N.
再看Makefile
obj-$(CONFIG_MMC_S3C) += s3cmci.o
我想我用s3cmci就可以了。我就猜测s3cmci和sdhci-s3c就是寄存器不一样。但是当我看了看代码,不是这样。
记得大神说过struct mmc_host。sd驱动用到的主要结构,但是sdhci-s3c用到的是struct sdhci_host。
这是什么情况。
首先我就考虑sdhci到底是什么,我看所有sdhci-*.c驱动都用到了sdhci.c,我看到sdhci.c对寄存器操作的偏移都
是一样的,这样我想到了usb的ochi驱动。应该有个sd控制器都遵循的协议。
然后我又打开了s3c6410的datasheet
第一行 SD Standard Host很耀眼。最后我在百度找的了这个:
Part_A2_SD_Host_Controller_Simplified_Specification_Ver2.00.pdf
这个就是所说的协议,sdhci.c要实现的东西。s3c2440并不遵循这个。
先看看sdhci吧,看c之前先看.h文件分析
/* * linux/include/linux/mmc/sdhci.h - Secure Digital Host Controller Interface * * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. */ #ifndef LINUX_MMC_SDHCI_H #define LINUX_MMC_SDHCI_H #include <linux/scatterlist.h> #include <linux/compiler.h> #include <linux/types.h> #include <linux/io.h> #include <linux/mmc/host.h> struct sdhci_host { /* Data set by hardware interface driver */ const char *hw_name; /* Hardware bus name */ //硬件总线名 unsigned int quirks; /* Deviations from spec. */ //偏离规范 //我们看有哪些怪癖,还有代码会如何处理 /* Controller doesn't honor resets unless we touch the clock register */ #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) /* SDHCI_QUIRK_CLOCK_BEFORE_RESET 是有的要在复位前设置时钟寄存器 会在复位前调用host->ops->set_clock(host, clock);驱动提供 */ /* Controller has bad caps bits, but really supports DMA */ #define SDHCI_QUIRK_FORCE_DMA (1<<1) /* if (host->quirks & SDHCI_QUIRK_FORCE_DMA) host->flags |= SDHCI_USE_SDMA; 就是支持SDMA */ /* Controller doesn't like to be reset when there is no card inserted. */ #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) /* 上面英文已说的很清楚: 没有卡插入时,控制器不想复位。 在复位时遇到这个标准,会想尝试读当前的状态,成功返回,失败进行复位。 */ /* Controller doesn't like clearing the power reg before a change */ #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) /* 控制器不想清除电源寄存器在一个改变MMC_VDD前。 遇到这个,直接改电源寄存器值,不清除。 */ /* Controller has flaky internal state so reset it on each ios change */ #define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) /* 在sdhci_do_set_ios()中会用到。 解释: 有些控制器在一些操作时会发疯,即使是CMD0,解决方法就是复位每一个ios. */ /* Controller has an unusable DMA engine */ #define SDHCI_QUIRK_BROKEN_DMA (1<<5) //控制器有一个无法使用的DMA引擎 //SDMA: secure DMA //ADMA: advanced DMA /* Controller has an unusable ADMA engine */ #define SDHCI_QUIRK_BROKEN_ADMA (1<<6) //控制器有一个无法使用的ADMA引擎 /* Controller can only DMA from 32-bit aligned addresses */ #define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<7) //DMA要32位地址对齐 /* Controller can only DMA chunk sizes that are a multiple of 32 bits */ #define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<8) //DMA的大小是32的倍数 /* Controller can only ADMA chunks that are a multiple of 32 bits */ #define SDHCI_QUIRK_32BIT_ADMA_SIZE (1<<9) //ADMA的大小