在freescale mx6q平台上添加spi资源

1:配置管脚为SPI功能

在board-mx6q_sabresd.h的最后添加,复制被重定义

(以添加SPI2为例)

       

[cpp] view plaincopy
 
  1. <span style="font-size:18px;">        MX6Q_PAD_EIM_CS0__ECSPI2_SCLK,  
  2.         MX6Q_PAD_EIM_CS1__ECSPI2_MOSI,  
  3.         MX6Q_PAD_EIM_OE__ECSPI2_MISO,  
  4.         MX6Q_PAD_CSI0_DAT11__ECSPI2_SS0 ,  
  5. </span>  


之后再板级文件board-mx6q_sabresd.c中将有相关函数对管脚进行统一初始化。

完成寄存器配置的工作。

[cpp] view plaincopy
 
  1. <span style="font-size:18px;">  mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_pads,  
  2.         ARRAY_SIZE(mx6q_sabresd_pads));  
  3.   
  4.     mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_cstm_tq_pads,  
  5.         ARRAY_SIZE(mx6q_sabresd_cstm_tq_pads));</span>  

2:在板级文件board-mx6q_sabresd.c中添加以下代码

将匹配到driver/spi/spidev.c文件中的驱动源码

2.1完成SPI master的注册

SPI2片选管脚宏定义:

[cpp] view plaincopy
 
  1. <span style="font-size:14px;">#define SABRESD_ECSPI2_CS0 IMX_GPIO_NR(5, 29)</span>  


添加相关结构体

[cpp] view plaincopy
 
  1. <span style="font-size:14px;">static int mx6q_marsboard_spi1_cs[] = {  
  2.         SABRESD_ECSPI2_CS0,  
  3. };  
  4. </span>  


 

[cpp] view plaincopy
 
  1. <span style="font-size:14px;">static const struct spi_imx_master mx6q_sabresd_spi2_data __initconst = {  
  2.         .chipselect = mx6q_marsboard_spi2_cs,  
  3.         .num_chipselect = ARRAY_SIZE(mx6q_marsboard_spi1_cs),  
  4. };  
  5. </span>  


 

2.2在spi 总线上匹配spi2的驱动文件

mx6q平台有2路spi资源,0/1,其中的bus_num则为挂载驱动的总线选择。

[cpp] view plaincopy
 
  1. <span style="font-size:18px;"><span style="font-size:14px;">static struct mtd_partition imx6_sabrelite_spi_nor_partitions[] = {  
  2.  {  
  3.   .name = "bootloader",  
  4.   .offset = 0,  
  5.   .size = 0x00100000,  
  6.  },  
  7.  {  
  8.   .name = "kernel",  
  9.   .offset = MTDPART_OFS_APPEND,  
  10.   .size = MTDPART_SIZ_FULL,  
  11.  },  
  12. };  
  13.   
  14.   
  15. static struct flash_platform_data imx6_sabrelite__spi_flash_data = {  
  16.  .name = "spidev",  / /匹配原则。  
  17.  .parts = imx6_sabrelite_spi_nor_partitions,  
  18.  .nr_parts = ARRAY_SIZE(imx6_sabrelite_spi_nor_partitions),  
  19.  .type = "sst25vf016b",  
  20. };  
  21.   
  22.   
  23.   
  24.   
  25. static struct spi_board_info imx6_sabrelite_spi_nor_device[] __initdata = {  
  26.  {  
  27.   .modalias = "spidev",  
  28.   .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */  
  29.   .bus_num = 1,    //设备挂载第几号spi总线上  
  30.   .chip_select = 0,  
  31.   .platform_data = &imx6_sabrelite__spi_flash_data,  
  32.  },  
  33. };  
  34.   
  35.   
  36. spi_register_board_info(imx6_sabrelite_spi_nor_device,  
  37. ARRAY_SIZE(imx6_sabrelite_spi_nor_device));  
  38.   
  39. imx6q_add_ecspi(0, &mx6q_sabrelite_spi2_data);  
  40.   
  41.   
  42.   
  43.   
  44.   
  45.   
  46. </span>   
  47. </span>  

3:内核配置

查看spidev.c文件目录下的Kconfig以及Makefile得知内核驱动的添加方法

选择蓝色部分选项,将spidev.c文件添加到内核中。

4:查看开发板/sys/bus/spi/drivers/spidev目录

在/dev下生成设备文件/dev/spidev1.0

5:使用freescale官方的bsp包中的spi测试程序对接口进行测试

