[U-Boot] [PATCH] ppc4xx: UART: Use NS16550 struct instead of offset macros

This patch changes the PPC4xx UART driver to use the NS16550 struct instead of macros for the register offsets.
Signed-off-by: Stefan Roese sr@denx.de --- arch/powerpc/cpu/ppc4xx/4xx_uart.c | 170 ++++++++++++++---------------------- 1 files changed, 66 insertions(+), 104 deletions(-)
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_uart.c b/arch/powerpc/cpu/ppc4xx/4xx_uart.c index e6ab570..fbfd691 100644 --- a/arch/powerpc/cpu/ppc4xx/4xx_uart.c +++ b/arch/powerpc/cpu/ppc4xx/4xx_uart.c @@ -50,6 +50,7 @@ #include <asm/io.h> #include <watchdog.h> #include <ppc4xx.h> +#include <ns16550.h>
#ifdef CONFIG_SERIAL_MULTI #include <serial.h> @@ -154,31 +155,6 @@ DECLARE_GLOBAL_DATA_PTR; #error "External serial clock not supported on AMCC PPC405EP!" #endif
-#define UART_RBR 0x00 -#define UART_THR 0x00 -#define UART_IER 0x01 -#define UART_IIR 0x02 -#define UART_FCR 0x02 -#define UART_LCR 0x03 -#define UART_MCR 0x04 -#define UART_LSR 0x05 -#define UART_MSR 0x06 -#define UART_SCR 0x07 -#define UART_DLL 0x00 -#define UART_DLM 0x01 - -/*-----------------------------------------------------------------------------+ - | Line Status Register. - +-----------------------------------------------------------------------------*/ -#define asyncLSRDataReady1 0x01 -#define asyncLSROverrunError1 0x02 -#define asyncLSRParityError1 0x04 -#define asyncLSRFramingError1 0x08 -#define asyncLSRBreakInterrupt1 0x10 -#define asyncLSRTxHoldEmpty1 0x20 -#define asyncLSRTxShiftEmpty1 0x40 -#define asyncLSRRxFifoError1 0x80 - #ifdef CONFIG_SERIAL_SOFTWARE_FIFO /*-----------------------------------------------------------------------------+ | Fifo @@ -192,7 +168,7 @@ typedef struct { volatile static serial_buffer_t buf_info; #endif
-static void serial_init_common(u32 base, u32 udiv, u16 bdiv) +static void serial_init_common(struct NS16550 *com_port, u32 udiv, u16 bdiv) { PPC4xx_SYS_INFO sys_info; u8 val; @@ -208,16 +184,16 @@ static void serial_init_common(u32 base, u32 udiv, u16 bdiv) gd->uart_clk = sys_info.freqUART / udiv; #endif
- out_8((u8 *)base + UART_LCR, 0x80); /* set DLAB bit */ - out_8((u8 *)base + UART_DLL, bdiv); /* set baudrate divisor */ - out_8((u8 *)base + UART_DLM, bdiv >> 8); /* set baudrate divisor */ - out_8((u8 *)base + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ - out_8((u8 *)base + UART_FCR, 0x00); /* disable FIFO */ - out_8((u8 *)base + UART_MCR, 0x00); /* no modem control DTR RTS */ - val = in_8((u8 *)base + UART_LSR); /* clear line status */ - val = in_8((u8 *)base + UART_RBR); /* read receive buffer */ - out_8((u8 *)base + UART_SCR, 0x00); /* set scratchpad */ - out_8((u8 *)base + UART_IER, 0x00); /* set interrupt enable reg */ + out_8(&com_port->lcr, 0x80); /* set DLAB bit */ + out_8(&com_port->dll, bdiv); /* set baudrate divisor */ + out_8(&com_port->dlm, bdiv >> 8); /* set baudrate divisor */ + out_8(&com_port->lcr, 0x03); /* clear DLAB; set 8 bits, no parity */ + out_8(&com_port->fcr, 0x00); /* disable FIFO */ + out_8(&com_port->mcr, 0x00); /* no modem control DTR RTS */ + val = in_8(&com_port->lsr); /* clear line status */ + val = in_8(&com_port->rbr); /* read receive buffer */ + out_8(&com_port->scr, 0x00); /* set scratchpad */ + out_8(&com_port->ier, 0x00); /* set interrupt enable reg */ }
#if (defined(CONFIG_440) || defined(CONFIG_405EX)) && \ @@ -326,7 +302,7 @@ static void serial_divs (int baudrate, unsigned long *pudiv, */
#if defined(CONFIG_440) -int serial_init_dev(unsigned long base) +int serial_init_dev(struct NS16550 *com_port) { unsigned long reg; unsigned long udiv; @@ -368,14 +344,14 @@ int serial_init_dev(unsigned long base) MTREG(UART3_SDR, reg); #endif
- serial_init_common(base, udiv, bdiv); + serial_init_common(com_port, udiv, bdiv);
return (0); }
#else /* !defined(CONFIG_440) */
-int serial_init_dev (unsigned long base) +int serial_init_dev (struct NS16550 *com_port) { unsigned long reg; unsigned long tmp; @@ -445,42 +421,42 @@ int serial_init_dev (unsigned long base) bdiv = (clk + tmp / 2) / tmp; #endif /* CONFIG_405EX */
- serial_init_common(base, udiv, bdiv); + serial_init_common(com_port, udiv, bdiv);
return (0); }
#endif /* if defined(CONFIG_440) */
-void serial_setbrg_dev(unsigned long base) +void serial_setbrg_dev(struct NS16550 *com_port) { - serial_init_dev(base); + serial_init_dev(com_port); }
-void serial_putc_dev(unsigned long base, const char c) +void serial_putc_dev(struct NS16550 *com_port, const char c) { int i;
if (c == '\n') - serial_putc_dev(base, '\r'); + serial_putc_dev(com_port, '\r');
/* check THRE bit, wait for transmiter available */ - for (i = 1; i < 3500; i++) { - if ((in_8((u8 *)base + UART_LSR) & 0x20) == 0x20) + for (i = 0; i < 3500; i++) { + if (in_8(&com_port->lsr) & UART_LSR_THRE) break; udelay (100); }
- out_8((u8 *)base + UART_THR, c); /* put character out */ + out_8(&com_port->thr, c); /* put character out */ }
-void serial_puts_dev (unsigned long base, const char *s) +void serial_puts_dev (struct NS16550 *com_port, const char *s) { while (*s) - serial_putc_dev (base, *s++); + serial_putc_dev (com_port, *s++); }
-int serial_getc_dev (unsigned long base) +int serial_getc_dev (struct NS16550 *com_port) { unsigned char status = 0;
@@ -489,42 +465,32 @@ int serial_getc_dev (unsigned long base) WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */ #endif /* CONFIG_HW_WATCHDOG */
- status = in_8((u8 *)base + UART_LSR); - if ((status & asyncLSRDataReady1) != 0x0) + status = in_8(&com_port->lsr); + if (status & UART_LSR_DR) break;
- if ((status & ( asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1 )) != 0) { - out_8((u8 *)base + UART_LSR, - asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1); + if ((status & (UART_LSR_FE | UART_LSR_OE | + UART_LSR_PE | UART_LSR_BI)) != 0) { + out_8(&com_port->lsr, UART_LSR_FE | UART_LSR_OE | + UART_LSR_PE | UART_LSR_BI); } }
- return (0x000000ff & (int) in_8((u8 *)base)); + return 0xff & in_8(&com_port->rbr); }
-int serial_tstc_dev (unsigned long base) +int serial_tstc_dev (struct NS16550 *com_port) { unsigned char status;
- status = in_8((u8 *)base + UART_LSR); - if ((status & asyncLSRDataReady1) != 0x0) - return (1); - - if ((status & ( asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1 )) != 0) { - out_8((u8 *)base + UART_LSR, - asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1); + status = in_8(&com_port->lsr); + if ((status & UART_LSR_DR) != 0x0) + return 1; + + if ((status & (UART_LSR_FE | UART_LSR_OE | + UART_LSR_PE | UART_LSR_BI)) != 0) { + out_8(&com_port->lsr, UART_LSR_FE | UART_LSR_OE | + UART_LSR_PE | UART_LSR_BI); }
return 0; @@ -703,22 +669,18 @@ int getDebugChar (void)
while (1) { status = in_8((u8 *)ACTING_UART1_BASE + UART_LSR); - if ((status & asyncLSRDataReady1) != 0x0) + if ((status & UART_LSR_DR) != 0x0) break;
- if ((status & (asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1 )) != 0) { + if ((status & (UART_LSR_FE | UART_LSR_OE | + UART_LSR_PE | UART_LSR_BI)) != 0) { out_8((u8 *)ACTING_UART1_BASE + UART_LSR, - asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1); + UART_LSR_FE | UART_LSR_OE | + UART_LSR_PE | UART_LSR_BI); } }
- return (0x000000ff & (int) in_8((u8 *)ACTING_UART1_BASE)); + return (0x000000ff & (int) in_8((u8 *)ACTING_UART1_BASE->rbr)); }
void kgdb_interruptible (int yes) @@ -759,62 +721,62 @@ void kgdb_interruptible (int yes) #if defined(CONFIG_SERIAL_MULTI) int serial0_init(void) { - return (serial_init_dev(UART0_BASE)); + return serial_init_dev((struct NS16550 *)UART0_BASE); }
int serial1_init(void) { - return (serial_init_dev(UART1_BASE)); + return serial_init_dev((struct NS16550 *)UART1_BASE); }
void serial0_setbrg (void) { - serial_setbrg_dev(UART0_BASE); + serial_setbrg_dev((struct NS16550 *)UART0_BASE); }
void serial1_setbrg (void) { - serial_setbrg_dev(UART1_BASE); + serial_setbrg_dev((struct NS16550 *)UART1_BASE); }
void serial0_putc(const char c) { - serial_putc_dev(UART0_BASE,c); + serial_putc_dev((struct NS16550 *)UART0_BASE, c); }
void serial1_putc(const char c) { - serial_putc_dev(UART1_BASE, c); + serial_putc_dev((struct NS16550 *)UART1_BASE, c); }
void serial0_puts(const char *s) { - serial_puts_dev(UART0_BASE, s); + serial_puts_dev((struct NS16550 *)UART0_BASE, s); }
void serial1_puts(const char *s) { - serial_puts_dev(UART1_BASE, s); + serial_puts_dev((struct NS16550 *)UART1_BASE, s); }
int serial0_getc(void) { - return(serial_getc_dev(UART0_BASE)); + return serial_getc_dev((struct NS16550 *)UART0_BASE); }
int serial1_getc(void) { - return(serial_getc_dev(UART1_BASE)); + return serial_getc_dev((struct NS16550 *)UART1_BASE); }
int serial0_tstc(void) { - return (serial_tstc_dev(UART0_BASE)); + return serial_tstc_dev((struct NS16550 *)UART0_BASE); }
int serial1_tstc(void) { - return (serial_tstc_dev(UART1_BASE)); + return serial_tstc_dev((struct NS16550 *)UART1_BASE); }
struct serial_device serial0_device = @@ -848,32 +810,32 @@ struct serial_device serial1_device = */ int serial_init(void) { - return serial_init_dev(ACTING_UART0_BASE); + return serial_init_dev((struct NS16550 *)ACTING_UART0_BASE); }
void serial_setbrg(void) { - serial_setbrg_dev(ACTING_UART0_BASE); + serial_setbrg_dev((struct NS16550 *)ACTING_UART0_BASE); }
void serial_putc(const char c) { - serial_putc_dev(ACTING_UART0_BASE, c); + serial_putc_dev((struct NS16550 *)ACTING_UART0_BASE, c); }
void serial_puts(const char *s) { - serial_puts_dev(ACTING_UART0_BASE, s); + serial_puts_dev((struct NS16550 *)ACTING_UART0_BASE, s); }
int serial_getc(void) { - return serial_getc_dev(ACTING_UART0_BASE); + return serial_getc_dev((struct NS16550 *)ACTING_UART0_BASE); }
int serial_tstc(void) { - return serial_tstc_dev(ACTING_UART0_BASE); + return serial_tstc_dev((struct NS16550 *)ACTING_UART0_BASE); } #endif /* CONFIG_SERIAL_MULTI */

Hi Stefan,
This patch changes the PPC4xx UART driver to use the NS16550 struct instead of macros for the register offsets.
Dumb question - can't you reuse drivers/serial/ns16550.c completely? This would be even better. It worked for me on the vct boards, remember?
Cheers Detlev

Hi Detlev,
On Thursday 16 September 2010 14:12:28 Detlev Zundel wrote:
This patch changes the PPC4xx UART driver to use the NS16550 struct instead of macros for the register offsets.
Dumb question - can't you reuse drivers/serial/ns16550.c completely? This would be even better. It worked for me on the vct boards, remember?
Yes, I remember. I'm "on the way" to using this common driver. But the PPC4xx one currently has quite a lot of special handling cases, like this SOFTWARE_FIFO stuff, which I first need to sort out.
But again, I'll try to move to the common driver soon.
Cheers, Stefan
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-0 Fax: (+49)-8142-66989-80 Email: office@denx.de

Dear Stefan Roese,
In message 201009161416.34827.sr@denx.de you wrote:
Yes, I remember. I'm "on the way" to using this common driver. But the PPC4xx one currently has quite a lot of special handling cases, like this SOFTWARE_FIFO stuff, which I first need to sort out.
Are any of these special cases really needed / used anywhere in current code?
But again, I'll try to move to the common driver soon.
If you plan to move anyway, then why would you clean up the old (to be removed) driver first? Just throw it out unchanged...
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Thursday 16 September 2010 14:27:23 Wolfgang Denk wrote:
Yes, I remember. I'm "on the way" to using this common driver. But the PPC4xx one currently has quite a lot of special handling cases, like this SOFTWARE_FIFO stuff, which I first need to sort out.
Are any of these special cases really needed / used anywhere in current code?
Yes, there is this CONFIG_CMD_KGDB (which I never used). From a quick glance this is also not used though. So this can be removed as well.
But again, I'll try to move to the common driver soon.
If you plan to move anyway, then why would you clean up the old (to be removed) driver first? Just throw it out unchanged...
OK, you convinced me. I'll try to move directly without this "migration" step.
Cheers, Stefan
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-0 Fax: (+49)-8142-66989-80 Email: office@denx.de
participants (3)
-
Detlev Zundel
-
Stefan Roese
-
Wolfgang Denk