µ±Ç°Î»ÖãºÖ÷Ò³ > ²é¿´ÄÚÈÝ

LinuxÏÂSPIÇý¶¯Ïê½â£¨¸É»õ£©

·¢²¼Ê±¼ä£º2021-04-27 00:00| ÓРλÅóÓѲ鿴

¼ò½é£º1. SPI×ÜÏß 1.1. SPI×ÜÏ߸ÅÊö SPI£¬ÊÇÓ¢ÓïSerial Peripheral interfaceµÄËõд£¬¹ËÃû˼Òå¾ÍÊÇ´®ÐÐÍâΧÉ豸½Ó¿Ú¡£ÊÇMotorolaÊ×ÏÈÔÚÆäMC68HCXXϵÁд¦ÀíÆ÷É϶¨ÒåµÄ¡£SPI½Ó¿ÚÖ÷ÒªÓ¦ÓÃÔÚ EEPROM£¬FLASH£¬ÊµÊ±Ê±ÖÓ£¬ADת»»Æ÷£¬»¹ÓÐÊý×ÖÐźŴ¦ÀíÆ÷ºÍÊý×ÖÐźŽâÂëÆ÷Ö®¡­¡­

1. SPI×ÜÏß

1.1. SPI×ÜÏ߸ÅÊö

SPI£¬ÊÇÓ¢ÓïSerial Peripheral interfaceµÄËõд£¬¹ËÃû˼Òå¾ÍÊÇ´®ÐÐÍâΧÉ豸½Ó¿Ú¡£ÊÇMotorolaÊ×ÏÈÔÚÆäMC68HCXXϵÁд¦ÀíÆ÷É϶¨ÒåµÄ¡£SPI½Ó¿ÚÖ÷ÒªÓ¦ÓÃÔÚ EEPROM£¬FLASH£¬ÊµÊ±Ê±ÖÓ£¬ADת»»Æ÷£¬»¹ÓÐÊý×ÖÐźŴ¦ÀíÆ÷ºÍÊý×ÖÐźŽâÂëÆ÷Ö®¼ä¡£SPI£¬ÊÇÒ»ÖÖ¸ßËٵģ¬È«Ë«¹¤£¬Í¬²½µÄͨÐÅ×ÜÏߣ¬²¢ÇÒÔÚоƬµÄ¹Ü½ÅÉÏÖ»Õ¼ÓÃËĸùÏߣ¬½ÚÔ¼ÁËоƬµÄ¹Ü½Å£¬Í¬Ê±ÎªPCBµÄ²¼¾ÖÉϽÚÊ¡¿Õ¼ä£¬Ìṩ·½±ã£¬ÕýÊdzöÓÚÕâÖÖ¼òµ¥Ò×ÓõÄÌØÐÔ£¬ÏÖÔÚÔ½À´Ô½¶àµÄоƬ¼¯³ÉÁËÕâÖÖͨÐÅЭÒé¡£SPI×ÜÏߵĹ¹³É¼°ÐźÅÀàÐÍÈçͼ1-1Ëùʾ£º

  • MOSI – Ö÷É豸Êý¾ÝÊä³ö£¬´ÓÉ豸Êý¾ÝÊäÈë ¶ÔÓ¦MOSI master output slave input
  • MISO – Ö÷É豸Êý¾ÝÊäÈ룬´ÓÉ豸Êý¾ÝÊä³ö ¶ÔÓ¦MISO master input slave output
  • CLK – ʱÖÓÐźţ¬ÓÉÖ÷É豸²úÉú
  • nCS – ´ÓÉ豸ʹÄÜÐźţ¬ÓÉÖ÷É豸¿ØÖÆ

ͼ1-1 SPI×ÜÏßÄ£ÐÍ

1.2. SPI×ÜÏßʱÐò

SPI½Ó¿ÚÔÚMaster¿ØÖÆϲúÉúµÄ´ÓÉ豸ʹÄÜÐźźÍʱÖÓÐźţ¬Á½¸öË«ÏòÒÆλ¼Ä´æÆ÷°´Î»´«Êä½øÐÐÊý¾Ý½»»»£¬´«ÊäÊý¾Ý¸ßλÔÚÇ°(MSB first)£¬µÍλÔÚºó¡£ÈçÏÂͼËùʾ£¬ÔÚCLKµÄϽµÑØÉÏÊý¾Ý¸Ä±ä£¬ÉÏÉýÑØһλÊý¾Ý±»´æÈëÒÆλ¼Ä´æÆ÷¡£

ͼ1-2 spi´«ÊäʱÐòͼ

ÔÚÒ»¸öSPIʱÖÓÖÜÆÚÄÚ£¬»áÍê³ÉÈçϲÙ×÷£º(1)Masterͨ¹ýMOSIÏß·¢ËÍ1λÊý¾Ý£¬Í¬Ê±Slaveͨ¹ýMOSIÏ߶ÁÈ¡Õâ1λÊý¾Ý;(2)Slaveͨ¹ýMISOÏß·¢ËÍ1λÊý¾Ý£¬Í¬Ê±Masterͨ¹ýMISOÏ߶ÁÈ¡Õâ1λÊý¾Ý¡£MasterºÍSlave¸÷ÓÐÒ»¸öÒÆλ¼Ä´æÆ÷£¬Èçͼ1-3Ëùʾ£¬¶øÇÒÕâÁ½¸öÒÆλ¼Ä´æÆ÷Á¬½Ó³É»·×´¡£ÒÀÕÕCLKµÄ±ä»¯£¬Êý¾ÝÒÔMSB firstµÄ·½Ê½ÒÀ´ÎÒƳöMaster¼Ä´æÆ÷ºÍSlave¼Ä´æÆ÷£¬²¢ÇÒÒÀ´ÎÒÆÈëSlave¼Ä´æÆ÷ºÍMaster¼Ä´æÆ÷¡£µ±¼Ä´æÆ÷ÖеÄÄÚÈÝÈ«²¿ÒƳöʱ£¬Ï൱ÓÚÍê³ÉÁËÁ½¸ö¼Ä´æÆ÷ÄÚÈݵĽ»»»¡£

1.3. SPI×ÜÏß´«Êäģʽ

SPI×ÜÏß´«ÊäÒ»¹²ÓÐ4ÖÖģʽ£¬Õâ4ÖÖģʽ·Ö±ðÓÉʱÖÓ¼«ÐÔ(CPOL£¬Clock Polarity)ºÍʱÖÓÏàλ(CPHA£¬Clock Phase)À´¶¨Ò壬ÆäÖÐCPOL²ÎÊý¹æ¶¨ÁËSCKʱÖÓÐźſÕÏÐ״̬µÄµçƽ£¬CPHA¹æ¶¨ÁËÊý¾ÝÊÇÔÚSCKʱÖÓµÄÉÏÉýÑر»²ÉÑù»¹ÊÇϽµÑر»²ÉÑù¡£ÕâËÄÖÖģʽµÄʱÐòͼÈçÏÂͼ1-4Ëùʾ£º


  • ģʽ0£ºCPOL= 0£¬CPHA=0¡£CLK´®ÐÐʱÖÓÏß¿ÕÏÐÊÇΪµÍµçƽ£¬Êý¾ÝÔÚSCKʱÖÓµÄÉÏÉýÑر»²ÉÑù£¬Êý¾ÝÔÚCLKʱÖÓµÄϽµÑØÇл»
  • ģʽ1£ºCPOL= 0£¬CPHA=1¡£CLK´®ÐÐʱÖÓÏß¿ÕÏÐÊÇΪµÍµçƽ£¬Êý¾ÝÔÚSCKʱÖÓµÄϽµÑر»²ÉÑù£¬Êý¾ÝÔÚCLKʱÖÓµÄÉÏÉýÑØÇл»
  • ģʽ2£ºCPOL= 1£¬CPHA=0¡£CLK´®ÐÐʱÖÓÏß¿ÕÏÐÊÇΪ¸ßµçƽ£¬Êý¾ÝÔÚSCKʱÖÓµÄϽµÑر»²ÉÑù£¬Êý¾ÝÔÚCLKʱÖÓµÄÉÏÉýÑØÇл»
  • ģʽ3£ºCPOL= 1£¬CPHA=1¡£CLK´®ÐÐʱÖÓÏß¿ÕÏÐÊÇΪ¸ßµçƽ£¬Êý¾ÝÔÚSCKʱÖÓµÄÉÏÉýÑر»²ÉÑù£¬Êý¾ÝÔÚCLKʱÖÓµÄϽµÑØÇл» ÆäÖбȽϳ£ÓõÄģʽÊÇģʽ0ºÍģʽ3¡£ÎªÁ˸üÇåÎúµÄÃèÊöSPI×ÜÏßµÄʱÐò£¬ÏÂÃæÕ¹ÏÖÁËģʽ0ϵÄSPIʱÐòͼ1-5£º

 

