IMX8QXP DMA资源和使用(未完结)

拥有4个edma(Enhanced Direct Memory Access)增强型直接内存访问,

4个edma总共有96个通道, 2个分别有32和16个通道,

以spi为例,可使用dma通道,配置寄存器

 

dts配置,有TX和RX的配置,有下面两种配置方法:

lpspi3: lpspi@5a030000 { 
	compatible = "fsl,imx7ulp-spi";
	reg = <0x0 0x5a030000 0x0 0x10000>;
	interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>; 
	interrupt-parent = <&gic>;
	clocks = <&clk IMX8QXP_SPI3_CLK>,
				<&clk IMX8QXP_SPI3_IPG_CLK>;
	clock-names = "per", "ipg";
	assigned-clocks = <&clk IMX8QXP_SPI3_CLK>;
	assigned-clock-rates = <20000000>;
	power-domains = <&pd_dma2_chan7>;
	dma-names = "tx","rx";
	dmas = <&edma2 7 0 0>, <&edma2 6 0 1>;
	status = "disabled";
};

			pd_dma_lpspi3: PD_DMA_SPI_3 {
				reg = <SC_R_SPI_3>;
				#power-domain-cells = <0>;
				power-domains = <&pd_dma>;
				wakeup-irq = <339>;

				pd_dma2_chan6: PD_LPSPI3_RX {
					reg = <SC_R_DMA_2_CH6>;
					power-domains =<&pd_dma_lpspi3>;
					#power-domain-cells = <0>;
					#address-cells = <1>;
					#size-cells = <0>;

					pd_dma2_chan7: PD_LPSPI3_TX {
						reg = <SC_R_DMA_2_CH7>;
						power-domains =<&pd_dma2_chan6>;
						#power-domain-cells = <0>;
						#address-cells = <1>;
						#size-cells = <0>;
					};
				};
			};
lpspi3: lpspi@5a030000 {
	compatible = "fsl,imx7ulp-spi";
	reg = <0x0 0x5a030000 0x0 0x10000>;
	interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
	interrupt-parent = <&gic>;
	clocks = <&clk IMX8QXP_SPI3_CLK>,
				<&clk IMX8QXP_SPI3_IPG_CLK>;
	clock-names = "per", "ipg";
	assigned-clocks = <&clk IMX8QXP_SPI3_CLK>;
	assigned-clock-rates = <20000000>;
	power-domains = <&pd_dma_lpspi3>;
	dma-names = "tx","rx";
	dmas = <&edma2 7 0 0>, <&edma2 6 0 1>;
	status = "okay";
};

            pd_dma_lpspi3: PD_DMA_SPI_3 {
                reg = <SC_R_SPI_3>;
                #power-domain-cells = <0>;
                power-domains = <&pd_dma>;
            };

edma 0到3的区别:

