MS_WP,SD_WP,SD卡写保护:GPI_09,驱动读取SD卡的写保护开关,进行不同操作;
MS_CD,SD_CD,插卡检测:GPI_04。(原理图的左边MS_CD和MS_WP写反了,以网络标号为准)
MS_PWR,SD_PWR,电源控制引脚,GPO_01,控制2SJ355。
驱动程序
写保护检测
GPI_09是单功能仅输入引脚,读取引脚状态,寄存器:P3_INP_STATE[9]。
代码:
103 u32 tmp;
104
105 tmp = __raw_readl(GPIO_P3_INP_STATE(GPIO_IOBASE)) & INP_STATE_GPI_09;
默认没有MMC写保护的代码,需要添加。mmc_platform_data数据结构的定义见:
./arch/arm/include/asm/mach/mmc.h
没有处理写保护之前插卡会出现如下提示:
mmc0: host does not support reading read-only switch. assuming write-enable.
信息从drivers/mmc/core/sd.c文件打印出来。
SD卡写保护状态的读取是host->ops->get_ro函数实现的。
下面的文件好像实现了get_ro函数:
[chenxibing@localhost linux-2.6.27.8]$ grep mmc_host_ops -R drivers/mmc/
drivers/mmc/host/imxmmc.c:static const struct mmc_host_ops imxmci_ops = {
drivers/mmc/host/wbsd.c:static const struct mmc_host_ops wbsd_ops = {
drivers/mmc/host/tifm_sd.c:static const struct mmc_host_ops tifm_sd_ops = {
drivers/mmc/host/sdricoh_cs.c:static struct mmc_host_ops sdricoh_ops = {
drivers/mmc/host/omap.c:static const struct mmc_host_ops mmc_omap_ops = {
drivers/mmc/host/pxamci.c:static const struct mmc_host_ops pxamci_ops = {
drivers/mmc/host/at91_mci.c:static const struct mmc_host_ops at91_mci_ops = {
drivers/mmc/host/s3cmci.c:static struct mmc_host_ops s3cmci_ops = {
drivers/mmc/host/mmci.c:static const struct mmc_host_ops mmci_ops = {
drivers/mmc/host/atmel-mci.c:static struct mmc_host_ops atmci_ops = {
drivers/mmc/host/sdhci.c:static const struct mmc_host_ops sdhci_ops = {
drivers/mmc/host/tmio_mmc.c:static struct mmc_host_ops tmio_mmc_ops = {
drivers/mmc/host/au1xmmc.c:static const struct mmc_host_ops au1xmmc_ops = {
drivers/mmc/host/mmc_spi.c: * beginning of an mmc_host_ops.request until the end. So beware
drivers/mmc/host/mmc_spi.c:static const struct mmc_host_ops mmc_spi_ops = {
OMAP1的MMC:
84 static struct omap_mmc_platform_data h3_mmc_data = {
85 .nr_slots = 1,
86 .switch_slot = NULL,
87 .init = h3_mmc_late_init,
88 .cleanup = h3_mmc_cleanup,
89 .slots[0] = {
90 .set_power = h3_mmc_set_power,
91 .set_bus_mode = h3_mmc_set_bus_mode,
92 .get_ro = NULL,
93 .get_cover_state = h3_mmc_get_cover_state,
94 .ocr_mask = MMC_VDD_28_29 | MMC_VDD_30_31 |
95 MMC_VDD_32_33 | MMC_VDD_33_34,
96 .name = "mmcblk",
97 },
98 };
omap_mmc_platform_data在 arch/arm/plat-omap/include/mach/mmc.h 文件中定义。
22 struct omap_mmc_platform_data {
23 struct omap_mmc_conf conf;
24
25 /* number of slots on board */
26 unsigned nr_slots:2;
27
28 /* set if your board has components or wiring that limits the
29 * maximum frequency on the MMC bus */
30 unsigned int max_freq;
31
32 /* switch the bus to a new slot */
33 int (* switch_slot)(struct device *dev, int slot);
34 /* initialize board-specific MMC functionality, can be NULL if
35 * not supported */
36 int (* init)(struct device *dev);
37 void (* cleanup)(struct device *dev);
38 void (* shutdown)(struct device *dev);
39
40 /* To handle board related suspend/resume functionality for MMC */
41 int (*suspend)(struct device *dev, int slot);
42 int (*resume)(struct device *dev, int slot);
43
44 struct omap_mmc_slot_data {
45 int (* set_bus_mode)(struct device *dev, int slot, int bus_mode);
46 int (* set_power)(struct device *dev, int slot, int power_on, int vdd);
47 int (* get_ro)(struct device *dev, int slot);
48
49 /* return MMC cover switch state, can be NULL if not supported.
50 *
51 * possible return values:
52 * 0 - open
53 * 1 - closed
54 */
55 int (* get_cover_state)(struct device *dev, int slot);
56
57 const char *name;
58 u32 ocr_mask;
59
60 /* Card detection IRQs */
61 int card_detect_irq;
62 int (* card_detect)(int irq);
63
64 unsigned int ban_openended:1;
65
66 } slots[OMAP_MMC_MAX_SLOTS];
67 };
LPC3250的SD/MMC采用abma_device结构描述:
475 struct amba_device mmc_device = {
476 .dev = {
477 .coherent_dma_mask = ~0,
478 .bus_id = "dev:31",
479 .platform_data = &lpc32xx_plat_data,
480 },
481 .res = {
482 .start = SD_BASE,
483 .end = (SD_BASE + SZ_4K - 1),
484 .flags = IORESOURCE_MEM,
485 },
486 .dma_mask = ~0,
487 .irq = {IRQ_SD0, IRQ_SD1},
488 };
amba_device结构在./include/linux/amba/bus.h 文件中定义,如下:
16 stuct amba_device {
17 struct device dev;
18 struct resource res;
19 u64 dma_mask;
20 unsigned int periphid;
21 int irq[AMBA_NR_IRQS];
22 };
LPC3250的Host不支持get_ro,无法检测SD卡是否写保护。
写保护实现
由于LPC3250的Host不支持get_ro,所以只好采取了更加直接的方法,直接修改drivers/mmc/core/sd.c文件,将其中检测SD卡是否写保护的函数进行修改:
499 /*
500 * Check if read-only switch is active.
501 */
502 if (!oldcard) {
503 #if defined(CONFIG_MACH_SMARTARM3250)
504 u32 tmp;
505
506 tmp = __raw_readl(GPIO_P3_INP_STATE(GPIO_IOBASE)) & INP_STATE_GPI_09;
507 if (tmp == 0) {
508 printk(KERN_WARNING "%s: in Read-Write mode\n", mmc_hostname(host));
509 } else {
510 mmc_card_set_readonly(card);
511 }
512 #else
513 if (!host->ops->get_ro || host->ops->get_ro(host) < 0) {
514 printk(KERN_WARNING "%s: host does not "
515 "support reading read-only "
516 "switch. assuming write-enable.\n",
517 mmc_hostname(host));
518 } else {
519 if (host->ops->get_ro(host) > 0)
520 mmc_card_set_readonly(card);
521 }
522 #endif
523 }
当然,需要增加一些必要的头文件:
25 #if defined(CONFIG_MACH_SMARTARM3250)
26 #include
27 #include "../../../arch/arm/mach-lpc32xx/sys-lpc32xx.h"
28 #include
29 #endif
插卡检测
GPI_04是单功能仅输入引脚,寄存器P3_INP_STATE[4]。
代码:__raw_readl(GPIO_P3_INP_STATE(GPIO_IOBASE)) & INP_STATE_GPI_04;
电源控制
GPO_01是单功能仅输出引脚,寄存器P3_OUTP_SET[1]和P3_OUTP_CLR[1]。
代码:
144 __raw_writel(OUTP_STATE_GPO(1), GPIO_P3_OUTP_CLR(GPIO_IOBASE));
148 __raw_writel(OUTP_STATE_GPO(1), GPIO_P3_OUTP_SET(GPIO_IOBASE));
操作信息
写保护后插卡,挂在后创建目录:
[root@nxp root]# mmc0: new SD card at address e624
mmcblk0: mmc0:e624 SD01G 992000KiB (ro)
mmcblk0:
[root@nxp root]# mount -t vfat /dev/mmcblk0 /mnt/
[root@nxp root]# mkdir /mnt/abing8
mkdir: cannot create directory '/mnt/abing8': Read-only file system
[root@nxp root]# umount /mnt/
[root@nxp root]#
将卡拔出,去掉写保护,再次插入,并挂载和创建目录:
mmc0: card e624 removed
mmc0: in Read-Write mode
mmc0: new SD card at address e624
mmcblk0: mmc0:e624 SD01G 992000KiB
mmcblk0:
[root@nxp root]# mount -t vfat /dev/mmcblk0 /mnt/
[root@nxp root]# mkdir /mnt/abing8
[root@nxp root]# umount /mnt/
再次查看:
[root@nxp root]# mount -t vfat /dev/mmcblk0 /mnt/
[root@nxp root]# ls /mnt/
3250serial.exe abing8 nk2.bin