ͼ1-5 mode0ϵÄSPIʱÐòͼ

1.4. SPI×ÜÏßµÄÓÅȱµã

(1) ÔÚµã¶ÔµãµÄͨÐÅÖУ¬SPI½Ó¿Ú²»ÐèÒª½øÐÐÑ°Ö·²Ù×÷£¬ÇÒΪȫ˫¹¤Í¨ÐÅ£¬ÏԵüòµ¥¸ßЧ¡£(2) SPI½Ó¿ÚûÓÐÖ¸¶¨µÄÁ÷¿ØÖÆ£¬Ã»ÓÐÓ¦´ð»úÖÆÈ·ÈÏÊÇ·ñ½ÓÊÕµ½Êý¾Ý¡£

2. Linux SPI ¿ò¼Ü

2.1. Èí¼þ¼Ü¹¹

Linuxϵͳ¶ÔspiÉ豸¾ßÓкܺõÄÖ§³Ö£¬linuxϵͳϵÄspiÇý¶¯³ÌÐò´ÓÂß¼­ÉÏ¿ÉÒÔ·ÖΪ3¸ö²¿·Ö£º

  1. spiºËÐÄ(SPI Core)£ºSPI CoreÊÇLinuxÄÚºËÓÃÀ´Î¬»¤ºÍ¹ÜÀíspiµÄºËÐIJ¿·Ö£¬SPI CoreÌṩ²Ù×÷½Ó¿Úº¯Êý£¬ÔÊÐíÒ»¸öspi master£¬spi driverºÍspi device³õʼ»¯Ê±ÔÚSPI CoreÖнøÐÐ×¢²á£¬ÒÔ¼°Í˳öʱ½øÐÐ×¢Ïú¡£
  2. spi¿ØÖÆÆ÷Çý¶¯(SPI Master Driver)£ºSPI MasterÕë¶Ô²»Í¬ÀàÐ͵Äspi¿ØÖÆÆ÷Ó²¼þ£¬ÊµÏÖspi×ÜÏßµÄÓ²¼þ·ÃÎʲÙ×÷¡£SPI Masterͨ¹ý½Ó¿Úº¯ÊýÏòSPI Core×¢²áÒ»¸ö¿ØÖÆÆ÷¡£
  3. spiÉ豸Çý¶¯(SPI Device Driver)£ºSPI DriverÊǶÔÓ¦ÓÚspiÉ豸¶ËµÄÇý¶¯³ÌÐò£¬Í¨¹ý½Ó¿Úº¯ÊýÏòSPI Core½øÐÐ×¢²á£¬SPI DriverµÄ×÷ÓÃÊǽ«spiÉ豸¹Ò½Óµ½spi×ÜÏßÉÏ;LinuxµÄÈí¼þ¼Ü¹¹Í¼Èçͼ2-1Ëùʾ£º

 

ͼ2-1 spiÈí¼þ¼Ü¹¹Í¼

2.2. ³õʼ»¯¼°Í˳öÁ÷³Ì

2.2.1. ×¢²áspi¿ØÖÆÆ÷

×¢²áspi¿ØÖÆÆ÷µ½Äں˷ÖΪÁ½¸ö½×¶Î£ºµÚÒ»¸ö½×¶Î£¬Ê¹ÓÃspi_alloc_master,·ÖÅäÒ»¸öspi_masterµÄ¿Õ¼ä£¬¾ßÌåÁ÷³ÌÈçͼ2-2Ëùʾ£º


µÚ¶þ½×¶Î£¬Ê¹ÓÃspi_register_master½«µÚÒ»½×¶Î·ÖÅäµÄspi_master×¢²áµ½ÄÚºËÖУ¬¾ßÌåÁ÷³ÌÈç2-3Ëùʾ£º

2.2.2. ×¢Ïúspi¿ØÖÆÆ÷

spi¿ØÖÆÆ÷×¢ÏúµÄÁ÷³ÌÈçͼ2-4Ëùʾ£º


2.3. ¹Ø¼üÊý¾Ý½á¹¹

2.3.1. spi_device

  1. struct spi_device { 
  2.         struct device         dev;      /*spi¿ØÖÆÆ÷¶ÔÓ¦µÄdevice½á¹¹ 
  3.         struct spi_master   *master;      /*É豸ʹÓõÄmaster½á¹¹£¬¹ÒÔÚÄĸöÖ÷¿ØÖÆÆ÷ÏÂ*/ 
  4.         u32                     max_speed_hz;   /*ͨѶʱÖÓ×î´óƵÂÊ*/ 
  5.         u8                      chip_select;     /*ƬѡºÅ£¬Ã¿¸ömasterÖ§³Ö¶à¸öspi_device  */  
  6.         u8                      mode; 
  7. #define SPI_CPHA        0x01                    /* clock phase */ 
  8. #define SPI_CPOL        0x02                    /* clock polarity */ 
  9. #define SPI_MODE_0      (0|0)                   /* (original MicroWire) */ 
  10. #define SPI_MODE_1      (0|SPI_CPHA) 
  11. #define SPI_MODE_2      (SPI_CPOL|0) 
  12. #define SPI_MODE_3      (SPI_CPOL|SPI_CPHA) 
  13. #define SPI_CS_HIGH     0x04                    /* chipselect active high? */ 
  14. #define SPI_LSB_FIRST   0x08                    /* per-word bits-on-wire */ 
  15. #define SPI_3WIRE       0x10                    /* SI/SO signals shared */ 
  16. #define SPI_LOOP        0x20                    /* loopback mode */ 
  17. #define SPI_NO_CS       0x40                    /* 1 dev/bus, no chipselect */ 
  18. #define SPI_READY       0x80                    /* slave pulls low to pause */ 
  19.         u8                      bits_per_word;    /*ÿ¸ö×Ö³¤µÄ±ÈÌØÊý£¬Ä¬ÈÏÊÇ8*/ 
  20.         int                     irq; 
  21.         void                    *controller_state; /*¿ØÖÆÆ÷״̬*/ 
  22.         void                    *controller_data;   /*¿ØÖÆÆ÷Êý¾Ý*/ 
  23.         char                    modalias[SPI_NAME_SIZE]; /* É豸Çý¶¯µÄÃû×Ö */ 
  24.         int                     cs_gpio;        /* chip select gpio */ 
  25.  
  26.         /* 
  27.          * likely need more hooks for more protocol options affecting how 
  28.          * the controller talks to each chip, like
  29.          *  - memory packing (12 bit samples into low bits, others zeroed) 
  30.          *  - priority 
  31.          *  - drop chipselect after each word 
  32.          *  - chipselect delays 
  33.          *  - ... 
  34.          */ 
  35. }; 

spi_device´ú±íÒ»¸öÍâΧspiÉ豸£¬ÓÉmaster controller driver×¢²áÍê³ÉºóɨÃèBSPÖÐ×¢²áÉ豸²úÉúµÄÉ豸Á´±í²¢Ïòspi_bus×¢²á²úÉú¡£ÔÚÄÚºËÖУ¬Ã¿¸öspi_device´ú±íÒ»¸öÎïÀíµÄspiÉ豸¡£

2.3.2. spi_driver

  1. struct spi_driver { 
  2.         const struct spi_device_id *id_table; /*Ö§³ÖµÄspi_deviceÉ豸±í*/ 
  3.  
  4.         int                     (*probe)(struct spi_device *spi); 
  5.         int                     (*remove)(struct spi_device *spi); 
  6.         void                    (*shutdown)(struct spi_device *spi); 
  7.         int                     (*suspend)(struct spi_device *spi, pm_message_t mesg); 
  8.         int                     (*resume)(struct spi_device *spi); 
  9.         struct device_driver    driver; 
  10. }; 

spi_driver´ú±íÒ»¸öSPI protocol drivers£¬¼´ÍâÉèÇý¶¯

