[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技術資料,可檢視新移科技官網網站-技術論壇。