In APM8018X SOC, UART register address space has been relocated to 32-bit data boundaries for APB bus implementation. Current legacy_serial driver ignores the reg-shift property. This patch modifies legacy_serial.c and udbg_16550.c to work with above mentioned UARTs.
Signed-off-by: Tanmay Inamdar <tinam...@apm.com> --- :100644 100644 8338aef... f5fc106... M arch/powerpc/include/asm/udbg.h :100644 100644 bedd12e... d523b7d... M arch/powerpc/kernel/legacy_serial.c :100644 100644 6837f83... e0cb7dc... M arch/powerpc/kernel/udbg_16550.c arch/powerpc/include/asm/udbg.h | 2 +- arch/powerpc/kernel/legacy_serial.c | 16 +++++--- arch/powerpc/kernel/udbg_16550.c | 64 ++++++++++++++++++++++------------ 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h index 8338aef..f5fc106 100644 --- a/arch/powerpc/include/asm/udbg.h +++ b/arch/powerpc/include/asm/udbg.h @@ -29,7 +29,7 @@ extern void udbg_printf(const char *fmt, ...) extern void udbg_progress(char *s, unsigned short hex); extern void udbg_init_uart(void __iomem *comport, unsigned int speed, - unsigned int clock); + unsigned int clock, unsigned int regshift); extern unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock); diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index bedd12e..d523b7d 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -33,6 +33,7 @@ static struct legacy_serial_info { unsigned int clock; int irq_check_parent; phys_addr_t taddr; + unsigned int regshift; } legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS]; static struct __initdata of_device_id legacy_serial_parents[] = { @@ -42,6 +43,7 @@ static struct __initdata of_device_id legacy_serial_parents[] = { {.compatible = "ibm,opb",}, {.compatible = "simple-bus",}, {.compatible = "wrs,epld-localbus",}, + {.compatible = "apm,apb",}, {}, }; @@ -163,11 +165,6 @@ static int __init add_legacy_soc_port(struct device_node *np, if (of_get_property(np, "clock-frequency", NULL) == NULL) return -1; - /* if reg-shift or offset, don't try to use it */ - if ((of_get_property(np, "reg-shift", NULL) != NULL) || - (of_get_property(np, "reg-offset", NULL) != NULL)) - return -1; - /* if rtas uses this device, don't try to use it as well */ if (of_get_property(np, "used-by-rtas", NULL) != NULL) return -1; @@ -319,7 +316,7 @@ static void __init setup_legacy_serial_console(int console) if (info->speed == 0) info->speed = udbg_probe_uart_speed(addr, info->clock); DBG("default console speed = %d\n", info->speed); - udbg_init_uart(addr, info->speed, info->clock); + udbg_init_uart(addr, info->speed, info->clock, info->regshift); } /* @@ -336,6 +333,7 @@ void __init find_legacy_serial_ports(void) struct device_node *np, *stdout = NULL; const char *path; int index; + unsigned int regshift; DBG(" -> find_legacy_serial_port()\n"); @@ -359,6 +357,12 @@ void __init find_legacy_serial_ports(void) index = add_legacy_soc_port(np, np); if (index >= 0 && np == stdout) legacy_serial_console = index; + if (of_property_read_u32(np, "reg-shift", + ®shift) == 0) { + legacy_serial_infos + [legacy_serial_console].regshift = + regshift; + } } } of_node_put(parent); diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index 6837f83..e0cb7dc 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c @@ -47,12 +47,29 @@ struct NS16550 { #define LCR_DLAB 0x80 +static unsigned int reg_shift; +#define ns16550_offset(addr) (addr - (unsigned char *)udbg_comport) + static struct NS16550 __iomem *udbg_comport; +static inline u8 serial_read(unsigned char *addr) +{ + u32 offset = ns16550_offset(addr) << reg_shift; + return readb(udbg_comport + offset); +} + +static inline void serial_write(unsigned char *addr, char val) +{ + u32 offset = ns16550_offset(addr) << reg_shift; + writeb(val, udbg_comport + offset); +} + static void udbg_550_flush(void) { + u32 timeout = 1000; if (udbg_comport) { - while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) + while (((serial_read(&udbg_comport->lsr) & LSR_THRE) == 0) + && --timeout) /* wait for idle */; } } @@ -63,15 +80,15 @@ static void udbg_550_putc(char c) if (c == '\n') udbg_550_putc('\r'); udbg_550_flush(); - out_8(&udbg_comport->thr, c); + serial_write(&udbg_comport->thr, c); } } static int udbg_550_getc_poll(void) { if (udbg_comport) { - if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0) - return in_8(&udbg_comport->rbr); + if ((serial_read(&udbg_comport->lsr) & LSR_DR) != 0) + return serial_read(&udbg_comport->rbr); else return -1; } @@ -81,15 +98,15 @@ static int udbg_550_getc_poll(void) static int udbg_550_getc(void) { if (udbg_comport) { - while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0) + while ((serial_read(&udbg_comport->lsr) & LSR_DR) == 0) /* wait for char */; - return in_8(&udbg_comport->rbr); + return serial_read(&udbg_comport->rbr); } return -1; } void udbg_init_uart(void __iomem *comport, unsigned int speed, - unsigned int clock) + unsigned int clock, unsigned int regshift) { unsigned int dll, base_bauds; @@ -103,22 +120,23 @@ void udbg_init_uart(void __iomem *comport, unsigned int speed, if (comport) { udbg_comport = (struct NS16550 __iomem *)comport; - out_8(&udbg_comport->lcr, 0x00); - out_8(&udbg_comport->ier, 0xff); - out_8(&udbg_comport->ier, 0x00); - out_8(&udbg_comport->lcr, LCR_DLAB); - out_8(&udbg_comport->dll, dll & 0xff); - out_8(&udbg_comport->dlm, dll >> 8); + serial_write(&udbg_comport->lcr, 0x00); + serial_write(&udbg_comport->ier, 0xff); + serial_write(&udbg_comport->ier, 0x00); + serial_write(&udbg_comport->lcr, LCR_DLAB); + serial_write(&udbg_comport->dll, dll & 0xff); + serial_write(&udbg_comport->dlm, dll >> 8); /* 8 data, 1 stop, no parity */ - out_8(&udbg_comport->lcr, 0x03); + serial_write(&udbg_comport->lcr, 0x03); /* RTS/DTR */ - out_8(&udbg_comport->mcr, 0x03); + serial_write(&udbg_comport->mcr, 0x03); /* Clear & enable FIFOs */ - out_8(&udbg_comport->fcr ,0x07); + serial_write(&udbg_comport->fcr, 0x07); udbg_putc = udbg_550_putc; udbg_flush = udbg_550_flush; udbg_getc = udbg_550_getc; udbg_getc_poll = udbg_550_getc_poll; + reg_shift = regshift; } } @@ -128,24 +146,24 @@ unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock) u8 old_lcr; struct NS16550 __iomem *port = comport; - old_lcr = in_8(&port->lcr); + old_lcr = serial_read(&port->lcr); /* select divisor latch registers. */ - out_8(&port->lcr, LCR_DLAB); + serial_write(&port->lcr, LCR_DLAB); /* now, read the divisor */ - dll = in_8(&port->dll); - dlm = in_8(&port->dlm); + dll = serial_read(&port->dll); + dlm = serial_read(&port->dlm); divisor = dlm << 8 | dll; /* check prescaling */ - if (in_8(&port->mcr) & 0x80) + if (serial_read(&port->mcr) & 0x80) prescaler = 4; else prescaler = 1; /* restore the LCR */ - out_8(&port->lcr, old_lcr); + serial_write(&port->lcr, old_lcr); /* calculate speed */ speed = (clock / prescaler) / (divisor * 16); @@ -341,7 +359,7 @@ void __init udbg_init_wsp(void) { udbg_comport = (struct NS16550 __iomem *)WSP_UART_VIRT; - udbg_init_uart(udbg_comport, 57600, 50000000); + udbg_init_uart(udbg_comport, 57600, 50000000, 0); udbg_putc = udbg_wsp_putc; udbg_flush = udbg_wsp_flush; -- 1.6.1.rc3 _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev