Chinaunix首页 | 论坛 | 博客
  • 博客访问: 929914
  • 博文数量: 376
  • 博客积分: 154
  • 博客等级: 入伍新兵
  • 技术积分: 1558
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-13 08:42
文章分类

全部博文(376)

文章存档

2014年(11)

2013年(88)

2012年(260)

2011年(17)

分类:

2012-05-25 11:43:22

原文地址:SD Card Driver 作者:chenxibing008

硬件资源


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
阅读(2026) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~