1. 程式人生 > >SPI協議及SDIO協議

SPI協議及SDIO協議

序列外設介面(SPI:Serial Peripheral interface)是一種串行同步通訊協議(同時讀入和寫出),由SDI(序列資料輸入),SDO(序列資料輸出),SCK(序列移位時鐘),CS(從使能訊號)四種訊號構成。CS 決定了唯一的與主裝置通訊的從裝置,如沒有CS 訊號,則只能存在一個從裝置,主裝置通過產生移位時鐘來發起通訊。
      主要影響SPI通訊的兩個引數是時鐘極性(CPOL)和時鐘相位(CPHA)兩個引數,SPI傳輸序列資料時首先傳輸最高位。時鐘極性(CPOL)對傳輸協議沒有重大的影響,如果CPOL=0,串行同步時鐘的空閒狀態為低電平;如果CPOL=1,串行同步時鐘的空閒狀態為高電平。時鐘相位(CPHA)能夠配置用於選擇兩種不同的傳輸協議之一進行資料傳輸,如果CPHA=0,在串行同步時鐘的第一個跳變沿(上升或下降)資料被取樣;如果CPHA=1,在串行同步時鐘的第二個跳變沿(上升或下降)資料被取樣。圖示如下:

                        

      一般的ARM系統對SPI的支援方式分三種:輪詢(POLLING),中斷(INTERRUPT,需要定義SPI的中斷號),和DMA(配置好SPI和DMA對應的暫存器,和DMA的源頭和目的地址,就可以開始進行DMA傳輸)。

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

      基於SDIO協議,SD卡的定義如下:

                                     

      它可以支援三種操作模式: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)即可。