SPI协议及SDIO协议

(1)串行外设接口(SPI:Serial Peripheral interface)是一种串行同步通讯协议(同时读入和写出),由SDI(串行数据输入),SDO(串行数据输出),SCK(串行移位时钟),CS(从使能信号)四种信号构成。CS 决定了唯一的与主设备通信的从设备,如没有CS 信号,则只能存在一个从设备,主设备通过产生移位时钟来发起通讯。
       主要影响SPI通讯的两个参数是时钟极性(CPOL)和时钟相位(CPHA)两个参数,SPI传输串行数据时首先传输最高位。时钟极性(CPOL)对传输协议没有重大的影响,如果CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输,如果CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。图示如下:

                                                       SPI协议及SDIO协议_第1张图片

        一般的ARM系统对SPI的支持方式分三种:轮询(POLLING),中断(INTERRUPT,需要定义SPI的中断号),和DMA(配置好SPI和DMA对应的寄存器,和DMA的源头和目的地址,就可以开始进行DMA传输)。

(2)基于SDIO协议,SD卡的定义如下:

                                                                                              SPI协议及SDIO协议_第2张图片

上图是以CD/DAT3的复用来实现卡检测功能,其实CD可以以单独的GPIO中断来实现,但本质上CD是可有可无的,因为很多应用场合并不需要支持SD热插拔。至于SD唤醒系统,也是由GPIO中断来实现,也可以定义数据线中断来实现(如果SDIO数据线协议支持的话)。

       SDIO协议可以支持三种操作模式:SPI,SD一线,SD四线(接口通过寄存器来配置)。SPI速度较低,一线或者四线需要寄存器来选择,高速模式下需要四线支持。其中DAT是数据线,一线模式下默认用DAT0;CMD线上传输串行命令,可以是单机寻址或者广播命令。

=================================================================================================================

        6410平台对SD卡的支持,表现在CH0(CH1被用来连接WIFI,和CH0共一个DETECT脚,即XmmcCDN0),添加HSMMC设备,分配对应资源即可。

(1)

static struct platform_device *smdk6410_devices[] __initdata = {

........

&s3c_device_hsmmc0,

........

}

定义如下:

struct platform_device s3c_device_hsmmc0 = {
        .name  = "s3c-sdhci",
        .id  = 0,
        .num_resources = ARRAY_SIZE(s3c_hsmmc_resource),
        .resource = s3c_hsmmc_resource,
        .dev  = {
                  .dma_mask  = &s3c_device_hsmmc_dmamask,
                  .coherent_dma_mask = 0xffffffffUL,
                  .platform_data  = &s3c_hsmmc0_def_platdata,
           },
};

调用如下:

static u64 s3c_device_hsmmc_dmamask = 0xffffffffUL;

struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
         .max_width = 4,
         .host_caps = (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED |
    MMC_CAP_SD_HIGHSPEED),
};

(2)

完善s3c_hsmmc0_def_platdata 的配置,在

static inline void s3c6410_default_sdhci0(void)
{
     s3c_hsmmc0_def_platdata.clocks = s3c6410_hsmmc_clksrcs;
     s3c_hsmmc0_def_platdata.cfg_gpio = s3c6410_setup_sdhci0_cfg_gpio;
     s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card;
}

在s3c6410_setup_sdhci0_cfg_gpio这个函数中,对XmmcCDN0进行了配置,使其只能单独用在MMC0或MMC1,此处用在MMC0上检测SD卡的热插拔:

       s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
       s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));

对应的在s3c6410_setup_sdhci1_cfg_gpio里面就要屏蔽掉这些东西。

      补充:在函数void s3c6410_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)中的width参数是用来配置1线还是4线模式的。在最开始的时候,mmc控制器不知道是什么卡,所以传进来的width就是1,这样就只初始化cmd和clk,仅仅保证可以识别出来,在识别出卡的类型后在传具体的width进来,比如4或者1来配置。这个过程在sdhci-s3c-sdio.c中。

(3)

以上是platform device,则dirver在sdhci-s3c.c调用如下:

static struct platform_driver sdhci_s3c_driver = {
          .probe  = sdhci_s3c_probe,
          .suspend = sdhci_s3c_suspend,
          .resume  = sdhci_s3c_resume,
          .remove  = __devexit_p(sdhci_s3c_remove),
          .driver  = {
                   .owner = THIS_MODULE,
                   .name = "s3c-sdhci",
             },
};

在初始化模块时用platform_driver_register(&sdhci_s3c_driver)即可

你可能感兴趣的:(SPI协议及SDIO协议)