[cpp] view plaincopy
 
  1. <span style="font-size:12px;">/* 
  2.  * SPI testing utility (using spidev driver) 
  3.  * 
  4.  * Copyright (c) 2007  MontaVista Software, Inc. 
  5.  * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com> 
  6.  * 
  7.  * This program is free software; you can redistribute it and/or modify 
  8.  * it under the terms of the GNU General Public License as published by 
  9.  * the Free Software Foundation; either version 2 of the License. 
  10.  * 
  11.  * Cross-compile with cross-gcc -I/path/to/cross-kernel/include 
  12.  */  
  13.   
  14. #include <stdint.h>  
  15. #include <unistd.h>  
  16. #include <stdio.h>  
  17. #include <stdlib.h>  
  18. #include <getopt.h>  
  19. #include <fcntl.h>  
  20. #include <sys/ioctl.h>  
  21. #include <linux/types.h>  
  22. #include <linux/spi/spidev.h>  
  23.   
  24. #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))  
  25.   
  26. static void pabort(const char *s)  
  27. {  
  28.     perror(s);  
  29.     abort();  
  30. }  
  31.   
  32. static const char *device = "/dev/spidev1.0";  
  33. static uint8_t mode;  
  34. static uint8_t bits = 8;  
  35. static uint32_t speed = 500000;  
  36. static uint16_t delay;  
  37.   
  38. static void transfer(int fd)  
  39. {  
  40.     int ret;  
  41.     uint8_t tx[] = {  
  42.         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
  43.         0x40, 0x00, 0x00, 0x00, 0x00, 0x95,  
  44.         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
  45.         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
  46.         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
  47.         0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,  
  48.         0xF0, 0x0D,  
  49.     };  
  50.     uint8_t rx[ARRAY_SIZE(tx)] = {0, };  
  51.     struct spi_ioc_transfer tr = {  
  52.         .tx_buf = (unsigned long)tx,  
  53.         .rx_buf = (unsigned long)rx,  
  54.         .len = ARRAY_SIZE(tx),  
  55.         .delay_usecs = delay,  
  56.         .speed_hz = speed,  
  57.         .bits_per_word = bits,  
  58.     };  
  59.   
  60.     ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);  
  61.     if (ret < 1)  
  62.         pabort("can't send spi message");  
  63.   
  64.     for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {  
  65.         if (!(ret % 6))  
  66.             puts("");  
  67.         printf("%.2X ", rx[ret]);  
  68.     }  
  69.     puts("");  
  70. }  
  71.   
  72.   
  73. int main(int argc, char *argv[])  
  74. {  
  75.     int ret = 0;  
  76.     int fd;  
  77.   
  78.     //parse_opts(argc, argv); /* for what ,unknow*/  
  79.   
  80.     fd = open(device, O_RDWR);  
  81.     if (fd < 0)  
  82.         pabort("can't open device");  
  83.   
  84.     /* 
  85.      * spi mode 
  86.      */  
  87.     ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);  
  88.     if (ret == -1)  
  89.         pabort("can't set spi mode");  
  90.   
  91.     ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);  
  92.     if (ret == -1)  
  93.         pabort("can't get spi mode");  
  94.   
  95.     /* 
  96.      * bits per word 
  97.      */  
  98.     ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);  
  99.     if (ret == -1)  
  100.         pabort("can't set bits per word");  
  101.   
  102.     ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);  
  103.     if (ret == -1)  
  104.         pabort("can't get bits per word");  
  105.   
  106.     /* 
  107.      * max speed hz 
  108.      */  
  109.     ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);  
  110.     if (ret == -1)  
  111.         pabort("can't set max speed hz");  
  112.   
  113.     ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);  
  114.     if (ret == -1)  
  115.         pabort("can't get max speed hz");  
  116.   
  117.     printf("spi mode: %d ", mode);  
  118.     printf("bits per word: %d ", bits);  
  119.     printf("max speed: %d Hz (%d KHz) ", speed, speed/1000);  
  120.   
  121.     transfer(fd);  
  122.   
  123.     close(fd);  
  124.   
  125.     return ret;  
  126. }  
  127. </span>  


 

执行应用程序,可以看到时序模式(spi 4种时序模式第0种),时钟频率等参数。

