kernel 2.6.15: cpm_uart driver broken?
Vitaly Bordug
vbordug at ru.mvista.com
Tue Apr 18 23:22:44 EST 2006
On Tue, 18 Apr 2006 14:46:08 +0200
David Jander <david.jander at protonic.nl> wrote:
>
> 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.
>
Well, existing code works just fine on 885ads and 866ads, that use SMC1 and SMC2 as UARTs.
> 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):
That's wrong - cpm_uart_cpm1.c applies to PQ only...
>
> ....
> 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?
>
Well, since it works on other boards, and kmalloc stuff seems to sorta work as well, then I guess reason is screwed DMA thing for your board. Check/alter CONFIG_CONSISTENT_* things and see if it will help.
And, try to just replace dma_alloc_.. with kmalloc (not changing rx_buf etc.) and reproduce the same behavior you had. BTW, rx_buf and tx_buf are never used actually in the code, hereby there is no difference what values they contain...
--
Sincerely,
Vitaly
More information about the Linuxppc-embedded
mailing list