imx6 sai cyclic dma

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

imx6 sai cyclic dma

Jump to solution
753 Views
andrwebb
Contributor II

So im trying to set up a cyclic transfer to/from the sai2 fifo on the imx6, but my tx and rx complete callbacks only seem to be called twice before the transfer just seems to be haulted, my sai2 register configurations and dmaengine code are below, any tips would be appreciated:

Sai2 registers(set up for external bit clock):

tcsr: 3491171329
tcr1: 26
tcr2: 0
tcr3: 65536
tcr4: 458801
tcr5: 522133248
tmr: 4294967292
rcr2: 1073741824
mclk: 0

Dmaengine code:

 

 

#define HARDWARE_BUFFER_BYTES 64*2 //* 2
#define HARDWARE_BUFFER_PERIOD_BYTES 32*2 

static int imx_tx_pingdma_init(struct pi_dma *master, struct device *dev)
{
	int err;

	dma_addr_t pcm_hardware_reg_base;
	const __be32 *addr;
	addr = of_get_address(dev->of_node, 0, NULL, NULL);
	if (!addr) {
		dev_err(dev, "could not get pcm hardware register address\n");
	}
	pcm_hardware_reg_base = be32_to_cpup(addr);
	master->dma_tx = dma_request_slave_channel(dev, "tx");
	if (!master->dma_tx) {
		dev_err(dev, "no tx-dma configuration found - not using dma mode\n");
		tdm_dma_release(master);
		return -1;
	}


	master->dma_rx = dma_request_slave_channel(dev, "rx");
	if (!master->dma_rx) {
		dev_err(dev, "no rx-dma configuration found - not using dma mode\n");
		tdm_dma_release(master);
		return -1;
	}

	/* configure DMAs */
	master->tx_ping_buffer =
		dma_alloc_coherent(master->dma_tx->device->dev,
		HARDWARE_BUFFER_BYTES,
		&master->tx_ping_buffer_dma,
		GFP_KERNEL);

	if (!master->tx_ping_buffer) {
		dev_err(dev, "could not allocate dma address\n");
		tdm_dma_release(master);
		return -1;
	}

	memset(master->tx_ping_buffer, 0, HARDWARE_BUFFER_BYTES);

	master->rx_ping_buffer =
		dma_alloc_coherent(master->dma_rx->device->dev,
		HARDWARE_BUFFER_BYTES,
		&master->rx_ping_buffer_dma,
		GFP_KERNEL);

	if (!master->rx_ping_buffer) {
		dev_err(dev, "could not allocate rx dma address\n");
		tdm_dma_release(master);
		return -1;
	}

	memset(master->rx_ping_buffer, 0, HARDWARE_BUFFER_BYTES);
	master->dma_tx_slave_config.direction = DMA_MEM_TO_DEV;
	master->dma_tx_slave_config.dst_addr = 0x202c000 + 0x20;
	master->dma_tx_slave_config.dst_maxburst = 1;
	master->dma_tx_slave_config.dst_addr_width = 4;
	master->dma_tx_slave_config.src_addr = master->tx_ping_buffer_dma;
	master->dma_tx_slave_config.src_maxburst = 1;
	master->dma_tx_slave_config.src_addr_width = 4;

	err = dmaengine_slave_config(master->dma_tx,
		&master->dma_tx_slave_config);

	if (err < 0) {
		printk("could not setup slave_tx_config\n");
		tdm_dma_release(master);
		return err;
	}


	master->dma_rx_slave_config.direction = DMA_DEV_TO_MEM;
	master->dma_rx_slave_config.dst_addr = master->rx_ping_buffer_dma;
	master->dma_rx_slave_config.dst_maxburst = 1;
	master->dma_rx_slave_config.dst_addr_width = 4;
	master->dma_rx_slave_config.src_addr = 0x202c000 + 0xa0;
	master->dma_rx_slave_config.src_maxburst = 1;
	master->dma_rx_slave_config.src_addr_width = 4;

	err = dmaengine_slave_config(master->dma_rx,
		&master->dma_rx_slave_config);

	if (err < 0) {
		printk("could not setup slave_rx_config\n");
		tdm_dma_release(master);
		return err;
	}

	master->dma_tx_desc =
		dmaengine_prep_dma_cyclic(master->dma_tx,
		master->tx_ping_buffer_dma,
		HARDWARE_BUFFER_BYTES,
		HARDWARE_BUFFER_PERIOD_BYTES,
		DMA_MEM_TO_DEV,
		DMA_CTRL_ACK | DMA_PREP_INTERRUPT);

	if (!master->dma_tx_desc) {
		printk("could not setup dma_tx_desc\n");
		tdm_dma_release(master);
		return -1;
	}

	master->dma_rx_desc =
		dmaengine_prep_dma_cyclic(master->dma_rx,
		master->rx_ping_buffer_dma,
		HARDWARE_BUFFER_BYTES,
		HARDWARE_BUFFER_PERIOD_BYTES,
		DMA_DEV_TO_MEM,
		DMA_CTRL_ACK | DMA_PREP_INTERRUPT);

	if (!master->dma_rx_desc) {
		printk("could not setup dma_rx_desc\n");
		tdm_dma_release(master);
		return -1;
	}

	master->dma_tx_desc->callback = dma_tx_complete;
	master->dma_tx_desc->callback_param = master;

	master->dma_rx_desc->callback = dma_rx_complete;
	master->dma_rx_desc->callback_param = master;

	printk("DMA configured by success!\n");
	return 0;
}

 

Edit: Ive since tried increasing the buffer size and it seems that the cyclical dma just stops the callback as soon as it reaches the end of the buffer. i.e. if period_len=64 and buff_len is 64*1024 the dma callback will run 1024 times and it will pause.

 

 

Labels (2)
0 Kudos
1 Solution
727 Views
andrwebb
Contributor II

Figured it out. For some reason the bus clock was being disabled shortly after my machine driver finished doing calls to it. Also halting was fixed by increasing buffer size like some people did in previous threads. 

View solution in original post

0 Kudos
1 Reply
728 Views
andrwebb
Contributor II

Figured it out. For some reason the bus clock was being disabled shortly after my machine driver finished doing calls to it. Also halting was fixed by increasing buffer size like some people did in previous threads. 

0 Kudos