硬件资源

 
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 <mach/lpc32xx_gpio.h>
27 #include "http://www.cnblogs.com/../arch/arm/mach-lpc32xx/sys-lpc32xx.h"
28 #include <mach/hardware.h>
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
posted on 2012-04-28 14:58  风行雪舞  阅读(897)  评论(0编辑  收藏  举报
无觅相关文章插件,快速提升流量