搜索

430

主题

515

帖子

2134

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2134
QQ
发表于 2020-11-3 20:03:44 6070 浏览 0 回复

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:
  1. 在$(project).dts文件的末尾增加spi device,example:在spi0上增加device

  2. &spi0{
  3.     #address-cells = <1>;
  4.     #size-cells = <0>;
  5.     test_spi{
  6.         compatible = "test_spi_device";    /*set spi->modalias  must*/
  7.         reg = <0>;    /*set spi->chip_select must*/
  8.         spi-max-frequency = <1000000>;    /*set spi->max_speed_hz must*/
  9.         /*other infromation*/
  10.         /*spi-cpha;*/    /*set cpha=1, optional*/
  11.         /*spi-cpol;*/    /*set cpol=1, optional*/
  12.         /*spi-cs-high;*/    /*set cs active level=1, optional*/
  13.         /*spi-3wire;*/    /*set no-tx or no-rx, optional*/
  14.         /*spi-lsb-first;*/    /*set lsb-first transfer, optional*/
  15.     };
  16. };
复制代码

Step2:添加 spi driver
  1. 在driver中添加spi_driver,example:

  2. #if defined(CONFIG_OF)
  3. static struct of_device_id test_match_table[] = {
  4.     {.compatible = "test_spi_device",},    /*与devicetree中的spi device的compatible一致*/
  5.     {},
  6. };
  7. #endif
  8. static struct spi_driver spi_test_driver = {
  9.     .driver = {
  10.         .name = "test_spi",
  11.         .owner = THIS_MODULE,
  12. #if defined(CONFIG_OF)
  13.         .of_match_table = test_match_table,
  14. #endif
  15.     },
  16.     .probe = spi_test_probe,
  17.     .remove = spi_test_remove,
  18.     //...
  19. };
复制代码


Step3:配置spi的参数
在driver中配置spi的传输参数,example:
  1. #include <mt_spi.h>
  2. int spi_set_para(struct spi_device *spidev)
  3. {
  4.     struct mt_chip_conf *chip_config = NULL;
  5.      
  6.     if(spidev == NULL){
  7.         pr_err("%s  spidev is null.\n", __func__);
  8.         return -EINVAL;
  9.     }
  10.     chip_config = (struct mt_chip_conf *)spidev->controller_data;
  11.     if(chip_config == NULL){
  12.         pr_err("%s  chip_config is null.\n", __func__);
  13.         return -EINVAL;
  14.     }
  15.     spi_bus_lock(spidev->master);    // lock bus
  16.     /*****这里修改设定您想要修改的参数*****/
  17.     chip_config->setuptime = 3;              /*传输开始时cs信号的setup时间(cs开始 -> clk开始)*/
  18.     chip_config->holdtime = 3;               /*传输结束后cs信号的保持时间(clk停止 -> cs停止)*/
  19.     chip_config->high_time = 10;         /*clk高电平持续时间*/
  20.     chip_config->low_time = 10;              /*clk低电平持续时间*/
  21.     chip_config->cs_idletime = 2;            /*cs空闲时间*/
  22.     chip_config->ulthgh_thrsh = 0;           /*未使用*/
  23.     chip_config->cs_pol = 0;             /*cs有效电平*/
  24.     chip_config->sample_sel = 0;         /**/
  25.     chip_config->cpol = 0;                   /*clk空闲时的电平*/
  26.     chip_config->cpha = 1;                   /*mosi/miso的采样点(0:前沿; 1:后沿)*/
  27.     chip_config->rx_mlsb = 1;                /*rx是否高位先发送(1:先发msb; 0:先发lsb)*/
  28.     chip_config->tx_mlsb = 1;                /*tx是否高位先发送(1:先发msb; 0:先发lsb)*/
  29.     chip_config->tx_endian = 0;              /*tx发送数据的端序(仅DMA mode有效)*/
  30.     chip_config->rx_endian = 0;              /*rx发送数据的端序(仅DMA mode有效)*/
  31.     chip_config->com_mod = DMA_TRANSFER; /*传输mode: FIFO_TRANSFER  or  DMA_TRANSFER*/
  32.     chip_config->pause = 0;                  /*是否开启pause mode(1:enable; 0:disable)*/
  33.     chip_config->finish_intr = 1;            /*是否打开传输完成的中断(1:打开; 0:不打开, code默认是打开的)*/
  34.     chip_config->deassert = 0;               /*是否使用deassert mode,一般不使用*/
  35.     chip_config->ulthigh = 0;                /*未使用*/
  36.     chip_config->tckdly = 0;             /*一般设置为0*/
  37.     /*end*/
  38.      
  39.     spi_setup(spidev);
  40.     spi_bus_unlock(spidev->master);    // unlock bus
  41.      
  42.     return 0;
  43. }
复制代码



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.



手机微信同号:13682654092
回复

使用道具 举报

返回列表
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


登录或注册
快速回复 返回顶部 返回列表