General steps for DMA operations on S3C2410

Source: Internet
Author: User
Generally, the following seven steps are required for DMA transmission in S3C2440:

I:
Int s3c2410_dma_request (unsigned int channel,
Struct s3c2410_dma_client * client,
Void * Dev)

S3c2410_dma_client is defined:
Struct s3c2410_dma_client {
Char * Name;
};
Taking the uda1314 driver as an example, the driver defines two s3c2410_dma_client
Static struct s3c2410_dma_client s3c2410iis_dma_out = {
. Name = "i2ssdo ",
};

Static struct s3c2410_dma_client s3c2410iis_dma_in = {
. Name = "i2ssdi ",
};

II:
S3c2410_dma_config (dmach_t channel, int xferunit, int dcon)

S3c2410_dma_config (dmach_t channel, int xferunit, int dcon)
Set the channel control register dconx Based on xferunit and dcon
Xferunit indicates the data size transmitted each time: 0: byte 1: Half word 2: Word

III:

int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)

Set the callback function after the corresponding DMA channel completes one DMA transmission, that is, the function that will be called after the completion of the s3c2410_dma_enqueue
The callback function must have the following format:
Typedef void (* s3c2410_dma_cbfn_t) (struct s3c2410_dma_chan *,
Void * Buf, int size,
Enum s3c2410_dma_buffresult result );
The Buf can transmit some useful data. In the uda1314 driver, the audio_buf_t struct is passed.

IV:
Int s3c2410_dma_setflags (dmach_t channel, unsigned int flags)

In driver 1314,
Flags = s3c2410_dmaf_autostart;
S3c2410_dma_setflags (Channel, flags );

V:

int s3c2410_dma_devconfig(int channel,
             enum s3c2410_dmasrc source,
             int hwcfg,
             unsigned long devaddr)

Parameter meaning:
* Source: s3c2410_dmasrc_hw: source is hardware
* S3c2410_dmasrc_mem: source is memory
*
* Hwcfg: The value for xxxstcn register,
* Bit 0: 0 = increment pointer, 1 = leave pointer
* Bit 1: 0 = soucreis AHB, 1 = soucreis APB
*
* Devaddr: physical address of the source

If the source is s3c2410_dmasrc_hw (peripheral), configure its s3c2410_dma_disrcc, s3c2410_dma_disrc, and s3c2410_dma_didstc.
If the source is s3c2410_dmasrc_mem (memory), configure its s3c2410_dma_disrcc, s3c2410_dma_didst, and s3c2410_dma_didstc.
It can be seen that in terms of addresses, only the addresses involving peripherals are configured.
Take the driver of uda1341 as an example. These values are
Source = s3c2410_dmasrc_mem;
Hwcfg = 3;
Devaddr = 0x55000010;

VI:
Void * dma_alloc_coherent (struct device * Dev, size_t size, dma_addr_t * dma_handle, int flag)

Use this function to apply for dmabuf and establish consistent ing
Take the driver of uda1314 as an example. The adjusted instance is:
Dmabuf = dma_alloc_coherent (null, dmasize, & dmaphys, gfp_kernel); (in the audio_setup_buf function)
Dmabuf is the virtual address, dmaphys is the BUS address, the virtual address is used for the driver to write the Buf, and dmaphys is used to transmit the data to DMA.
DMA is concerned with bus addresses.
The difference between the BUS address and the physical address is described here:
1) the physical address is CPU-related. Physical addresses are generated on the address signal line of the CPU. After the virtual address in the program instruction passes the field ing and page ing, a physical address is generated, which is placed on the address line of the CPU.
2) the BUS address, as the name implies, is related to the bus, that is, the BUS address line or the signal generated during the address cycle. The peripheral uses the BUS address.
3) the relationship between physical addresses and bus addresses is determined by the system design. On the X86 platform, the physical address is the same as the pci bus address. On other platforms, there may be some kind of transformation, usually linear conversion.

For example, if the CPU needs to access a unit whose physical address is 0xfa000, an access to the 0xfa000 address on the PCI bus will be generated on the X86 platform. This unit is either in memory or a storage unit on a card, or even has no corresponding memory on this address. On another platform, access generated on the PCI bus may be directed to the unit with the IP address 0x1fa000.
The above functions are used to establish consistent ing. You can use the dma_map_single function to create consistent mappings:
2. When only one buffer zone is to be transferred, use the dma_map_single function to map it.
Dma_addr_t dma_map_single (struct device * Dev, void * buffer, size_t size, Enum dma_data_direction direction)
3. Create a ing for the buffer to which the Page Structure Pointer Points. Single-page streaming ing:
Dma_addr_t dma_map_page (struct device * Dev, struct page * Page, unsigned long offset, size_t size, Enum dma_data_direction direction );
4. Scatter/aggregate ing
Int dma_map_sg (struct device * Dev, struct scatterlist * SG, int nents, Enum dma_alloc_coherent direction );
I still don't know which scenario to use streaming ing and which to use consistent ing. For S3C2440, scattered aggregation (Stream) ing is used in the MMC driver, and consistent ing is used in the audio card driver.

7:
Int s3c2410_dma_enqueue (unsigned int channel, void * ID,
Dma_addr_t data, int size)