2.3.3. struct spi_master

  1. struct spi_master { 
  2.         struct device   dev;  /*spi¿ØÖÆÆ÷¶ÔÓ¦µÄdevice½á¹¹*/ 
  3.  
  4.         struct list_head list;  /*Á´±í 
  5.  
  6.         /* other than negative (== assign one dynamically), bus_num is fully 
  7.          * board-specific.  usually that simplifies to being SOC-specific. 
  8.          * example:  one SOC has three SPI controllers, numbered 0..2, 
  9.          * and one board's schematics might show it using SPI-2.  software 
  10.          * would normally use bus_num=2 for that controller. 
  11.          */ 
  12.         s16                     bus_num; /*×ÜÏߣ¨»ò¿ØÖÆÆ÷±àºÅ£©*/ 
  13.  
  14.         /* chipselects will be integral to many controllers; some others 
  15.          * might use board-specific GPIOs. 
  16.          */ 
  17.         u16                     num_chipselect; /*ƬѡÊýÁ¿*/ 
  18.  
  19.         /* some SPI controllers pose alignment requirements on DMAable 
  20.          * buffers; let protocol drivers know about these requirements. 
  21.          */ 
  22.         u16                     dma_alignment; 
  23.  
  24.         /* spi_device.mode flags understood by this controller driver */ 
  25.         u16                     mode_bits;   /* masterÖ§³ÖµÄÉ豸ģʽ */ 
  26.  
  27.         /* bitmask of supported bits_per_word for transfers */ 
  28.         u32                     bits_per_word_mask; 
  29.  
  30.         /* other constraints relevant to this driver */ 
  31.         u16                     flags; /*ÓÃÓÚÏÞ¶¨Ä³Ð©ÏÞÖÆÌõ¼þµÄ±ê־λ 
  32. #define SPI_MASTER_HALF_DUPLEX  BIT(0)          /* can't do full duplex */ 
  33. #define SPI_MASTER_NO_RX        BIT(1)          /* can't do buffer read */ 
  34. #define SPI_MASTER_NO_TX        BIT(2)          /* can't do buffer write */ 
  35.  
  36.         /* lock and mutex for SPI bus locking */ 
  37.         spinlock_t              bus_lock_spinlock; 
  38.         struct mutex            bus_lock_mutex; 
  39.  
  40.         /* flag indicating that the SPI bus is locked for exclusive use */ 
  41.         bool                    bus_lock_flag; 
  42.  
  43.         /* Setup mode and clock, etc (spi driver may call many times). 
  44.          * 
  45.          * IMPORTANT:  this may be called when transfers to another 
  46.          * device are active.  DO NOT UPDATE SHARED REGISTERS in ways 
  47.          * which could break those transfers. 
  48.          */ 
  49.         int                     (*setup)(struct spi_device *spi); /*¸ù¾ÝspiÉ豸¸üÐÂÓ²¼þÅäÖá£ÉèÖÃspi¹¤×÷ģʽ¡¢Ê±ÖÓµÈ*/ 
  50.  
  51.         /* bidirectional bulk transfers 
  52.          * 
  53.          * + The transfer() method may not sleep; its main role is 
  54.          *   just to add the message to the queue. 
  55.          * + For now there's no remove-from-queue operation, or 
  56.          *   any other request management 
  57.          * + To a given spi_device, message queueing is pure fifo 
  58.          * 
  59. * + The master's main job is to process its message queue, 
  60.          *   selecting a chip then transferring data 
  61.          * + If there are multiple spi_device children, the i/o queue 
  62.          *   arbitration algorithm is unspecified (round robin, fifo, 
  63.          *   priority, reservations, preemption, etc) 
  64.          * 
  65.          * + Chipselect stays active during the entire message 
  66.          *   (unless modified by spi_transfer.cs_change != 0). 
  67.          * + The message transfers use clock and SPI mode parameters 
  68.          *   previously established by setup() for this device 
  69.          */ 
  70.         int                     (*transfer)(struct spi_device *spi, 
  71.                                                 struct spi_message *mesg);   /*Ìí¼ÓÏûÏ¢µ½¶ÓÁеķ½·¨£¬´Ëº¯Êý²»¿É˯Ãß¡£ËüµÄÖ°ÔðÊÇ°²ÅÅ·¢ÉúµÄ´«ËͲ¢ÇÒµ÷ÓÃ×¢²áµÄ»Øµ÷º¯Êýcomplete()*/ 
  72.  
  73.  
  74.  
  75.         /* called on release() to free memory provided by spi_master */ 
  76.         void                    (*cleanup)(struct spi_device *spi);/*cleanupº¯Êý»áÔÚspidev_releaseº¯ÊýÖб»µ÷Óã¬spidev_release±»µÇ¼ÇΪspi devµÄreleaseº¯Êý¡£*/ 
  77.  
  78.  
  79.         /* 
  80.          * These hooks are for drivers that want to use the generic 
  81.          * master transfer queueing mechanism. If these are used, the 
  82.          * transfer() function above must NOT be specified by the driver. 
  83.          * Over time we expect SPI drivers to be phased over to this API. 
  84.          */ 
  85.         bool                      queued;  
  86.         struct kthread_worker  kworker; /*ÓÃÓÚ¹ÜÀíÊý¾Ý´«ÊäÏûÏ¢¶ÓÁеŤ×÷¶ÓÁÐÏß³Ì*/ 
  87.         struct task_struct     *kworker_task; 
  88.         struct kthread_work    pump_messages; /*¾ßÌåʵÏÖÊý¾Ý´«Êä¶ÓÁеŤ×÷¶ÓÁÐ*/ 
  89.         spinlock_t               queue_lock; 
  90.         struct list_head        queue; /*¸Ã¿ØÖÆÆ÷µÄÏûÏ¢¶ÓÁУ¬ËùÓеȴý´«ÊäµÄ¶ÓÁйÒÔÚ¸ÃÁ´±íÏÂ*/ 
  91.         struct spi_message     *cur_msg;/*µ±Ç°ÕýÔÚ´¦ÀíµÄÏûÏ¢¶ÓÁÐ*/ 
  92.         bool                       busy; /æ״̬*/ 
  93.         bool                       running; /*ÕýÔÚÅÜ*/ 
  94.         bool                       rt;  
  95.  
  96.         int (*prepare_transfer_hardware)(struct spi_master *master); /*»Øµ÷º¯Êý£¬Õýʽ·¢Æð´«ÊäÇ°»á±»µ÷Óã¬ÓÃÓÚ×¼±¸Ó²¼þ×ÊÔ´*/ 
  97.         int (*transfer_one_message)(struct spi_master *master, struct spi_message *mesg); /*µ¥¸öÏûÏ¢µÄÔ­×Ó´«Êä»Øµ÷º¯Êý£¬¶ÓÁÐÖÐÿ¸öÏûÏ¢¶¼»á»Øµ÷Ò»´Î¸Ã»Øµ÷À´Íê³É´«Ê乤×÷*/ 
  98.       int (*unprepare_transfer_hardware)(struct spi_master *master); /*ÇåÀí»Øµ÷º¯Êý*/ 
  99.         /* gpio chip select */ 
  100.         int                     *cs_gpios; 
  101. }; 

spi_master´ú±íÒ»¸öspi¿ØÖÆÆ÷¡£

2.3.4. struct spi_message ºÍspi_transfer

ÒªÍê³ÉºÍSPIÉ豸µÄÊý¾Ý´«Ê乤×÷£¬ÎÒÃÇ»¹ÐèÒªÁíÍâÁ½¸öÊý¾Ý½á¹¹£ºspi_messageºÍspi_transfer¡£

spi_message°üº¬ÁËÒ»¸öµÄspi_transfer½á¹¹ÐòÁУ¬Ò»µ©¿ØÖÆÆ÷½ÓÊÕÁËÒ»¸öspi_message£¬ÆäÖеÄspi_transferÓ¦¸Ã°´Ë³Ðò±»·¢ËÍ£¬²¢ÇÒ²»Äܱ»ÆäËüspi_message´ò¶Ï£¬ËùÒÔÎÒÃÇÈÏΪspi_message¾ÍÊÇÒ»´ÎSPIÊý¾Ý½»»»µÄÔ­×Ó²Ù×÷¡£ÏÂÃæÎÒÃÇ¿´¿´ÕâÁ½¸öÊý¾Ý½á¹¹µÄ¶¨Ò壺

