[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] Problems after enabling rcv/xmit interrupts of ns16550 on OMAP5
On Jul 11, 2013, at 7:21 PM, Ian Campbell <ian.campbell@xxxxxxxxxx> wrote: > On Thu, 2013-07-11 at 18:53 +0800, Chen Baozi wrote: > >> Any ideas? > > Nothing immediately springs to mind. Did you DT-enable the ns16550 > driver? Yes, I think. The printk works well before init_postirq. > > I did a quick hack and slash job to get it going on the cubieboard2, > which I've pasted below (also needed io.h to actually implement the > accessors). (Be kind, it obviously needs proper cleanup ;-)) > > Do you know if you are getting any interrupts at all? I'm wondering if > maybe there is a storm? I think "press 'd'" triggers to dump the debug info states that the console's interrupt works at a certain point? > > Ian. > > diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c > index e0c87bb..ed18b91 100644 > --- a/xen/drivers/char/ns16550.c > +++ b/xen/drivers/char/ns16550.c > @@ -19,7 +19,10 @@ > #include <xen/iocap.h> > #include <xen/pci.h> > #include <xen/pci_regs.h> > +#include <xen/vmap.h> > #include <asm/io.h> > +#include <asm/early_printk.h> > +#include <asm/device.h> > #ifdef CONFIG_X86 > #include <asm/fixmap.h> > #endif > @@ -39,7 +42,8 @@ string_param("com2", opt_com2); > > static struct ns16550 { > int baud, clock_hz, data_bits, parity, stop_bits, fifo_size, irq; > - unsigned long io_base; /* I/O port or memory-mapped I/O address. */ > + u64 io_base; /* I/O port or memory-mapped I/O address. */ > + u64 io_size; > char __iomem *remapped_io_base; /* Remapped virtual address of MMIO. */ > /* UART with IRQ line: interrupt-driven I/O. */ > struct irqaction irqaction; > @@ -56,6 +60,7 @@ static struct ns16550 { > u32 bar; > u16 cr; > u8 bar_idx; > + struct dt_irq dt_irq; > } ns16550_com[2] = { { 0 } }; > > /* Register offsets */ > @@ -128,18 +133,20 @@ static struct ns16550 { > #define RESUME_DELAY MILLISECS(10) > #define RESUME_RETRIES 100 > > +#define REG_SHIFT 2 > + > static char ns_read_reg(struct ns16550 *uart, int reg) > { > - if ( uart->remapped_io_base == NULL ) > - return inb(uart->io_base + reg); > - return readb(uart->remapped_io_base + reg); > +// if ( uart->remapped_io_base == NULL ) > +// return inb(uart->io_base + reg); > + return readl(uart->remapped_io_base + (reg<<REG_SHIFT)); > } > > static void ns_write_reg(struct ns16550 *uart, int reg, char c) > { > - if ( uart->remapped_io_base == NULL ) > - return outb(c, uart->io_base + reg); > - writeb(c, uart->remapped_io_base + reg); > +// if ( uart->remapped_io_base == NULL ) > +// return outb(c, uart->io_base + reg); > + writel(c, uart->remapped_io_base + (reg<<REG_SHIFT)); > } > > static void ns16550_interrupt( > @@ -214,6 +221,7 @@ static int ns16550_getc(struct serial_port *port, char > *pc) > return 1; > } > > +#if 0 > static void pci_serial_early_init(struct ns16550 *uart) > { > if ( !uart->ps_bdf_enable || uart->io_base >= 0x10000 ) > @@ -231,6 +239,7 @@ static void pci_serial_early_init(struct ns16550 *uart) > pci_conf_write16(0, uart->ps_bdf[0], uart->ps_bdf[1], uart->ps_bdf[2], > PCI_COMMAND, PCI_COMMAND_IO); > } > +#endif > > static void ns16550_setup_preirq(struct ns16550 *uart) > { > @@ -239,7 +248,9 @@ static void ns16550_setup_preirq(struct ns16550 *uart) > > uart->intr_works = 0; > > +#if 0 > pci_serial_early_init(uart); > +#endif > > lcr = (uart->data_bits - 5) | ((uart->stop_bits - 1) << 2) | uart->parity; > > @@ -260,7 +271,8 @@ static void ns16550_setup_preirq(struct ns16550 *uart) > /* Baud rate already set: read it out from the divisor latch. */ > divisor = ns_read_reg(uart, DLL); > divisor |= ns_read_reg(uart, DLM) << 8; > - uart->baud = uart->clock_hz / (divisor << 4); > + early_printk("divisor %d\n", divisor); > + //uart->baud = uart->clock_hz / (divisor << 4); > } > ns_write_reg(uart, LCR, lcr); > > @@ -285,8 +297,10 @@ static void __init ns16550_init_preirq(struct > serial_port *port) > uart->remapped_io_base = (void __iomem *)fix_to_virt(idx); > uart->remapped_io_base += uart->io_base & ~PAGE_MASK; > #else > - uart->remapped_io_base = (char *)ioremap(uart->io_base, 8); > + uart->remapped_io_base = ioremap_attr(uart->io_base, uart->io_size, > PAGE_HYPERVISOR_NOCACHE); > +// uart->remapped_io_base = (char *)ioremap(uart->io_base, 8); > #endif > + early_printk("UART mapped at %p\n", uart->remapped_io_base); > } > > ns16550_setup_preirq(uart); > @@ -326,23 +340,27 @@ static void __init ns16550_init_postirq(struct > serial_port *port) > > /* Calculate time to fill RX FIFO and/or empty TX FIFO for polling. */ > bits = uart->data_bits + uart->stop_bits + !!uart->parity; > - uart->timeout_ms = max_t( > - unsigned int, 1, (bits * uart->fifo_size * 1000) / uart->baud); > - > +// uart->timeout_ms = max_t( > +// unsigned int, 1, (bits * uart->fifo_size * 1000) / uart->baud); > + uart->timeout_ms = 1; > if ( uart->irq > 0 ) > { > uart->irqaction.handler = ns16550_interrupt; > uart->irqaction.name = "ns16550"; > uart->irqaction.dev_id = port; > - if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 ) > - printk("ERROR: Failed to allocate ns16550 IRQ %d\n", uart->irq); > + //if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 ) > + // printk("ERROR: Failed to allocate ns16550 IRQ %d\n", > uart->irq); > + if ( (rc = setup_dt_irq(&uart->dt_irq, &uart->irqaction)) != 0 ) > + printk("ERROR: Failed to allocate ns16550 DT IRQ.\n"); > } > > ns16550_setup_postirq(uart); > > +#if 0 > if ( uart->bar || uart->ps_bdf_enable ) > pci_hide_device(uart->ps_bdf[0], PCI_DEVFN(uart->ps_bdf[1], > uart->ps_bdf[2])); > +#endif > } > > static void ns16550_suspend(struct serial_port *port) > @@ -351,13 +369,16 @@ static void ns16550_suspend(struct serial_port *port) > > stop_timer(&uart->timer); > > +#if 0 > if ( uart->bar ) > uart->cr = pci_conf_read16(0, uart->ps_bdf[0], uart->ps_bdf[1], > uart->ps_bdf[2], PCI_COMMAND); > +#endif > } > > static void _ns16550_resume(struct serial_port *port) > { > +#if 0 > struct ns16550 *uart = port->uart; > > if ( uart->bar ) > @@ -367,6 +388,7 @@ static void _ns16550_resume(struct serial_port *port) > pci_conf_write16(0, uart->ps_bdf[0], uart->ps_bdf[1], uart->ps_bdf[2], > PCI_COMMAND, uart->cr); > } > +#endif > > ns16550_setup_preirq(port->uart); > ns16550_setup_postirq(port->uart); > @@ -440,6 +462,12 @@ static int __init ns16550_irq(struct serial_port *port) > return ((uart->irq > 0) ? uart->irq : -1); > } > > +static const struct dt_irq __init *ns16550_dt_irq(struct serial_port *port) > +{ > + struct ns16550 *uart = port->uart; > + return &uart->dt_irq; > +} > + > static struct uart_driver __read_mostly ns16550_driver = { > .init_preirq = ns16550_init_preirq, > .init_postirq = ns16550_init_postirq, > @@ -449,9 +477,13 @@ static struct uart_driver __read_mostly ns16550_driver = > { > .tx_ready = ns16550_tx_ready, > .putc = ns16550_putc, > .getc = ns16550_getc, > - .irq = ns16550_irq > + .irq = ns16550_irq, > + .dt_irq_get = ns16550_dt_irq, > + > }; > > +#if 0 > + > static int __init parse_parity_char(int c) > { > switch ( c ) > @@ -709,8 +741,78 @@ void __init ns16550_init(int index, struct > ns16550_defaults *defaults) > /* Default is no transmit FIFO. */ > uart->fifo_size = 1; > > - ns16550_parse_port_config(uart, (index == 0) ? opt_com1 : opt_com2); > + /* Register with generic serial driver. */ > + serial_register_uart(uart - ns16550_com, &ns16550_driver, uart); > } > +#endif > + > +#if 1 > +static int __init ns16550_uart_dt_init(struct dt_device_node *dev, > + const void *data) > +{ > + struct ns16550 *uart; > + int res; > + > + early_printk("%s\n", __func__); > + > + uart = &ns16550_com[0]; > + > + uart->baud = BAUD_AUTO;//115200; > + uart->clock_hz = UART_CLOCK_HZ; > + uart->data_bits = 8; > + uart->parity = PARITY_NONE; > + uart->stop_bits = 1; > + //uart->irq = defaults->irq; > + //uart->io_base = defaults->io_base; > + /* Default is no transmit FIFO. */ > + uart->fifo_size = 1; > + > + res = dt_device_get_address(dev, 0, &uart->io_base, &uart->io_size); > + if ( res ) > + { > + early_printk("ns16550: Unable to retrieve the base" > + " address of the UART\n"); > + return res; > + } > + > + early_printk("ns16550 at %"PRIx64"-%"PRIx64"\n", uart->io_base, > uart->io_base + uart->io_size); > + > +// uart->io_base = addr; //ioremap_attr(addr, size, > PAGE_HYPERVISOR_NOCACHE); > +// if ( !uart->io_base ) > +// { > +// early_printk("ns16550: Unable to map the UART memory\n"); > +// > +// return -ENOMEM; > +// } > + > + res = dt_device_get_irq(dev, 0, &uart->dt_irq); > + if ( res ) > + { > + early_printk("ns16550: Unable to retrieve the IRQ\n"); > + return res; > + } > + > + /* Register with generic serial driver. */ > + serial_register_uart(uart - ns16550_com, &ns16550_driver, uart); > + > + dt_device_set_used_by(dev, DOMID_XEN); > + > + early_printk("console done?\n"); > + printk("normal printk\n"); > + return 0; > +} > + > +static const char const *ns16550_dt_compat[] __initdata = > +{ > + "snps,dw-apb-uart", > + NULL > +}; > + > +DT_DEVICE_START(ns16550, "NS16550 UART", DEVICE_SERIAL) > + .compatible = ns16550_dt_compat, > + .init = ns16550_uart_dt_init, > +DT_DEVICE_END > +#endif > > /* > * Local variables: > diff --git a/xen/include/asm-arm/io.h b/xen/include/asm-arm/io.h > index aea5233..170263f 100644 > --- a/xen/include/asm-arm/io.h > +++ b/xen/include/asm-arm/io.h > @@ -1,6 +1,54 @@ > #ifndef _ASM_IO_H > #define _ASM_IO_H > > +static inline void __raw_writeb(u8 val, volatile void __iomem *addr) > +{ > + asm volatile("strb %1, %0" > + : "+Qo" (*(volatile u8 __force *)addr) > + : "r" (val)); > +} > + > +static inline void __raw_writel(u32 val, volatile void __iomem *addr) > +{ > + asm volatile("str %1, %0" > + : "+Qo" (*(volatile u32 __force *)addr) > + : "r" (val)); > +} > + > +static inline u8 __raw_readb(const volatile void __iomem *addr) > +{ > + u8 val; > + asm volatile("ldrb %1, %0" > + : "+Qo" (*(volatile u8 __force *)addr), > + "=r" (val)); > + return val; > +} > + > +static inline u32 __raw_readl(const volatile void __iomem *addr) > +{ > + u32 val; > + asm volatile("ldr %1, %0" > + : "+Qo" (*(volatile u32 __force *)addr), > + "=r" (val)); > + return val; > +} > + > +#define __iormb() rmb() > +#define __iowmb() wmb() > + > +#define readb_relaxed(c) ({ u8 __r = __raw_readb(c); __r; }) > +#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ > + __raw_readl(c)); __r; }) > + > +#define writeb_relaxed(v,c) __raw_writeb(v,c) > +#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) > + > +#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); > __v; }) > +#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); > __v; }) > + > +#define writeb(v,c) ({ __iowmb(); writeb_relaxed(v,c); }) > +#define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); }) > + > #endif > /* > * Local variables: > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |