kernel 2.6.15: cpm_uart driver broken?

David Jander david.jander at protonic.nl
Tue Apr 18 22:46:08 EST 2006


Hi all,

Situation 1: MPC852T with SMC1 as uart/console, and SCC3/SCC4 as additional 
uarts. SMC1 works fine, but SCC3/4 don't. On transmission attempt, both UARTS 
transmit a byte 0x00 instead of what was intended to be transmitted.\

Situation 2: The same as above, but console on either SCC3 or SCC4. The uart 
being initialized as console works ok, the other two don't.

I'm pretty sure the following is wrong, but I can't seem to fix it either. 
This seems to apply for both PQ and PQ2 type uarts:
from drivers/serial/cpm_uart/cpm_uart_cpm1.c (line 190):

....
	if (is_con) {
		/* was hostalloc but changed cause it blows away the */
		/* large tlb mapping when pinning the kernel area    */
		mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
		dma_addr = 0;
	} else
		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
					      GFP_KERNEL);

....
	pinfo->dp_addr = dp_offset;
	pinfo->mem_addr = mem_addr;
	pinfo->dma_addr = dma_addr;

	pinfo->rx_buf = mem_addr;
....

AFAICS pinfo->rx_buf is the pointer to a buffer as seen from the CPM's point 
of view, so it should hold a physical adress, not a virtual address. It seems 
to me that it should be more like this (lines marked with ** are changed):

....
	if (is_con) {
		/* was hostalloc but changed cause it blows away the */
		/* large tlb mapping when pinning the kernel area    */
		mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
**		dma_addr = mem_addr;
	} else
		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
					      GFP_KERNEL);

....
	pinfo->dp_addr = dp_offset;
	pinfo->mem_addr = mem_addr;
	pinfo->dma_addr = dma_addr;

**	pinfo->rx_buf = dma_addr;
....

This does not work either, but I suspect this is a different problem, because 
if I change dma_alloc_coherent() for something using kmalloc() and then 
dma_addr=virt_to_phys(mem_addr), uarts begin to work, but trasmit mixed old 
and new data from the buffers due to the cache getting in the way. At least 
reception seems to work ok then. 
So, why doesn't dma_alloc_coherent() work the way one would expect?
Obviously, changing "if (is_con)" into "if (1)" all three uarts work 
correctly, but I guess we want to save on DP_RAM usage if ever possible.

What else is wrong here?

Greetings,

-- 
David Jander



More information about the Linuxppc-embedded mailing list