edma3 16个,edma2 32个(用于SPI和UART),edma1 16个,edma0 32个(SAI)。

    edma2: dma-controller@5a1f0000 {
        compatible = "fsl,imx8qm-edma";
        reg = <0x0 0x5a200000 0x0 0x10000>, /* channel0 LPSPI0 rx */
              <0x0 0x5a210000 0x0 0x10000>, /* channel1 LPSPI0 tx */
              <0x0 0x5a220000 0x0 0x10000>, /* channel2 LPSPI1 rx */
              <0x0 0x5a230000 0x0 0x10000>, /* channel3 LPSPI1 tx */
              <0x0 0x5a240000 0x0 0x10000>, /* channel4 LPSPI2 rx */
              <0x0 0x5a250000 0x0 0x10000>, /* channel5 LPSPI2 tx */
              <0x0 0x5a260000 0x0 0x10000>, /* channel6 LPSPI3 rx */
              <0x0 0x5a270000 0x0 0x10000>, /* channel7 LPSPI3 tx */
              <0x0 0x5a280000 0x0 0x10000>, /* channel8 UART0 rx */
              <0x0 0x5a290000 0x0 0x10000>, /* channel9 UART0 tx */
              <0x0 0x5a2a0000 0x0 0x10000>, /* channel10 UART1 rx */
              <0x0 0x5a2b0000 0x0 0x10000>, /* channel11 UART1 tx */
              <0x0 0x5a2c0000 0x0 0x10000>, /* channel12 UART2 rx */
              <0x0 0x5a2d0000 0x0 0x10000>, /* channel13 UART2 tx */
              <0x0 0x5a2e0000 0x0 0x10000>, /* channel14 UART3 rx */
              <0x0 0x5a2f0000 0x0 0x10000>; /* channel15 UART3 tx */
        #dma-cells = <3>;
        dma-channels = <16>;
        interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 435 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 436 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 437 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>;
        interrupt-names = "edma2-chan0-rx", "edma2-chan1-tx",
                  "edma2-chan2-rx", "edma2-chan3-tx",
                  "edma2-chan4-rx", "edma2-chan5-tx",
                  "edma2-chan6-rx", "edma2-chan7-tx",
                  "edma2-chan8-rx", "edma2-chan9-tx",
                  "edma2-chan10-rx", "edma2-chan11-tx",
                  "edma2-chan12-rx", "edma2-chan13-tx",
                  "edma2-chan14-rx", "edma2-chan15-tx";
        pdomains = <&pd_dma2_chan0>, <&pd_dma2_chan1>,/* lpspi0 */
               <&pd_dma2_chan2>, <&pd_dma2_chan3>,/* lpspi1 */
               <&pd_dma2_chan4>, <&pd_dma2_chan5>,/* lpspi2 */
               <&pd_dma2_chan6>, <&pd_dma2_chan7>,/* lpspi3 */
               <&pd_dma2_chan8>, <&pd_dma2_chan9>,/* UART0 */
               <&pd_dma2_chan10>, <&pd_dma2_chan11>,/* UART1 */
               <&pd_dma2_chan12>, <&pd_dma2_chan13>,/* UART2 */
               <&pd_dma2_chan14>, <&pd_dma2_chan15>;/* UART3 */
        status = "okay";
    };

spi dma代码流程

fsl_lpspi_probe
	fsl_lpspi_dma_init
	controller->transfer_one = fsl_lpspi_transfer_one;

fsl_lpspi_dma_init
	controller->dma_tx = dma_request_slave_channel_reason(dev, "tx");
	controller->dma_rx = dma_request_slave_channel_reason(dev, "rx");

	controller->can_dma = fsl_lpspi_can_dma;
	controller->max_dma_len = FSL_LPSPI_MAX_EDMA_BYTES;	((1 << 15) - 1)

fsl_lpspi_transfer_one
	fsl_lpspi_setup_transfer
		if (fsl_lpspi_can_dma(controller, spi, t))
			fsl_lpspi->usedma = 1;
		else
			fsl_lpspi->usedma = 0;			
			
		fsl_lpspi_can_dma	
			bytes_per_word = fsl_lpspi_bytes_per_word(transfer->bits_per_word);
			if (bytes_per_word != 1 && bytes_per_word != 2 && bytes_per_word != 4)【8/16/32 bits_per_word发送使用DMA,范围应该在8~32bit】
				return false;		

		fsl_lpspi_config
			if (fsl_lpspi->usedma)
				temp = DER_TDDE | DER_RDDE;
			writel(temp, fsl_lpspi->base + IMX7ULP_DER);
		另一个比较重要的成员是bits_per_word。这个成员指定每次读写的字长,单位是比特。虽然大部分SPI接口的字长是8或者16,仍然会有一些特殊的例子。需要说明的是,如果这个成员为零的话,默认使用8作为字长。

	fsl_lpspi_set_cmd
		设置bpw,mode

	if (fsl_lpspi->usedma)
		ret = fsl_lpspi_dma_transfer(controller, fsl_lpspi, t);
	else
		ret = fsl_lpspi_pio_transfer(controller, t);

fsl_lpspi_dma_transfer
	fsl_lpspi_dma_configure
		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
		tx.direction = DMA_MEM_TO_DEV;
		tx.dst_addr = fsl_lpspi->base_phys + IMX7ULP_TDR;
		tx.dst_addr_width = buswidth;
		tx.dst_maxburst = 1;
		ret = dmaengine_slave_config(controller->dma_tx, &tx);		

疑问:
    1、发送数据可选择使用DMA方式,接收数据是使用中断的形势+dma方式吗?
    
DMA测试:
    1、发送数据,设置bits_per_word=8/16/32,查看cpu使用率,设置12/20对比发送的总体系统时间,加内核函数打印。
    2、接收数据,一样的测试。

猜你喜欢

转载自blog.csdn.net/TSZ0000/article/details/125103567