7    /*
8     * SPI testing utility (using spidev driver)
9     *
10     * Copyright (c) 2007  MontaVista Software, Inc.
11     * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
12     *
13     * This program is free software; you can redistribute it and/or modify
14     * it under the terms of the GNU General Public License as published by
15     * the Free Software Foundation; either version 2 of the License.
16     *
17     * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
18     */
19    
20    #include <stdint.h>
21    #include <unistd.h>
22    #include <stdio.h>
23    #include <stdlib.h>
24    #include <getopt.h>
25    #include <fcntl.h>
26    #include <sys/ioctl.h>
27    #include <linux/types.h>
28    #include <linux/spi/spidev.h>
29    
30    #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
31    
32    static void pabort(const char *s)
33    {
34        perror(s);
35        abort();
36    }
37    
38    static const char *device = "/dev/spidev1.0";
39    static uint8_t mode;
40    static uint8_t bits = 8;
41    static uint32_t speed = 9000000;
42    static uint16_t delay=0;
43    
44    static void transfer(int fd)
45    {
46        int ret;
47        uint8_t tx[] = {
48            0x11, 0x12, 0x18, 0x78, 0x24, 0xa2,
49            0x40, 0x00, 0x13, 0x00, 0x00, 0x95,
50            0x23, 0x56, 0x54, 0x34, 0x45, 0x65,
51            0x69, 0x78, 0x98, 0xFF, 0xFF, 0x36,
52        };
53        uint8_t rx[ARRAY_SIZE(tx)] = {0, };
54        struct spi_ioc_transfer tr = {
55            .tx_buf = (unsigned long)tx,
56            .rx_buf = (unsigned long)rx,
57            .len = ARRAY_SIZE(tx),
58            .delay_usecs = delay,
59            .speed_hz = speed,
60            .bits_per_word = bits,
61            .cs_change=1
62        };
63    
64        ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
65        if (ret < 1)
66            pabort("can't send spi message");
67    
68        for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
69            if (!(ret % 6))
70                puts("");
71            printf("%.2X ", rx[ret]);
72        }
73        puts("");
74    }
75    
76    static void print_usage(const char *prog)
77    {
78        printf("Usage: %s [-DsbdlHOLC3]
", prog);
79        puts("  -D --device   device to use (default /dev/spidev1.0)
"
80             "  -s --speed    max speed (Hz)
"
81             "  -d --delay    delay (usec)
"
82             "  -b --bpw      bits per word 
"
83             "  -l --loop     loopback
"
84             "  -H --cpha     clock phase
"
85             "  -O --cpol     clock polarity
"
86             "  -L --lsb      least significant bit first
"
87             "  -C --cs-high  chip select active high
"
88             "  -3 --3wire    SI/SO signals shared
");
89        exit(1);
90    }
91    
92    static void parse_opts(int argc, char *argv[])
93    {
94        while (1) {
95            static const struct option lopts[] = {
96                { "device",  1, 0, 'D' },
97                { "speed",   1, 0, 's' },
98                { "delay",   1, 0, 'd' },
99                { "bpw",     1, 0, 'b' },
100                { "loop",    0, 0, 'l' },
101                { "cpha",    0, 0, 'H' },
102                { "cpol",    0, 0, 'O' },
103                { "lsb",     0, 0, 'L' },
104                { "cs-high", 0, 0, 'C' },
105                { "3wire",   0, 0, '3' },
106                { "no-cs",   0, 0, 'N' },
107                { "ready",   0, 0, 'R' },
108                { NULL, 0, 0, 0 },
109            };
110            int c;
111    
112            c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
113    
114            if (c == -1)
115                break;
116    
117            switch (c) {
118            case 'D':
119                device = optarg;
120                break;
121            case 's':
122                speed = atoi(optarg);
123                break;
124            case 'd':
125                delay = atoi(optarg);
126                break;
127            case 'b':
128                bits = atoi(optarg);
129                break;
130            case 'l':
131                mode |= SPI_LOOP;
132                break;
133            case 'H':
134                mode |= SPI_CPHA;
135                break;
136            case 'O':
137                mode |= SPI_CPOL;
138                break;
139            case 'L':
140                mode |= SPI_LSB_FIRST;
141                break;
142            case 'C':
143                mode |= SPI_CS_HIGH;
144                break;
145            case '3':
146                mode |= SPI_3WIRE;
147                break;
148            case 'N':
149                mode |= SPI_NO_CS;
150                break;
151            case 'R':
152                mode |= SPI_READY;
153                break;
154            default:
155                print_usage(argv[0]);
156                break;
157            }
158        }
159    }
160    
161    int main(int argc, char *argv[])
162    {
163        int ret = 0;
164        int fd;
165    
166        parse_opts(argc, argv);
167    
168        fd = open(device, O_RDWR);
169        if (fd < 0)
170            pabort("can't open device");
171    
172        /*
173         * spi mode
174         */
175        ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
176        if (ret == -1)
177            pabort("can't set spi mode");
178    
179        ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
180        if (ret == -1)
181            pabort("can't get spi mode");
182    
183        /*
184         * bits per word
185         */
186        ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
187        if (ret == -1)
188            pabort("can't set bits per word");
189    
190        ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
191        if (ret == -1)
192            pabort("can't get bits per word");
193    
194        /*
195         * max speed hz
196         */
197        ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
198        if (ret == -1)
199            pabort("can't set max speed hz");
200    
201        ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
202        if (ret == -1)
203            pabort("can't get max speed hz");
204    
205        printf("spi mode: %d
", mode);
206        printf("bits per word: %d
", bits);
207        printf("max speed: %d Hz (%d KHz)
", speed, speed/1000);
208    
209        transfer(fd);
210    
211        close(fd);
212    
213        return ret;
214    }
原文地址:https://www.cnblogs.com/subo_peng/p/4837372.html