Linux SPI Subsystem

Source: Internet
Author: User

========================================================== ====
Author: yuanlulu

Http://blog.csdn.net/yuanlulu

No copyright, but please keep this statement for reprinting
========================================================== ====

The relationship between spi_master/spi_device and spi_driver.

 

Important data structures:

~~~~~~~~~~
The topic of the SPI controller is spi_master. Although you do not need to write your own SPI controller driver, it is necessary to understand this struct.

Struct spi_master {<br/> struct device dev; </P> <p> S16 bus_num; // bus number, starting from scratch </P> <p> 2010num_chipselect; // The number of supported parts. The number of parts selected from the device cannot exceed this number </P> <p>/* setup mode and clock, etc (SPI driver may call timed times) */<br/> int (* setup) (struct spi_device * SPI); // update the hardware configuration based on the SPI device. </P> <p> int (* Transfer) (struct spi_device * SPI, struct spi_message * mesg); // Method for adding a message to a queue. This function cannot be sleep. It is responsible for arranging the transfer and calling the registered callback function complete (). </P> <p>/* called on release () to free memory provided by spi_master */<br/> void (* cleanup) (struct spi_device * SPI ); // The cleanup function is called in the spidev_release function, and spidev_release is registered as the SPI Dev release function. <Br/>}; </P> <p>

The driver of the SPI controller is generally declared in arch/.../Mach-*/board-*. C, register a platform device, and then create a platform driver under driver/SPI.
Spi_master will scan ARCH /... /Mach-*/board -*. in C, the spi_register_board_info registration information is called to create a spi_device for each information with the same number as the local bus.
Based on the driver model of the Linux kernel, the drivers and devices registered under the same bus match each other. Spi_bus_type indicates the name of the bus. In this way, when the name of your own spi_driver and spi_device is the same,
The probe method of spi_driver will be called. The spi_driver will be able to see the matching spi_device.

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~
Struct spi_driver {<br/> int (* probe) (struct spi_device * SPI); // this method is called after successful match with SPI. Therefore, this method requires device and private data initialization. <Br/> int (* remove) (struct spi_device * SPI); // unbind spi_device from spi_driver and release resources applied by probe. <Br/> void (* shutdown) (struct spi_device * SPI); // close <br/> int (* suspend) (struct spi_device * SPI, pm_message_t mesg ); // suspend <br/> int (* resume) (struct spi_device * SPI); // restore <br/> struct device_driver driver; <br/>}; <br/>

This struct is an auxiliary data structure. It mainly provides binding methods and power management interfaces under the driver model. The driver. Name is the basis for matching with spi_device.
The purpose of this structure is to bind ARCH/.../Mach-*/board-*. C to the spi_device corresponding to the information registered by spi_register_board_info.
An example in the kernel is as follows.

 

Static struct spi_driver tle62x0_driver ={< br/>. driver ={< br/>. name = "tle62x0", <br/>. owner = this_module, <br/>}, <br/>. probe = tle62x0_probe, <br/>. remove = _ devexit_p (tle62x0_remove), <br/>}; </P> <p> static _ init int tle62x0_init (void) <br/>{< br/> return spi_register_driver (& tle62x0_driver); <br/>}</P> <p> static _ exit void tle62x0_exit (void) <br/>{< br/> spi_unregister_driver (& tle62x0_driver); <br/>}</P> <p>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Struct spi_device {<br/> struct device dev; <br/> struct spi_master * master; // corresponding controller pointer <br/> u32 max_speed_hz; // SPI communication clock <br/> u8 chip_select; // chip number, used to differentiate devices on the same master controller. <Br/> u8 mode; // The definitions are as follows: Transmission Mode and chip polarity. <Br/> # define spi_cpha 0x01/* Clock Phase */<br/> # define spi_cpol 0x02/* Clock polarity */<br/> # define spi_mode_0 (0 | 0) /* (original Microwire) */<br/> # define spi_mode_1 (0 | spi_cpha) <br/> # define spi_mode_2 (spi_cpol | 0) <br/> # define spi_mode_3 (spi_cpol | spi_cpha) <br/> # define spi_cs_high 0x04/* chipselect active high? */The chip selection potential is high <br/> # define spi_lsb_first 0x08/* per-word bits-on-wire */output low bit first <br/> # define spi_3wire 0 x 10/* Si/so signals shared */input/output shared interface, at this time, only half duplex is allowed. <Br/> # define spi_loop 0x20/* loopback mode */Write-back/echo mode <br/> u8 bits_per_word; // The number of BITs for each character length. <Br/> int IRQ; // used interrupt <br/> void * controller_state; <br/> void * controller_data; <br/> char modalias [32]; // name. <Br/>}; </P> <p> ~~~~~~~~~~~~~~~~~~~~~~~ <Br/> This struct describes the device information. <Br/> struct spi_board_info {<br/> char modalias [32]; // device name <br/> const void * platform_data; // Platform Data <br/> void * controller_data; <br/> int IRQ; // interrupt </P> <p>/* slower Signaling on noisy or low voltage boards */<br/> u32 max_speed_hz; // communication clock </P> <p> 2010bus_num; // bus number <br/> 2010chip_select; // chip selection number </P> <p> u8 mode; // refer to the member in spi_device <br/>}; </P> <p>

 

 

How to write an SPI driver? (Device driver, which does not involve the driver of the SPI Controller)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Static Declaration
======
Declare from Device
-----------------
ARCH/.../Mach-*/board-*. c generally contains the following statements:
 Static struct ads7846_platform_data ads_info ={< br/>. vref_delay_usecs = 100, <br/>. x_plate_ohms = 580, <br/>. y_plate_ohms = 410, <br/>}; </P> <p> static struct spi_board_info [] _ initdata ={< br/>{< br/>. modalias = "ads7846", <br/>. platform_data = & ads_info, <br/>. mode = spi_mode_0, <br/>. IRQ = gpio_irq (31), <br/>. max_speed_hz= 120000/* max sample rate at 3 V */* 16, <br/>. bus_num = 1, <br/>. chip_select = 0, <br/>}, <br/>}; </P> <p>

Use the following function to register the information declared above (registered to the SPI subsystem ):
Spi_register_board_info (spi_board_info, array_size (spi_board_info ));
This static registration does not need to be canceled.
Write driver
-------------
The SPI communication driver is very similar to the platform device driver.
Static struct spi_driver chip_driver ={< br/>. driver ={< br/>. name = "chip", <br/>. owner = this_module, <br/>}, </P> <p>. probe = chip_probe, <br/>. remove = _ devexit_p (chip_remove), <br/>. suspend = chip_suspend, <br/>. resume = chip_resume, <br/>}; </P> <p>

The driver core binds the device with the modalias member of board_info as "chip" and the driver.
The probe code should be as follows:
Static int _ devinit chip_probe (struct spi_device * SPI) <br/>{< br/> struct chip * chip; <br/> struct chip_platform_data * pdata; </P> <p>/* Assuming the driver requires board-specific data: */<br/> pdata = & SPI-> Dev. platform_data; <br/> If (! Pdata) <br/> return-enodev; </P> <p>/* Get memory for driver's per-chip state */<br/> chip = kzarloc (sizeof * chip, gfp_kernel ); // apply for memory space for your own struct. <Br/> If (! Chip) <br/> return-enomem; <br/> spi_set_drvdata (SPI, Chip); </P> <p>... ETC/other sentences. <Br/> return 0; <br/>}</P> <p>

Probe initializes private data. Then you can use the spi_device obtained by probe to communicate with the device. Spi_driver is not required for communication.
The spi_driver struct is only used to get the pointer of the driver and manage the power supply;
Using the input subsystem or hybrid device on the spi_driver is irrelevant to the SPI itself.
Spi_device is the lower bound of the driver. The upper bound includes sysfs, input subsystem, ALSA, network layer, MTD, character device framework, and other Linux subsystems.

Non-static Declaration
======
The static Declaration is that the SPI device can be determined at kernel compilation. However, sometimes it is impossible to determine when the kernel is compiled. when the device is added, no one wants to modify the kernel and re-compile it.
As we mentioned above, the SPI communication process does not require spi_driver, so we only need to establish our spi_device.
Spi_busnum_to_master () can return the spi_master pointer Based on the bus number. The prototype is as follows:
Struct spi_master * spi_busnum_to_master (2010bus_num );
First, obtain the spi_master pointer Based on the Controller number to be used (which controller corresponding to the hardware is related to the controller driver), and then define the spi_board_info as in the static declaration,
Finally, call struct spi_device * spi_new_device (struct spi_master * master, struct spi_board_info * chip) to apply for and register the device. Returning a non-null pointer means you can use
The returned spi_device pointer is used for communication. Note: The Code shows that spi_new_device Cannot initialize the bits_per_word member of spi_device. Therefore, this length is also defined after spi_device is obtained.
After the device is removed, use spi_unregister_device () to cancel the device ().

 

How to communicate
~~~~
Use encapsulated Interfaces
============================
Static inline int
Spi_write (struct spi_device * SPI, const u8 * Buf, size_t Len); // synchronous write, possibly sleep. Zero is returned for success, and negative is returned for failure.
Static inline int
Spi_read (struct spi_device * SPI, u8 * Buf, size_t Len) // synchronous read, write, and sleep. Zero is returned for success, and negative is returned for failure.
Extern int spi_write_then_read (struct spi_device * SPI, const u8 * txbuf, unsigned n_tx, u8 * rxbuf, unsigned n_rx); // sleep is possible.
Write n_tx bytes and then read n_rx bytes. Zero is returned for success, and negative is returned for failure. The number of Read and Write bytes cannot exceed 32.
Static inline ssize_t spi_w8r8 (struct spi_device * SPI, u8 cmd) // encapsulate the previous function. Write 8 bits and then read 8 bits.
Static inline ssize_t spi_w8r16 (struct spi_device * SPI, u8 cmd) // write 8 bit and then read 16 bit.

Original Interface
======================
Static inline int
Spi_async (struct spi_device * SPI, struct spi_message * message); // asynchronous read/write. It can be called in sleep-free context.
Extern int spi_sync (struct spi_device * SPI, struct spi_message * message); // synchronous read/write. Sleep and cannot be used in interrupt context. All synchronous SPI transmission interfaces are encapsulated.
The following describes spi_message.

Spi_message
~~~~~~~
Struct spi_message {<br/> struct list_head transfers; // queue of the transmission segment of the message. A message can contain multiple transmission segments. </P> <p> struct spi_device * SPI; // destination device for transmission </P> <p> unsigned is_dma_mapped: 1; // if true, this call provides DMA and CPU virtual addresses. </P> <p>/* completion is reported through a callback */<br/> void (* Complete) (void * context ); // callback function after asynchronous call <br/> void * context; // callback function parameter <br/> unsigned actual_length; // the actual length of the transfer <br/> int status; // The result of execution. 0 is set successfully. Otherwise, it is a negative error code. </P> <p> struct list_head queue; // The following two members are selected for the driver that owns the message. Spi_master will use them. You 'd better not use it yourself. <Br/> void * State; <br/>}; </P> <p>

Spi_message is used for atomic execution of an array transmission request represented by spi_transfer.
This transmission queue is atomic, which means that no other message occupies the bus before the message is completed.
Messages are always executed in FIFO order.
The code that submits spi_message to the underlying layer is responsible for managing its memory space. The initialization memory is not displayed and must be initialized using 0.
 
Spi_transfer
----------------
As shown above, a spi_message is composed of multiple spi_transfer instances.
Each spi_transfer always reads the number of bits of the same length as the write, but it is easy to use a null pointer to discard the read or write.
The memory allocated for spi_transfer and spi_message should be complete during message processing.

Struct spi_transfer {<br/>/* it's OK if tx_buf = rx_buf (right ?) <Br/> * for Microwire, one buffer must be null <br/> * buffers must work with DMA _ * map_single () CILS, unless <br/> * spi_message.is_dma_mapped reports a pre-existing mapping <br/> */<br/> const void * tx_buf; // The data to be written to the device (which must be dma_safe) or null. <br/> void * rx_buf; // data buffer to be read (must be dma_safe) or null. <br/> unsigned Len; // the size of TX and Rx (number of bytes ). Here we don't mean its sum, but their respective lengths. They are always equal. </P> <p> dma_addr_t tx_dma; // If spi_message.is_dma_mapped is true, this is the DMA address of TX. <br/> dma_addr_t rx_dma; // If the token is true, this is the DMA address of RX </P> <p> unsigned cs_change: 1; // affects the selection of slices after this transmission. Indicates whether to reselect a new part after the end of this transfer and call setup to change the settings. This flag can reduce system overhead. <Br/> u8 bits_per_word; // Number of BITs for each character length. If it is 0, use the default value <br/> delay_usecs; // the delay between the end of the transfer and the change of the selected part. Then, another transmission is started or the entire message is ended. <Br/> u32 speed_hz; // communication clock. If it is 0, use the default value </P> <p> struct list_head transfer_list; // The bidirectional linked list node to be connected. <Br/>}; </P> <p>

The Controller Driver First writes the Tx data and then reads the data of the same length. The Length indicates Len.
If tx_buff is a null pointer, 0 is output when rx_buff is filled (to generate the received clock). If rx_buff is null, the received data is discarded.
Only long-read Len data is output and received.
The output length is incorrect (for example, when the word length is 2 bytes, three bytes are output, and the last byte cannot be a whole word ).

The data in the local memory always uses the byte order of the local CPU, whether the byte order of SPI is large or short (using spi_lsb_firs)
When the word length of spi_transfer is not an integer multiple of the power of 8 bits, these data words contain extended bits. In the SPI communication driver's view, the data in the memory is always
Alignment, so the RX median definition and the bit not used in RX are always the highest valid bit. (For example, the character length of 13 bit, each word occupies 2 bytes, and Rx and TX should be stored in this way)

All SPI transmission starts with enabling the relevant chip line selection. Generally, the Slice Line Selection remains valid before the end of the message. The driver can use
The cs_change member in spi_transfer affects slice selection:
(I) If transfer is not the last message, this flag can conveniently set the slice to an invalid status.
Sometimes this method is required to inform the chip of the end of a command and enable the chip to complete this batch of processing tasks.
(Ii) When the trasfer is the last one, the slice will always be valid and the next transfer will arrive.
There is no way to prevent other devices from receiving data on the bus of the Multi-SPI slave machine. This method can be used as a special prompt. To start transmitting information to another device, you must first
The chip selection is invalid. However, in other cases, this ensures correctness. The information behind some devices depends on the previous information and is required after a processing sequence is complete.
Disable the slice line selection.
The above paragraph is translated and cannot be understood.
Besides, cs_change affects whether to disable the Line Selection and call setup to change the configuration after the transfer is completed. (This flag is used to change the chip select change option)
In no special case, a spi_message is set to this flag in the last transfer.

 

 

 

 

 

Spi_message function interface
-------------------------------
Static inline void spi_message_init (struct spi_message * m); // initialization, which is actually filled with 0 and initialized to the linked list node.
Static inline void
Spi_message_add_tail (struct spi_transfer * t, struct spi_message * m); // Add transfer to the end of the message linked list.
Static inline void
Spi_transfer_del (struct spi_transfer * t); // remove transfer from the message linked list
Static inline struct spi_message * spi_message_alloc (unsigned ntrans, gfp_t flags); // create a message and create ntrans transfer and add it to the linked list. flag indicates the memory usage.
Static inline void spi_message_free (struct spi_message * m); // release the message.

Bits_per_word
-----------------------
Bits_per_word is defined in spi_device and spi_transfer.
The SPI controller driver first uses the definition in spi_transfer. If its value is 0, the default value is used, that is, the bits_per_word definition of spi_device. If it is also zero, the default value is 8 (BIT ).

No bits_per_word is defined in spi_board_info, and no encapsulation interface functions such as spi_write/spi_read have initialized this variable. Therefore, if the length of 8 characters cannot meet the requirements, you should initialize the bits_per_word of spi_device explicitly, or use
The original interface and initialize the bits_per_word member of spi_transfer.
,

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.