struct spi_message £º

  1. struct spi_message { 
  2.         struct list_head        transfers;  /*spi_transferÁ´±í¶ÓÁУ¬´Ë´ÎÏûÏ¢µÄ´«Êä¶Î¶ÓÁУ¬Ò»¸öÏûÏ¢¿ÉÒÔ°üº¬¶à¸ö´«Êä¶Î¡£*/ 
  3.  
  4.         struct spi_device       *spi; /*´«ÊäµÄÄ¿µÄÉ豸*/ 
  5.         unsigned                is_dma_mapped:1;  /*Èç¹ûΪÕ棬´Ë´Îµ÷ÓÃÌṩdmaºÍcpuÐéÄâµØÖ·¡£*/ 
  6.  
  7.         /* REVISIT:  we might want a flag affecting the behavior of the 
  8.          * last transfer ... allowing things like "read 16 bit length L" 
  9.          * immediately followed by "read L bytes".  Basically imposing 
  10.          * a specific message scheduling algorithm. 
  11.          * 
  12.          * Some controller drivers (message-at-a-time queue processing) 
  13.          * could provide that as their default scheduling algorithm.  But 
  14.          * others (with multi-message pipelines) could need a flag to 
  15.          * tell them about such special cases. 
  16.          */ 
  17.  
  18.         /* completion is reported through a callback */ 
  19.         void                    (*complete)(void *context);/*Òì²½µ÷ÓÃÍê³ÉºóµÄ»Øµ÷º¯Êý*/ 
  20.         void                    *context; /*»Øµ÷º¯ÊýµÄ²ÎÊý*/ 
  21.         unsigned                actual_length; /*ʵ¼Ê´«ÊäµÄ³¤¶È*/ 
  22.         int                     status; /*¸ÃÏûÏ¢µÄ·¢Ëͽá¹û£¬³É¹¦±»ÖÃ0£¬·ñÔòÊÇÒ»¸ö¸ºµÄ´íÎóÂë¡£*/ 
  23.  
  24.         /* for optional use by whatever driver currently owns the 
  25.          * spi_message ...  between calls to spi_async and then later 
  26.          * complete(), that's the spi_master controller driver. 
  27.          */ 
  28.         struct list_head        queue; 
  29.         void                    *state; 
  30. }; 

Á´±í×Ö¶ÎqueueÓÃÓڰѸýṹ¹ÒÔÚ´ú±í¿ØÖÆÆ÷µÄspi_master½á¹¹µÄqueue×Ö¶ÎÉÏ£¬¿ØÖÆÆ÷ÉÏ¿ÉÒÔͬʱ±»¼ÓÈë¶à¸öspi_message½øÐÐÅŶӡ£ÁíÒ»¸öÁ´±í×Ö¶ÎtransfersÔòÓÃÓÚÁ´½Ó¹ÒÔÚ±¾messageϵÄspi_tranfer½á¹¹¡£complete»Øµ÷º¯ÊýÔò»áÔÚ¸ÃmessageϵÄËùÓÐspi_transfer¶¼±»´«ÊäÍê³Éʱ±»µ÷Óã¬ÒÔ±ã֪ͨЭÒéÇý¶¯´¦Àí½ÓÊÕµ½µÄÊý¾ÝÒÔ¼°×¼±¸ÏÂÒ»ÅúÐèÒª·¢Ë͵ÄÊý¾Ý¡£ÎÒÃÇÔÙÀ´¿´¿´spi_transfer½á¹¹£ºspi_transfer

  1. struct spi_transfer { 
  2.         /* it's ok if tx_buf == rx_buf (right?) 
  3.          * for MicroWire, one buffer must be null 
  4.          * buffers must work with dma_*map_single() calls, unless 
  5.          *   spi_message.is_dma_mapped reports a pre-existing mapping 
  6.          */ 
  7.         const void     *tx_buf; /*·¢ËÍ»º³åÇø*/ 
  8.         void            *rx_buf; /*½ÓÊÕ»º³åÇø*/ 
  9.         unsigned        len; /*»º³åÇø³¤¶È£¬txºÍrxµÄ´óС£¨×Ö½ÚÊý£©¡£Ö¸ËüÃǸ÷×ԵĴóС*/ 
  10.  
  11.         dma_addr_t      tx_dma; /*txµÄdmaµØÖ·*/ 
  12.         dma_addr_t      rx_dma;  /*rxµÄdmaµØÖ·*/ 
  13.   
  14.         unsigned        cs_change:1; /*µ±Ç°spi_transfer·¢ËÍÍê³ÉÖ®ºóÖØÐÂƬѡ*/ 
  15.         u8              bits_per_word; /*ÿ¸ö×Ö³¤µÄ±ÈÌØÊý£¬0´ú±íʹÓÃspi_deviceÖеÄĬÈÏÖµ8*/ 
  16.         u16             delay_usecs; /*·¢ËÍÍê³ÉÒ»¸öspi_transferºóµÄÑÓʱʱ¼ä£¬´Ë´Î´«Êä½áÊøºÍƬѡ¸Ä±äÖ®¼äµÄÑÓʱ£¬Ö®ºó¾Í»áÆô¶¯ÁíÒ»¸ö´«Êä»òÕß½áÊøÕû¸öÏûÏ¢*/ 
  17.         u32             speed_hz; /*ͨÐÅʱÖÓ¡£Èç¹ûÊÇ0£¬Ê¹ÓÃĬÈÏÖµ*/ 
  18.  
  19. #ifdef CONFIG_SPI_LOMBO 
  20.         struct lombo_spi_operate_para *esop; 
  21. #endif 
  22.  
  23.         struct list_head transfer_list; /*ÓÃÓÚÁ´½Óµ½spi_message£¬ÓÃÀ´Á¬½ÓµÄË«ÏòÁ´½Ó½Úµã*/ 
  24.  
  25. }; 

Ê×ÏÈ£¬transfer_listÁ´±í×Ö¶ÎÓÃÓڰѸÃtransfer¹ÒÔÚÒ»¸öspi_message½á¹¹ÖУ¬tx_bufºÍrx_bufÌṩÁË·ÇdmaģʽϵÄÊý¾Ý»º³åÇøµØÖ·£¬lenÔòÊÇÐèÒª´«ÊäÊý¾ÝµÄ³¤¶È£¬tx_dmaºÍrx_dmaÔò¸ø³öÁËdmaģʽϵĻº³åÇøµØÖ·¡£Ô­ÔòÀ´½²£¬spi_transfer²ÅÊÇ´«ÊäµÄ×îСµ¥Î»£¬Ö®ËùÒÔÓÖÒý½øÁËspi_message½øÐдò°ü£¬ÎÒ¾õµÃÔ­ÒòÊÇ£ºÓÐʱºòÏ£ÍûÍùspiÉ豸µÄ¶à¸ö²»Á¬ÐøµÄµØÖ·(»ò¼Ä´æÆ÷)Ò»´ÎÐÔдÈ룬Èç¹ûûÓÐspi_message½øÐаÑÕâÑùµÄ¶à¸öspi_transfer´ò°ü£¬ÒòΪͨ³£ÕæÕýµÄÊý¾Ý´«Ë͹¤×÷ÊÇÔÚÁíÒ»¸öÄÚºËÏß³Ì(¹¤×÷¶ÓÁÐ)ÖÐÍê³ÉµÄ£¬²»´ò°üµÄºó¹û¾ÍÊÇ»áÔì³É¸ü¶àµÄ½ø³ÌÇл»£¬Ð§ÂʽµµÍ£¬ÑÓ³ÙÔö¼Ó£¬ÓÈÆä¶ÔÓÚ¶à¸ö²»Á¬ÐøµØÖ·µÄС¹æÄ£Êý¾Ý´«ËͶøÑԾ͸üΪÃ÷ÏÔ¡£

2.3.5. spi_board_info

  1. struct spi_board_info { 
  2.         /* the device name and module name are coupled, like platform_bus; 
  3.          * "modalias" is normally the driver name
  4.          * 
  5.          * platform_data goes to spi_device.dev.platform_data, 
  6.          * controller_data goes to spi_device.controller_data, 
  7.          * irq is copied too 
  8.          */ 
  9.         char            modalias[SPI_NAME_SIZE]; /*Ãû×Ö*/ 
  10.  
  11.         const void      *platform_data; /*ƽ̨Êý¾Ý*/ 
  12.         void            *controller_data; /*¿ØÖÆÆ÷Êý¾Ý*/ 
  13.         int             irq; 
  14.  
  15.         /* slower signaling on noisy or low voltage boards */ 
  16.         u32             max_speed_hz; /*×î´óËÙÂÊ*/ 
  17.  
  18.  
  19.         /* bus_num is board specific and matches the bus_num of some 
  20.          * spi_master that will probably be registered later. 
  21.          * 
  22.          * chip_select reflects how this chip is wired to that master; 
  23.          * it's less than num_chipselect. 
  24.          */ 
  25.         u16             bus_num; /*spi×ÜÏß±àºÅ*/ 
  26.         u16             chip_select; /*Ƭѡ*/ 
  27.  
  28.         /* mode becomes spi_device.mode, and is essential for chips 
  29.          * where the default of SPI_CS_HIGH = 0 is wrong. 
  30.          */ 
  31.         u8              mode; /*ģʽ */ 
  32.  
  33.         /* ... may need additional spi_device chip config data here. 
  34.          * avoid stuff protocol drivers can set; but include stuff 
  35.          * needed to behave without being bound to a driver: 
  36.          *  - quirks like clock rate mattering when not selected 
  37.          */ 
  38. }; 

