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",
+                                                       &regshift) == 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

Reply via email to