Initiate a DMA Transmission
Parameter meaning:
* ID the device driver's ID information for this buffer
* Data the physical address of the buffer data
* Size the size of the buffer in bytes
Transmit the dmaphys obtained in dma_alloc_coherent to s3c2410_dma_enqueue. s3c2410_dma_enqueue to submit a DMA request. When the DMA channel is available, an IRQ is interrupted after the transmission is completed. The DMA interrupt service function will continue to start the request in the DMA Request queue and transmit the remaining data. ========================================================== ==== Descriptions of related functions. For your reference in the future.
Bytes --------------------------------------------------------------------------------------
Int _ init s3c24xx_dma_init_map (struct s3c24xx_dma_selection * SEL)
Initialize the dma_sel structure of the global variable. What you may be confused about in this function is:
NMAP = kmalloc (map_sz, gfp_kernel );
If (NMAP = NULL)
Return-enomem;

Memcpy (NMAP, Sel-> map, map_sz );
Memcpy (& dma_sel, Sel, sizeof (* SEL ));

Dma_sel.map = NMAP;
In these statements, why do we use memcpy to initialize to dma_sel, and assign values to dma_sel using the distributed NMAP structure. The answer is to insure, because the MAP member in dma_sel is a pointer. Be careful with pointer operations. Here, a new pointer variable is defined in this function and points to it to prevent the pointer defined elsewhere from being undone and causing a cross-border error.Access. In fact, I don't think this is necessary.

Dma_sel is defined as struct s3c24xx_dma_selection dma_sel;
Struct s3c24xx_dma_selection is defined
Struct s3c24xx_dma_selection {
Struct s3c24xx_dma_map * map;
Unsigned long map_size;
Unsigned long dcon_mask;

Void (* select) (struct s3c2410_dma_chan * Chan,
Struct s3c24xx_dma_map * map );
};

Bytes --------------------------------------------------------------------------------------------------------
Struct s3c2410_dma_chan * s3c2410_dma_map_channel (INT channel)
This functionFunctionYes: Turn the virtual channel number into a real, and un-used hardware channel.DMAChannel ing
Find the channel corresponding to the corresponding channel in the s3c2440_dma_mappings array (0--4, which is not valid), and record the ing relationship to the dma_chan_map [Channel] array.

Bytes ---------------------------------------------------------------------------------------------------------
Static int _ init s3c2410_init_dma (void)
Used to initialize the s3c2410_dma_chan structure and completeAddressIng.

Bytes -----------------------------------------------------------------------------------------------------------
Static struct s3c2410_dma_chan * lookup_dma_channel (unsigned int channel)
DMA channel Virtual/real Conversion

Bytes -----------------------------------------------------------------------------------------------------------
Int s3c2410_dma_request (unsigned int channel,
Struct s3c2410_dma_client * client,
Void * Dev)
Find the channel through the s3c2410_dma_map_channel function, andSetCorresponding channel status, application interrupted
Bytes -----------------------------------------------------------------------------------------------------------

Int s3c2410_dma_started (struct s3c2410_dma_chan * Chan)
/* If we 've only loaded one buffer onto the channel, then CHEC
* To see if we have another, and if so, try and load it so when
* The first buffer is finished, the new one will be loaded
* The channel */
Bytes -----------------------------------------------------------------------------------------------------------
Int s3c2410_dma_free (dmach_t channel, struct s3c2410_dma_client * client)
/* S3c2410_dma_free
*
* Release the given channel back to the system, will stop and flush
* Any outstanding transfers, and ensure the channel is ready for
* Next claimant.
*
* Note, although a warning is currently printed if the freeing Client
* Info is not the same as the registrant's Client info, the free is still
* Allowed to go through.
*/

Bytes --------------------------------------------------------------------------------------------------------------
Static int s3c2410_dma_flush (struct s3c2410_dma_chan * Chan)
* Stop the channel, and remove all current and pending transfers

Bytes --------------------------------------------------------------------------------------------------------------
Int s3c2410_dma_config (dmach_t channel,
Int xferunit,
Int dcon)
Set the channel control register based on xferunit
Bytes --------------------------------------------------------------------------------------------------------------
Int s3c2410_dma_setflags (dmach_t channel, unsigned int flags)
Set the channel flags according to flags
Bytes --------------------------------------------------------------------------------------------------------------
Int s3c2410_dma_devconfig (INT channel,
Enum s3c2410_dmasrc source,
Int hwcfg,
Unsigned long devaddr)
Parameter meaning:
* Source: s3c2410_dmasrc_hw: source is hardware
* S3c2410_dmasrc_mem: source is memory
*
* Hwcfg: The value for xxxstcn register,
* Bit 0: 0 = increment pointer, 1 = leave pointer
* Bit 1: 0 = soucreis AHB, 1 = soucreis APB
*
* Devaddr: physical address of the source

If the source is s3c2410_dmasrc_hw (peripheral), configure its s3c2410_dma_disrcc, s3c2410_dma_disrc, and s3c2410_dma_didstc.
If the source is s3c2410_dmasrc_mem (memory), configure its s3c2410_dma_disrcc, s3c2410_dma_didst, and s3c2410_dma_didstc.
It can be seen that in terms of addresses, only the addresses involving peripherals are configured.

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.