On Thu, Jan 22, 2015 at 4:44 PM, Julien Grall <[email protected]>
wrote:
>
> Hi Iurii,
Hi Julien,
It's Oleksandr. Thank you for your comments.
>
>
> On 21/01/15 14:16, Iurii Konovalenko wrote:
> > diff --git a/xen/drivers/char/rcar2-uart.c
b/xen/drivers/char/rcar2-uart.c
> > +static void rcar2_uart_interrupt(int irq, void *data, struct
cpu_user_regs *regs)
> > +{
> > + struct serial_port *port = data;
> > + struct rcar2_uart *uart = port->uart;
> > + uint16_t status, ctrl;
> > +
> > + ctrl = rcar2_readw(uart, SCIF_SCSCR);
> > + status = rcar2_readw(uart, SCIF_SCFSR) & ~SCFSR_TEND;
> > + /* Ignore next flag if TX Interrupt is disabled */
> > + if ( !(ctrl & SCSCR_TIE) )
> > + status &= ~SCFSR_TDFE;
> > +
> > + while ( status != 0 )
> > + {
> > + /* TX Interrupt */
> > + if ( status & SCFSR_TDFE )
> > + {
> > + serial_tx_interrupt(port, regs);
> > +
> > + if ( port->txbufc == port->txbufp )
> > + {
> > + /*
> > + * There is no data bytes to send. We have to disable
> > + * TX Interrupt to prevent us from getting stuck in the
> > + * interrupt handler
> > + */
> > + ctrl = rcar2_readw(uart, SCIF_SCSCR);
> > + ctrl &= ~SCSCR_TIE;
> > + rcar2_writew(uart, SCIF_SCSCR, ctrl);
> > + }
>
> serial_start_tx and serial_stop_tx callback have been recently
> introduced to start/stop transmission.
>
> I think you could use them to replace this if (and maybe some others).
Am I right that you are speaking about this patch "[PATCH v1] xen/arm:
Manage pl011 uart TX interrupt correctly"?
http://www.gossamer-threads.com/lists/xen/devel/359033
I will rewrite code to use these callbacks.
>
>
> [..]
>
> > +static void __init rcar2_uart_init_preirq(struct serial_port *port)
> > +{
> > + struct rcar2_uart *uart = port->uart;
> > + unsigned int divisor;
> > + uint16_t val;
> > +
> > + /*
> > + * Wait until last bit has been transmitted. This is needed for a
smooth
> > + * transition when we come from early printk
> > + */
> > + while ( !(rcar2_readw(uart, SCIF_SCFSR) & SCFSR_TEND) );
>
> Would it be possible that it get stucks forever?
I don't think so. We just waiting for transmission to end. But anyway, I
can break this loop by timeout.
>
> [..]
>
> > + ASSERT( uart->clock_hz > 0 );
> > + if ( uart->baud != BAUD_AUTO )
> > + {
> > + /* Setup desired Baud rate */
> > + divisor = uart->clock_hz / (uart->baud << 4);
> > + ASSERT( divisor >= 1 && divisor <= (uint16_t)UINT_MAX );
> > + rcar2_writew(uart, SCIF_DL, (uint16_t)divisor);
> > + /* Selects the frequency divided clock (SC_CLK external input)
*/
> > + rcar2_writew(uart, SCIF_CKS, 0);
> > + /*
> > + * TODO: should be uncommented
> > + * udelay(1000000 / uart->baud + 1);
> > + */
>
> Why didn't you uncommented?
Ah, I just recollected about this. This is due to driver get stucks in
udelay().
http://lists.xen.org/archives/html/xen-devel/2014-10/msg01935.html
Now, we come from U-Boot with arch timer enabled.
I will try your suggestion (about moving init_xen_time() before
console_init_preirq()) again.
I hope that we can uncomment this call.
>
> [..]
>
> > +static int rcar2_uart_tx_ready(struct serial_port *port)
> > +{
> > + struct rcar2_uart *uart = port->uart;
> > + uint16_t cnt;
> > +
> > + /* Check for empty space in TX FIFO */
> > + if ( !(rcar2_readw(uart, SCIF_SCFSR) & SCFSR_TDFE) )
> > + return 0;
> > +
> > + /*
> > + * It seems that the Framework has a data bytes to send.
> > + * Enable TX Interrupt disabled from interrupt handler before
> > + */
> > + if ( uart->irq_en )
> > + rcar2_writew(uart, SCIF_SCSCR, rcar2_readw(uart, SCIF_SCSCR) |
> > + SCSCR_TIE);
>
> I think you can replace it by implementing the callback start_tx.
ok.
>
> [..]
>
> > +static int __init rcar2_uart_init(struct dt_device_node *dev,
> > + const void *data)
> > +{
> > + const char *config = data;
> > + struct rcar2_uart *uart;
> > + int res;
> > + u64 addr, size;
> > +
> > + if ( strcmp(config, "") )
> > + printk("WARNING: UART configuration is not supported\n");
> > +
> > + uart = &rcar2_com;
> > +
> > + uart->clock_hz = SCIF_CLK_FREQ;
> > + uart->baud = BAUD_AUTO;
> > + uart->data_bits = 8;
> > + uart->parity = PARITY_NONE;
> > + uart->stop_bits = 1;
> > +
> > + res = dt_device_get_address(dev, 0, &addr, &size);
> > + if ( res )
> > + {
> > + printk("rcar2-uart: Unable to retrieve the base"
> > + " address of the UART\n");
> > + return res;
> > + }
> > +
> > + uart->regs = ioremap_nocache(addr, size);
> > + if ( !uart->regs )
> > + {
> > + printk("rcar2-uart: Unable to map the UART memory\n");
> > + return -ENOMEM;
> > + }
> > +
> > + res = platform_get_irq(dev, 0);
> > + if ( res < 0 )
> > + {
> > + printk("rcar2-uart: Unable to retrieve the IRQ\n");
> > + return res;
>
> if platform_get_irq fails, the driver will leak the mapping made with
> ioremap_cache. I would invert the 2 call:
>
> res = platform_get_irq(dev, 0);
> if ( res < 0 )
> ...
>
> uart->regs = ioremap_nocache(addr, size);
> if ( !uart->regs )
Sounds reasonable. ok.
> ...
>
> Regards,
>
> --
> Julien Grall
--
Oleksandr Tyshchenko | Embedded Dev
GlobalLogic
www.globallogic.com
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xen.org/xen-devel