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

Reply via email to