天天看點

MTK 驅動 Kernel-3.18中如何配置和使用spi

[DESCRIPTION]

(1)kernel-3.18中使用了device tree機制,可以通過device tree來配置spi device。

(2)使用DMA 方式傳輸時,需要正确申請buffer,才能傳輸成功。

[SOLUTION]

kernel-3.18中使用 spi 的步驟:

Step1:添加 spi device:

在$(project).dts檔案的末尾增加spi device,example:在spi0上增加device

 &spi0{

    #address-cells = <1>;

    #size-cells = <0>;

    test_spi{

        compatible = "test_spi_device";    /*set spi->modalias  must*/

        reg = <0>;    /*set spi->chip_select must*/

        spi-max-frequency = <1000000>;    /*set spi->max_speed_hz must*/

        /*other infromation*/

        /*spi-cpha;*/    /*set cpha=1, optional*/

        /*spi-cpol;*/    /*set cpol=1, optional*/

        /*spi-cs-high;*/    /*set cs active level=1, optional*/

        /*spi-3wire;*/    /*set no-tx or no-rx, optional*/

        /*spi-lsb-first;*/    /*set lsb-first transfer, optional*/

    };

};

Step2:添加 spi driver

在driver中添加spi_driver,example:

#if defined(CONFIG_OF)

static struct of_device_id test_match_table[] = {

    {.compatible = "test_spi_device",},    /*與devicetree中的spi device的compatible一緻*/

    {},

};

#endif

static struct spi_driver spi_test_driver = {

    .driver = {

        .name = "test_spi",

        .owner = THIS_MODULE,

#if defined(CONFIG_OF)

        .of_match_table = test_match_table,

#endif

    },

    .probe = spi_test_probe,

    .remove = spi_test_remove,

    //...

};

Step3:配置spi的參數

在driver中配置spi的傳輸參數,example:

#include <mt_spi.h>

int spi_set_para(struct spi_device *spidev)

{

    struct mt_chip_conf *chip_config = NULL;

    if(spidev == NULL){

        pr_err("%s  spidev is null.\n", __func__);

        return -EINVAL;

    }

    chip_config = (struct mt_chip_conf *)spidev->controller_data;

    if(chip_config == NULL){

        pr_err("%s  chip_config is null.\n", __func__);

        return -EINVAL;

    }

    spi_bus_lock(spidev->master);    // lock bus

    /*****這裡修改設定您想要修改的參數*****/

    chip_config->setuptime = 3;              /*傳輸開始時cs信号的setup時間(cs開始 -> clk開始)*/

    chip_config->holdtime = 3;               /*傳輸結束後cs信号的保持時間(clk停止 -> cs停止)*/

    chip_config->high_time = 10;         /*clk高電平持續時間*/

    chip_config->low_time = 10;              /*clk低電平持續時間*/ 

    chip_config->cs_idletime = 2;            /*cs空閑時間*/

    chip_config->ulthgh_thrsh = 0;           /*未使用*/

    chip_config->cs_pol = 0;             /*cs有效電平*/

    chip_config->sample_sel = 0;         /**/

    chip_config->cpol = 0;                   /*clk空閑時的電平*/

    chip_config->cpha = 1;                   /*mosi/miso的采樣點(0:前沿; 1:後沿)*/

    chip_config->rx_mlsb = 1;                /*rx是否高位先發送(1:先發msb; 0:先發lsb)*/

    chip_config->tx_mlsb = 1;                /*tx是否高位先發送(1:先發msb; 0:先發lsb)*/

    chip_config->tx_endian = 0;              /*tx發送資料的端序(僅DMA mode有效)*/

    chip_config->rx_endian = 0;              /*rx發送資料的端序(僅DMA mode有效)*/

    chip_config->com_mod = DMA_TRANSFER; /*傳輸mode: FIFO_TRANSFER  or  DMA_TRANSFER*/

    chip_config->pause = 0;                  /*是否開啟pause mode(1:enable; 0:disable)*/

    chip_config->finish_intr = 1;            /*是否打開傳輸完成的中斷(1:打開; 0:不打開, code預設是打開的)*/

    chip_config->deassert = 0;               /*是否使用deassert mode,一般不使用*/

    chip_config->ulthigh = 0;                /*未使用*/

    chip_config->tckdly = 0;             /*一般設定為0*/

    /*end*/

    spi_setup(spidev);

    spi_bus_unlock(spidev->master);    // unlock bus

    return 0;

}

Step4:使用spi傳輸

(1)FIFO mode

      a。将spi 參數設定為FIFO mode,

chip_config->com_mod = FIFO_TRANSFER;

b。然後使用linux标準的spi傳輸函數進行資料傳輸,一般使用 spi_sync().

int spi_sync(struct spi_device *spi, struct spi_message *message);

(2)DMA mode

a。将spi 參數設定為DMA mode,

chip_config->com_mod = DMA_TRANSFER;

b。申請buf,需要使用flag:  GFP_DMA

buf = kzalloc(buf_len, GFP_KERNEL | GFP_DMA);

c。然後使用linux标準的spi傳輸函數進行資料傳輸,一般使用 spi_sync().

Note:

(1) $(project) 是指工程名。example:evb6755_64。

(2)當使用DMA方式進行傳輸時,請将 spi_transfer中的tx_buf和rx_buf都設定上,不要設定為NULL.

更多MTKJ技術資料,可檢視新移科技官網網站-技術論壇。

繼續閱讀