imx6 sai cyclic dma

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 
763件の閲覧回数
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.

 

 

ラベル(2)
0 件の賞賛
1 解決策
737件の閲覧回数
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 件の賞賛
1 返信
738件の閲覧回数
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 件の賞賛