2.4. Êý¾Ý´«ÊäÁ÷³Ì

ÕûÌåµÄÊý¾Ý´«ÊäÁ÷³Ì´óÖÂÉÏÊÇÕâÑùµÄ:

  1. ¶¨ÒåÒ»¸öspi_message½á¹¹;
  2. ÓÃspi_message_initº¯Êý³õʼ»¯spi_message;
  3. ¶¨ÒåÒ»¸ö»òÊý¸öspi_transfer½á¹¹£¬³õʼ»¯²¢ÎªÊý¾Ý×¼±¸»º³åÇø²¢¸³Öµ¸øspi_transferÏàÓ¦µÄ×Ö¶Î(tx_buf£¬rx_bufµÈ);
  4. ͨ¹ýspi_message_initº¯Êý°ÑÕâЩspi_transfer¹ÒÔÚspi_message½á¹¹ÏÂ;
  5. Èç¹ûʹÓÃͬ²½·½Ê½£¬µ÷ÓÃspi_sync()£¬Èç¹ûʹÓÃÒì²½·½Ê½£¬µ÷ÓÃspi_async();(ÎÒµ÷ÊÔÍâÉèʱ£¬Ö»Ê¹Óùýspi_sync

´«ÊäʾÒâͼÈçͼ2-5Ëùʾ£º


2.4.1. Êý¾Ý×¼±¸

2.4.1.1. spi_message_init

  1. static inline void spi_message_init(struct spi_message *m) 
  2.  memset(m, 0, sizeof *m); 
  3.  INIT_LIST_HEAD(&m->transfers); 

³õʼ»¯spi_message£ºÇå¿Õmessage£¬³õʼ»¯transfersÁ´±íÍ·¡£

2.4.1.2. spi_message_add_tail

  1. static inline void 
  2. spi_message_add_tail(struct spi_transfer *t, struct spi_message *m) 
  3.  list_add_tail(&t->transfer_list, &m->transfers); 

½«spi_transfer¼ÓÈëµ½spi_messageµÄÁ´±íβ²¿¡£

2.4.2. Êý¾Ý´«Êä

SPIÊý¾Ý´«Êä¿ÉÒÔÓÐÁ½ÖÖ·½Ê½£ºÍ¬²½·½Ê½ºÍÒì²½·½Ê½¡£Ëùνͬ²½·½Ê½ÊÇÖ¸Êý¾Ý´«ÊäµÄ·¢ÆðÕß±ØÐëµÈ´ý±¾´Î´«ÊäµÄ½áÊø£¬Æڼ䲻ÄÜ×öÆäËüÊÂÇ飬ÓôúÂëÀ´½âÊ;ÍÊÇ£¬µ÷Óô«ÊäµÄº¯Êýºó£¬Ö±µ½Êý¾Ý´«ÊäÍê³É£¬º¯Êý²Å»á·µ»Ø¡£¶øÒì²½·½Ê½ÔòÕýºÃÏà·´£¬Êý¾Ý´«ÊäµÄ·¢ÆðÕßÎÞÐèµÈ´ý´«ÊäµÄ½áÊø£¬Êý¾Ý´«ÊäÆڼ仹¿ÉÒÔ×öÆäËüÊÂÇ飬ÓôúÂëÀ´½âÊ;ÍÊÇ£¬µ÷Óô«ÊäµÄº¯Êýºó£¬º¯Êý»áÁ¢¿Ì·µ»Ø¶ø²»ÓõȴýÊý¾Ý´«ÊäÍê³É£¬ÎÒÃÇÖ»ÐèÉèÖÃÒ»¸ö»Øµ÷º¯Êý£¬´«ÊäÍê³Éºó£¬¸Ã»Øµ÷º¯Êý»á±»µ÷ÓÃÒÔ֪ͨ·¢ÆðÕßÊý¾Ý´«ËÍÒѾ­Íê³É¡£Í¬²½·½Ê½¼òµ¥Ò×Ó㬺ÜÊʺϴ¦ÀíÄÇЩÉÙÁ¿Êý¾ÝµÄµ¥´Î´«Êä¡£µ«ÊǶÔÓÚÊý¾ÝÁ¿´ó¡¢´ÎÊý¶àµÄ´«ÊäÀ´Ëµ£¬Òì²½·½Ê½¾ÍÏԵøü¼ÓºÏÊÊ¡£¶ÔÓÚSPI¿ØÖÆÆ÷À´Ëµ£¬ÒªÖ§³ÖÒì²½·½Ê½±ØÐëÒª¿¼ÂÇÒÔÏÂÁ½ÖÖ×´¿ö£º

  • ¶ÔÓÚͬһ¸öÊý¾Ý´«ÊäµÄ·¢ÆðÕߣ¬¼ÈÈ»Òì²½·½Ê½ÎÞÐèµÈ´ýÊý¾Ý´«ÊäÍê³É¼´¿É·µ»Ø£¬·µ»Øºó£¬¸Ã·¢ÆðÕß¿ÉÒÔÁ¢¿ÌÓÖ·¢ÆðÒ»¸ömessage£¬¶øÕâʱÉÏÒ»¸ömessage»¹Ã»Óд¦ÀíÍê¡£
  • ¶ÔÓÚÁíÍâÒ»¸ö²»Í¬µÄ·¢ÆðÕßÀ´Ëµ£¬Ò²ÓпÉÄÜͬʱ·¢ÆðÒ»´Îmessage´«ÊäÇëÇó Ê×ÏÈ·ÖÎöspi_sync()½Ó¿ÚµÄʵÏÖÁ÷³Ì£¬Èçͼ2-6£º

Æä´Î·ÖÎöspi_async_locked½Ó¿ÚµÄʵÏÖÁ÷³Ì£¬Èçͼ2-7Ëùʾ£º

spi_queued_transfer½Ó¿ÚµÄʵÏÖÁ÷³ÌÈçͼ3-8Ëùʾ£º


spi_pump_messagesº¯ÊýµÄ´¦ÀíÁ÷³ÌÈçͼ3-9Ëùʾ£º

ͼÖÐtransfer_one_messageÊÇspi¿ØÖÆÆ÷Çý¶¯ÒªÊµÏֵģ¬Ö÷Òª¹¦ÄÜÊÇ´¦Àíspi_messageÖеÄÿ¸öspi_transfer¡£

2.5. ¹Ø¼üº¯Êý½âÎö

2.5.1. spi_alloc_master

Ô­ÐÍ£º

  1. struct spi_master *spi_alloc_master(struct device *dev, unsigned size

¹¦ÄÜ£º·ÖÅäÒ»¸öspi_master½á¹¹ÌåÖ¸Õë¡£

²ÎÊý£ºdev:spi¿ØÖÆÆ÷deviceÖ¸Õë size £º·ÖÅäµÄdriver-private data´óС

·µ»ØÖµ £º³É¹¦£¬·µ»Øspi_masterÖ¸Õë;·ñÔò·µ»ØNULL

2.5.2. spi_register_master

Ô­ÐÍ£º

  1. int spi_register_master(struct spi_master *master)  

¹¦ÄÜ ×¢²áspi¿ØÖÆÆ÷Çý¶¯µ½Äںˡ£

²ÎÊý master£ºspi_masterÖ¸Õë

·µ»ØÖµ ³É¹¦£¬·µ»Ø0;·ñÔò·µ»Ø´íÎóÂë

2.5.3. spi_unregister_master

Ô­ÐÍ£º

  1. void spi_unregister_master(struct spi_master *master)  

¹¦ÄÜ ×¢Ïúspi¿ØÖÆÆ÷Çý¶¯¡£

²ÎÊý master£ºspi_masterÖ¸Õë

·µ»ØÖµ ÎÞ

3. Demo

(²Î¿¼×ÔÕýµãÔ­×Ó)

  1. #include <linux/types.h> 
  2. #include <linux/kernel.h> 
  3. #include <linux/delay.h> 
  4. #include <linux/ide.h> 
  5. #include <linux/init.h> 
  6. #include <linux/module.h> 
  7. #include <linux/errno.h> 
  8. #include <linux/gpio.h> 
  9. #include <linux/cdev.h> 
  10. #include <linux/device.h> 
  11. #include <linux/of_gpio.h> 
  12. #include <linux/semaphore.h> 
  13. #include <linux/timer.h> 
  14. #include <linux/i2c.h> 
  15. #include <linux/spi/spi.h> 
  16. #include <linux/of.h> 
  17. #include <linux/of_address.h> 
  18. #include <linux/of_gpio.h> 
  19. #include <linux/platform_device.h> 
  20. #include <asm/mach/map.h> 
  21. #include <asm/uaccess.h> 
  22. #include <asm/io.h> 
  23. #include "icm20608reg.h" 
  24. /*************************************************************** 
  25. Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved. 
  26. ÎļþÃû  : icm20608.c 
  27. ×÷Õß    : ×󹤠
  28. °æ±¾     : V1.0 
  29. ÃèÊö     : ICM20608 SPIÇý¶¯³ÌÐò 
  30. ÆäËû     : ÎÞ 
  31. ÂÛ̳  :  
  32. ÈÕÖ¾     : ³õ°æV1.0 2019/9/2 ×󹤴´½¨ 
  33. ***************************************************************/ 
  34. #define ICM20608_CNT 1 
  35. #define ICM20608_NAME "icm20608" 
  36.  
  37. struct icm20608_dev { 
  38.  dev_t devid;    /* É豸ºÅ   */ 
  39.  struct cdev cdev;   /* cdev  */ 
  40.  struct class *class;  /* Àà   */ 
  41.  struct device *device;  /* É豸   */ 
  42.  struct device_node *nd;  /* É豸½Úµã */ 
  43.  int major;     /* Ö÷É豸ºÅ */ 
  44.  void *private_data;   /* Ë½ÓÐÊý¾Ý   */ 
  45.  int cs_gpio;    /* Æ¬Ñ¡ËùʹÓõÄGPIO±àºÅ  */ 
  46.  signed int gyro_x_adc;  /* ÍÓÂÝÒÇXÖáԭʼֵ   */ 
  47.  signed int gyro_y_adc;  /* ÍÓÂÝÒÇYÖáԭʼֵ  */ 
  48.  signed int gyro_z_adc;  /* ÍÓÂÝÒÇZÖáԭʼֵ   */ 
  49.  signed int accel_x_adc;  /* ¼ÓËٶȼÆXÖáԭʼֵ  */ 
  50.  signed int accel_y_adc;  /* ¼ÓËٶȼÆYÖáԭʼֵ */ 
  51.  signed int accel_z_adc;  /* ¼ÓËٶȼÆZÖáԭʼֵ  */ 
  52.  signed int temp_adc;  /* Î¶Èԭʼֵ    */ 
  53. }; 
  54.  
  55. static struct icm20608_dev icm20608dev; 
  56.  
  57. /* 
  58.  * @description : ´Óicm20608¶ÁÈ¡¶à¸ö¼Ä´æÆ÷Êý¾Ý 
  59.  * @param - dev:  icm20608É豸 
  60.  * @param - reg:  Òª¶ÁÈ¡µÄ¼Ä´æÆ÷Ê×µØÖ· 
  61.  * @param - val:  ¶ÁÈ¡µ½µÄÊý¾Ý 
  62.  * @param - len:  Òª¶ÁÈ¡µÄÊý¾Ý³¤¶È 
  63.  * @return   : ²Ù×÷½á¹û 
  64.  */ 
  65. static int icm20608_read_regs(struct icm20608_dev *dev, u8 reg, void *buf, int len) 
  66.  int ret; 
  67.  unsigned char txdata[len]; 
  68.  struct spi_message m; 
  69.  struct spi_transfer *t; 
  70.  struct spi_device *spi = (struct spi_device *)dev->private_data; 
  71.  
  72.  gpio_set_value(dev->cs_gpio, 0);    /* Æ¬Ñ¡À­µÍ£¬Ñ¡ÖÐICM20608 */ 
  73.  t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL); /* ÉêÇëÄÚ´æ */ 
  74.  
  75.  /* µÚ1´Î£¬·¢ËÍÒª¶ÁÈ¡µÄ¼Ä´æµØÖ· */ 
  76.  txdata[0] = reg | 0x80;  /* Ð´Êý¾ÝµÄʱºò¼Ä´æÆ÷µØÖ·bit8ÒªÖÃ1 */ 
  77.  t->tx_buf = txdata;   /* Òª·¢Ë͵ÄÊý¾Ý */ 
  78.  t->len = 1;     /* 1¸ö×Ö½Ú */ 
  79.  spi_message_init(&m);  /* ³õʼ»¯spi_message */ 
  80.  spi_message_add_tail(t, &m);/* ½«spi_transferÌí¼Óµ½spi_message¶ÓÁР*/ 
  81.  ret = spi_sync(spi, &m); /* Í¬²½·¢ËÍ */ 
  82.  
  83.  /* µÚ2´Î£¬¶ÁÈ¡Êý¾Ý */ 
  84.  txdata[0] = 0xff;   /* Ëæ±ãÒ»¸öÖµ£¬´Ë´¦ÎÞÒâÒå */ 
  85.  t->rx_buf = buf;   /* ¶ÁÈ¡µ½µÄÊý¾Ý */ 
  86.  t->len = len;    /* Òª¶ÁÈ¡µÄÊý¾Ý³¤¶È */ 
  87.  spi_message_init(&m);  /* ³õʼ»¯spi_message */ 
  88.  spi_message_add_tail(t, &m);/* ½«spi_transferÌí¼Óµ½spi_message¶ÓÁР*/ 
  89.  ret = spi_sync(spi, &m); /* Í¬²½·¢ËÍ */ 
  90.  
  91.  kfree(t);         /* ÊÍ·ÅÄÚ´æ */ 
  92.  gpio_set_value(dev->cs_gpio, 1);   /* Æ¬Ñ¡À­¸ß£¬ÊÍ·ÅICM20608 */ 
  93.  
  94.  return ret; 
  95.  
  96. /* 
  97.  * @description : Ïòicm20608¶à¸ö¼Ä´æÆ÷дÈëÊý¾Ý 
  98.  * @param - dev:  icm20608É豸 
  99.  * @param - reg:  ÒªÐ´ÈëµÄ¼Ä´æÆ÷Ê×µØÖ· 
  100.  * @param - val:  ÒªÐ´ÈëµÄÊý¾Ý»º³åÇø 
  101.  * @param - len:  ÒªÐ´ÈëµÄÊý¾Ý³¤¶È 
  102.  * @return    :   ²Ù×÷½á¹û 
  103.  */ 
  104. static s32 icm20608_write_regs(struct icm20608_dev *dev, u8 reg, u8 *buf, u8 len) 
  105.  int ret; 
  106.  
  107.  unsigned char txdata[len]; 
  108.  struct spi_message m; 
  109.  struct spi_transfer *t; 
  110.  struct spi_device *spi = (struct spi_device *)dev->private_data; 
  111.  
  112.  t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL); /* ÉêÇëÄÚ´æ */ 
  113.  gpio_set_value(dev->cs_gpio, 0);   /* Æ¬Ñ¡À­µÍ */ 
  114.  
  115.  /* µÚ1´Î£¬·¢ËÍÒª¶ÁÈ¡µÄ¼Ä´æµØÖ· */ 
  116.  txdata[0] = reg & ~0x80; /* Ð´Êý¾ÝµÄʱºò¼Ä´æÆ÷µØÖ·bit8ÒªÇåÁã */ 
  117.  t->tx_buf = txdata;   /* Òª·¢Ë͵ÄÊý¾Ý */ 
  118.  t->len = 1;     /* 1¸ö×Ö½Ú */ 
  119.  spi_message_init(&m);  /* ³õʼ»¯spi_message */ 
  120.  spi_message_add_tail(t, &m);/* ½«spi_transferÌí¼Óµ½spi_message¶ÓÁР*/ 
  121.  ret = spi_sync(spi, &m); /* Í¬²½·¢ËÍ */ 
  122.  
  123.  /* µÚ2´Î£¬·¢ËÍҪдÈëµÄÊý¾Ý */ 
  124.  t->tx_buf = buf;   /* ÒªÐ´ÈëµÄÊý¾Ý */ 
  125.  t->len = len;    /* Ð´ÈëµÄ×Ö½ÚÊý */ 
  126.  spi_message_init(&m);  /* ³õʼ»¯spi_message */ 
  127.  spi_message_add_tail(t, &m);/* ½«spi_transferÌí¼Óµ½spi_message¶ÓÁР*/ 
  128.  ret = spi_sync(spi, &m); /* Í¬²½·¢ËÍ */ 
  129.  
  130.  kfree(t);     /* ÊÍ·ÅÄÚ´æ */ 
  131.  gpio_set_value(dev->cs_gpio, 1);/* Æ¬Ñ¡À­¸ß£¬ÊÍ·ÅICM20608 */ 
  132.  return ret; 
  133.  
  134. /* 
  135.  * @description : ¶ÁÈ¡icm20608Ö¸¶¨¼Ä´æÆ÷Öµ£¬¶ÁÈ¡Ò»¸ö¼Ä´æÆ÷ 
  136.  * @param - dev:  icm20608É豸 
  137.  * @param - reg:  Òª¶ÁÈ¡µÄ¼Ä´æÆ÷ 
  138.  * @return    :   ¶ÁÈ¡µ½µÄ¼Ä´æÆ÷Öµ 
  139.  */ 
  140. static unsigned char icm20608_read_onereg(struct icm20608_dev *dev, u8 reg) 
  141.  u8 data = 0; 
  142.  icm20608_read_regs(dev, reg, &data, 1); 
  143.  return data; 
  144.  
  145. /* 
  146.  * @description : Ïòicm20608Ö¸¶¨¼Ä´æÆ÷дÈëÖ¸¶¨µÄÖµ£¬Ð´Ò»¸ö¼Ä´æÆ÷ 
  147.  * @param - dev:  icm20608É豸 
  148.  * @param - reg:  ÒªÐ´µÄ¼Ä´æÆ÷ 
  149.  * @param - data: ÒªÐ´ÈëµÄÖµ 
  150.  * @return   :    ÎÞ 
  151.  */  
  152.  
  153. static void icm20608_write_onereg(struct icm20608_dev *dev, u8 reg, u8 value) 
  154.  u8 buf = value; 
  155.  icm20608_write_regs(dev, reg, &buf, 1); 
  156.  
  157. /* 
  158.  * @description : ¶ÁÈ¡ICM20608µÄÊý¾Ý£¬¶ÁȡԭʼÊý¾Ý£¬°üÀ¨ÈýÖáÍÓÂÝÒÇ¡¢ 
  159.  *     : ÈýÖá¼ÓËٶȼƺÍÄÚ²¿Î¶ȡ£ 
  160.  * @param - dev : ICM20608É豸 
  161.  * @return   : ÎÞ¡£ 
  162.  */ 
  163. void icm20608_readdata(struct icm20608_dev *dev) 
  164.  unsigned char data[14]; 
  165.  icm20608_read_regs(dev, ICM20_ACCEL_XOUT_H, data, 14); 
  166.  
  167.  dev->accel_x_adc = (signed short)((data[0] << 8) | data[1]);  
  168.  dev->accel_y_adc = (signed short)((data[2] << 8) | data[3]);  
  169.  dev->accel_z_adc = (signed short)((data[4] << 8) | data[5]);  
  170.  dev->temp_adc    = (signed short)((data[6] << 8) | data[7]);  
  171.  dev->gyro_x_adc  = (signed short)((data[8] << 8) | data[9]);  
  172.  dev->gyro_y_adc  = (signed short)((data[10] << 8) | data[11]); 
  173.  dev->gyro_z_adc  = (signed short)((data[12] << 8) | data[13]); 
  174.  
  175. /* 
  176.  * @description  : ´ò¿ªÉ豸 
  177.  * @param - inode  : ´«µÝ¸øÇý¶¯µÄinode 
  178.  * @param - filp  : É豸Îļþ£¬file½á¹¹ÌåÓиö½Ð×öprivateate_dataµÄ³ÉÔ±±äÁ¿ 
  179.  *        Ò»°ãÔÚopenµÄʱºò½«private_dataËÆÓÐÏòÉ豸½á¹¹Ìå¡£ 
  180.  * @return    : 0 ³É¹¦;ÆäËû Ê§°Ü 
  181.  */ 
  182. static int icm20608_open(struct inode *inode, struct file *filp) 
  183.  filp->private_data = &icm20608dev; /* ÉèÖÃ˽ÓÐÊý¾Ý */ 
  184.  return 0; 
  185.  
  186. /* 
  187.  * @description  : ´ÓÉ豸¶ÁÈ¡Êý¾Ý  
  188.  * @param - filp  : Òª´ò¿ªµÄÉ豸Îļþ(ÎļþÃèÊö·û) 
  189.  * @param - buf  : ·µ»Ø¸øÓû§¿Õ¼äµÄÊý¾Ý»º³åÇø 
  190.  * @param - cnt  : Òª¶ÁÈ¡µÄÊý¾Ý³¤¶È 
  191.  * @param - offt  : Ïà¶ÔÓÚÎļþÊ×µØÖ·µÄÆ«ÒÆ 
  192.  * @return    : ¶ÁÈ¡µÄ×Ö½ÚÊý£¬Èç¹ûΪ¸ºÖµ£¬±íʾ¶Áȡʧ°Ü 
  193.  */ 
  194. static ssize_t icm20608_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off
  195.  signed int data[7]; 
  196.  long err = 0; 
  197.  struct icm20608_dev *dev = (struct icm20608_dev *)filp->private_data; 
  198.  
  199.  icm20608_readdata(dev); 
  200.  data[0] = dev->gyro_x_adc; 
  201.  data[1] = dev->gyro_y_adc; 
  202.  data[2] = dev->gyro_z_adc; 
  203.  data[3] = dev->accel_x_adc; 
  204.  data[4] = dev->accel_y_adc; 
  205.  data[5] = dev->accel_z_adc; 
  206.  data[6] = dev->temp_adc; 
  207.  err = copy_to_user(buf, data, sizeof(data)); 
  208.  return 0; 
  209.  
  210. /* 
  211.  * @description  : ¹Ø±Õ/ÊÍ·ÅÉ豸 
  212.  * @param - filp  : Òª¹Ø±ÕµÄÉ豸Îļþ(ÎļþÃèÊö·û) 
  213.  * @return    : 0 ³É¹¦;ÆäËû Ê§°Ü 
  214.  */ 
  215. static int icm20608_release(struct inode *inode, struct file *filp) 
  216.  return 0; 
  217.  
  218. /* icm20608²Ù×÷º¯Êý */ 
  219. static const struct file_operations icm20608_ops = { 
  220.  .owner = THIS_MODULE, 
  221.  .open = icm20608_open, 
  222.  .read = icm20608_read, 
  223.  .release = icm20608_release, 
  224. }; 
  225.  
  226. /* 
  227.  * ICM20608ÄÚ²¿¼Ä´æÆ÷³õʼ»¯º¯Êý  
  228.  * @param   : ÎÞ 
  229.  * @return  : ÎÞ 
  230.  */ 
  231. void icm20608_reginit(void) 
  232.  u8 value = 0; 
  233.   
  234.  icm20608_write_onereg(&icm20608dev, ICM20_PWR_MGMT_1, 0x80); 
  235.  mdelay(50); 
  236.  icm20608_write_onereg(&icm20608dev, ICM20_PWR_MGMT_1, 0x01); 
  237.  mdelay(50); 
  238.  
  239.  value = icm20608_read_onereg(&icm20608dev, ICM20_WHO_AM_I); 
  240.  printk("ICM20608 ID = %#X\r\n", value);  
  241.  
  242.  icm20608_write_onereg(&icm20608dev, ICM20_SMPLRT_DIV, 0x00);  /* Êä³öËÙÂÊÊÇÄÚ²¿²ÉÑùÂÊ     */ 
  243.  icm20608_write_onereg(&icm20608dev, ICM20_GYRO_CONFIG, 0x18);  /* ÍÓÂÝÒDZ2000dpsÁ¿³Ì     */ 
  244.  icm20608_write_onereg(&icm20608dev, ICM20_ACCEL_CONFIG, 0x18);  /* ¼ÓËٶȼƱ16GÁ¿³Ì      */ 
  245.  icm20608_write_onereg(&icm20608dev, ICM20_CONFIG, 0x04);   /* ÍÓÂÝÒǵÍͨÂ˲¨BW=20Hz     */ 
  246.  icm20608_write_onereg(&icm20608dev, ICM20_ACCEL_CONFIG2, 0x04); /* ¼ÓËٶȼƵÍͨÂ˲¨BW=21.2Hz    */ 
  247.  icm20608_write_onereg(&icm20608dev, ICM20_PWR_MGMT_2, 0x00);  /* ´ò¿ª¼ÓËٶȼƺÍÍÓÂÝÒÇËùÓÐÖá     */ 
  248.  icm20608_write_onereg(&icm20608dev, ICM20_LP_MODE_CFG, 0x00);  /* ¹Ø±ÕµÍ¹¦ºÄ       */ 
  249.  icm20608_write_onereg(&icm20608dev, ICM20_FIFO_EN, 0x00);  /* ¹Ø±ÕFIFO      */ 
  250.  
  251.  /* 
  252.   * @description     : spiÇý¶¯µÄprobeº¯Êý£¬µ±Çý¶¯Óë 
  253.   *                    É豸ƥÅäÒÔºó´Ëº¯Êý¾Í»áÖ´ÐР
  254.   * @param - client  : spiÉ豸 
  255.   * @param - id      : spiÉ豸ID 
  256.   *  
  257.   */  
  258. static int icm20608_probe(struct spi_device *spi) 
  259.  int ret = 0; 
  260.  
  261.  /* 1¡¢¹¹½¨É豸ºÅ */ 
  262.  if (icm20608dev.major) { 
  263.   icm20608dev.devid = MKDEV(icm20608dev.major, 0); 
  264.   register_chrdev_region(icm20608dev.devid, ICM20608_CNT, ICM20608_NAME); 
  265.  } else { 
  266.   alloc_chrdev_region(&icm20608dev.devid, 0, ICM20608_CNT, ICM20608_NAME); 
  267.   icm20608dev.major = MAJOR(icm20608dev.devid); 
  268.  } 
  269.  
  270.  /* 2¡¢×¢²áÉ豸 */ 
  271.  cdev_init(&icm20608dev.cdev, &icm20608_ops); 
  272.  cdev_add(&icm20608dev.cdev, icm20608dev.devid, ICM20608_CNT); 
  273.  
  274.  /* 3¡¢´´½¨Àà */ 
  275.  icm20608dev.class = class_create(THIS_MODULE, ICM20608_NAME); 
  276.  if (IS_ERR(icm20608dev.class)) { 
  277.   return PTR_ERR(icm20608dev.class); 
  278.  } 
  279.  
  280.  /* 4¡¢´´½¨É豸 */ 
  281.  icm20608dev.device = device_create(icm20608dev.class, NULL, icm20608dev.devid, NULL, ICM20608_NAME); 
  282.  if (IS_ERR(icm20608dev.device)) { 
  283.   return PTR_ERR(icm20608dev.device); 
  284.  } 
  285.  
  286.  /* »ñÈ¡É豸Ê÷ÖÐcsƬѡÐźŠ*/ 
  287.  icm20608dev.nd = of_find_node_by_path("/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02010000"); 
  288.  if(icm20608dev.nd == NULL) { 
  289.   printk("ecspi3 node not find!\r\n"); 
  290.   return -EINVAL; 
  291.  }  
  292.  
  293.  /* 2¡¢ »ñÈ¡É豸Ê÷ÖеÄgpioÊôÐÔ£¬µÃµ½BEEPËùʹÓõÄBEEP±àºÅ */ 
  294.  icm20608dev.cs_gpio = of_get_named_gpio(icm20608dev.nd, "cs-gpio", 0); 
  295.  if(icm20608dev.cs_gpio < 0) { 
  296.   printk("can't get cs-gpio"); 
  297.   return -EINVAL; 
  298.  } 
  299.  
  300.  /* 3¡¢ÉèÖÃGPIO1_IO20ΪÊä³ö£¬²¢ÇÒÊä³ö¸ßµçƽ */ 
  301.  ret = gpio_direction_output(icm20608dev.cs_gpio, 1); 
  302.  if(ret < 0) { 
  303.   printk("can't set gpio!\r\n"); 
  304.  } 
  305.  
  306.  /*³õʼ»¯spi_device */ 
  307.  spi->mode = SPI_MODE_0; /*MODE0£¬CPOL=0£¬CPHA=0*/ 
  308.  spi_setup(spi); 
  309.  icm20608dev.private_data = spi; /* ÉèÖÃ˽ÓÐÊý¾Ý */ 
  310.  
  311.  /* ³õʼ»¯ICM20608ÄÚ²¿¼Ä´æÆ÷ */ 
  312.  icm20608_reginit();   
  313.  return 0; 
  314.  
  315. /* 
  316.  * @description     : spiÇý¶¯µÄremoveº¯Êý£¬ÒƳýspiÇý¶¯µÄʱºò´Ëº¯Êý»áÖ´ÐР
  317.  * @param - client  : spiÉ豸 
  318.  * @return          : 0£¬³É¹¦;ÆäËû¸ºÖµ,ʧ°Ü 
  319.  */ 
  320. static int icm20608_remove(struct spi_device *spi) 
  321.  /* É¾³ýÉ豸 */ 
  322.  cdev_del(&icm20608dev.cdev); 
  323.  unregister_chrdev_region(icm20608dev.devid, ICM20608_CNT); 
  324.  
  325.  /* ×¢ÏúµôÀàºÍÉ豸 */ 
  326.  device_destroy(icm20608dev.class, icm20608dev.devid); 
  327.  class_destroy(icm20608dev.class); 
  328.  return 0; 
  329.  
  330. /* ´«Í³Æ¥Å䷽ʽIDÁбí */ 
  331. static const struct spi_device_id icm20608_id[] = { 
  332.  {"alientek,icm20608", 0},   
  333.  {} 
  334. }; 
  335.  
  336. /* É豸Ê÷Æ¥ÅäÁбí */ 
  337. static const struct of_device_id icm20608_of_match[] = { 
  338.  { .compatible = "alientek,icm20608" }, 
  339.  { /* Sentinel */ } 
  340. }; 
  341.  
  342. /* SPIÇý¶¯½á¹¹Ìå */  
  343. static struct spi_driver icm20608_driver = { 
  344.  .probe = icm20608_probe, 
  345.  .remove = icm20608_remove, 
  346.  .driver = { 
  347.    .owner = THIS_MODULE, 
  348.       .name = "icm20608"
  349.       .of_match_table = icm20608_of_match,  
  350.      }, 
  351.  .id_table = icm20608_id, 
  352. }; 
  353.       
  354. /* 
  355.  * @description : Çý¶¯Èë¿Úº¯Êý 
  356.  * @param   : ÎÞ 
  357.  * @return   : ÎÞ 
  358.  */ 
  359. static int __init icm20608_init(void) 
  360.  return spi_register_driver(&icm20608_driver); 
  361.  
  362. /* 
  363.  * @description : Çý¶¯³ö¿Úº¯Êý 
  364.  * @param   : ÎÞ 
  365.  * @return   : ÎÞ 
  366.  */ 
  367. static void __exit icm20608_exit(void) 
  368.  spi_unregister_driver(&icm20608_driver); 
  369.  
  370. module_init(icm20608_init); 
  371. module_exit(icm20608_exit); 
  372. MODULE_LICENSE("GPL"); 
  373. MODULE_AUTHOR(yikoulinux"); 


±¾ÎÄתÔØ×ÔÍøÂ磬ԭÎÄÁ´½Ó£ºhttps://mp.weixin.qq.com/s/KHU9yuQJ_WvptWkpyub--g
±¾Õ¾²¿·ÖÄÚÈÝתÔØÓÚÍøÂ磬°æȨ¹éÔ­×÷ÕßËùÓУ¬×ªÔØ֮ĿµÄÔÚÓÚ´«²¥¸ü¶àÓÅÐã¼¼ÊõÄÚÈÝ£¬ÈçÓÐÇÖȨÇëÁªÏµQQ/΢ÐÅ£º153890879ɾ³ý£¬Ð»Ð»£¡

ÍƼöͼÎÄ

  • ÖÜÅÅÐÐ
  • ÔÂÅÅÐÐ
  • ×ÜÅÅÐÐ

Ëæ»úÍƼö