This is the mail archive of the ecos-patches@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PPC40x serial_init fix


serial initialization failed to set UART Divisor in DCR register
when calculation baud clock.
added calculation for PPC405EP 
diff -Nbaur ecos-cvs/packages/hal/powerpc/ppc40x/current/ChangeLog ecos/packages/hal/powerpc/ppc40x/current/ChangeLog
--- ecos-cvs/packages/hal/powerpc/ppc40x/current/ChangeLog	2005-08-25 16:06:08.000000000 +0200
+++ ecos/packages/hal/powerpc/ppc40x/current/ChangeLog	2005-09-02 14:49:50.000000000 +0200
@@ -1,3 +1,9 @@
+2005-09-02  Markus Schade <marks@peppercon.de>
+
+	* src/hal_diag.c: Correct and _complete_ serial initialization
+	for 405EP and GP. Fixed calculation of baud clock and
+	actually _setting_ UART Divisor
+
 2005-08-25  Markus Schade <marks@peppercon.de>
 
 	* src/var_misc.c: 
diff -Nbaur ecos-cvs/packages/hal/powerpc/ppc40x/current/src/hal_diag.c ecos/packages/hal/powerpc/ppc40x/current/src/hal_diag.c
--- ecos-cvs/packages/hal/powerpc/ppc40x/current/src/hal_diag.c	2005-08-25 16:06:08.000000000 +0200
+++ ecos/packages/hal/powerpc/ppc40x/current/src/hal_diag.c	2005-09-02 15:19:49.000000000 +0200
@@ -75,13 +75,22 @@
 
 //-----------------------------------------------------------------------------
 // There are two serial ports.
-#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP)
-#define CYG_DEV_SERIAL_BASE_A    _PPC405GP_UART0
-#define CYG_DEV_SERIAL_BASE_B    _PPC405GP_UART1
-#endif
+// baseBaud = cpuClock/(uartDivisor*16)
+#define CFG_BASE_BAUD           691200
 #if defined(CYGHWR_HAL_POWERPC_PPC4XX_405EP)
 #define CYG_DEV_SERIAL_BASE_A    _PPC405EP_UART0
 #define CYG_DEV_SERIAL_BASE_B    _PPC405EP_UART1
+#define UCR0_MASK       0x0000007f
+#define UCR1_MASK       0x00007f00
+#define UCR0_UDIV_POS   0
+#define UCR1_UDIV_POS   8
+#define UDIV_MAX        127
+#else /* defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP) */
+#define CYG_DEV_SERIAL_BASE_A    _PPC405GP_UART0
+#define CYG_DEV_SERIAL_BASE_B    _PPC405GP_UART1
+#define CR0_MASK        0x00001fff
+#define CR0_UDIV_POS    1
+#define UDIV_MAX        32
 #endif
 //-----------------------------------------------------------------------------
 // Define the serial registers. The PPC405GP has 16552 UART(s) builtin.
@@ -164,14 +173,54 @@
 int
 cyg_var_baud_generator(int baud)
 {
-    int clock_rate, baud_clock, clock_divisor;
-    unsigned int cr0;
+    cyg_uint32 reg;
+    cyg_uint32 tmp;
+    cyg_uint32 clk;
+    cyg_uint32 clock_divisor;
+    cyg_uint8 baud_clock;
+
+    /* Calculate baud rate clock divisor */
+#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405EP)
+    /* CPC0_UCR_BASE 25:31 (7Bit) U0DIV 17:23 (7bit) U1DIV */
+    CYGARC_MFDCR(DCR_CPC0_UCR_BASE, reg);
+    reg &= ~(UCR0_MASK | UCR1_MASK);
+
+    // baseBaud = cpuClock/(uartDivisor*16)
+    clk = (CYGHWR_HAL_POWERPC_CPU_SPEED*1000000);
+    tmp = CFG_BASE_BAUD * 16;
+    clock_divisor = (clk + tmp / 2) / tmp;
+    if (clock_divisor > UDIV_MAX)
+	    clock_divisor = UDIV_MAX;		/* Max == 128 */
+    reg |= (clock_divisor) << UCR0_UDIV_POS;	/* set the UART divisor */
+    reg |= (clock_divisor) << UCR1_UDIV_POS;	/* set the UART divisor */
+
+    /* write back both UART Divisors */
+    CYGARC_MTDCR(DCR_CPC0_UCR_BASE, reg);
+
+#else /* defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP) */
+    /* CPC0_CR0 26:30 (5Bit) generic UART divisor */
+    CYGARC_MFDCR(DCR_CPC0_CR0, reg);
+    reg &= & ~CR0_MASK;
+    /* 405GP could also be clocked externally TODO */
+    clk = (CYGHWR_HAL_POWERPC_CPU_SPEED*1000000);
+#ifdef CYGHWR_HAL_POWERPC_PPC4XX_405_UART_ERRATA_59
+    /* PPC405 Errata 59 (UART Div stuck at 31)
+     * phew, that is way too long for my taste :-) */
+    clock_divisor = 31;
+#else
+    tmp = CFG_BASE_BAUD * 16;
+    clock_divisor = (clk + tmp / 2) / tmp;
+    if (clock_divisor > UDIV_MAX)
+	    clock_divisor = UDIV_MAX;
+#endif
+    reg |= (clock_divisor - 1) << CR0_UDIV_POS;      /* set the UART divisor */
+
+    /* write back both UART Divisor */
+    CYGARC_MTDCR(DCR_CPC0_CR0, reg);
+#endif
 
-    // Calculate baud rate clock divisor
-    CYGARC_MFDCR(DCR_CPC0_CR0, cr0);
-    clock_divisor = ((cr0 & 0x3E) >> 1) + 1;
-    clock_rate = ((CYGHWR_HAL_POWERPC_CPU_SPEED*1000000)/clock_divisor);
-    baud_clock = ((clock_rate)/16)/baud;
+    tmp = baud * 16 * clock_divisor;
+    baud_clock = (clk + tmp / 2) /tmp;
     return baud_clock;
 }
 
@@ -182,34 +231,40 @@
 {
     cyg_uint8* base = __ch_data->base;
     cyg_uint8 lcr;
-    int baud_clock = cyg_var_baud_generator(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD);
+    cyg_uint8 baud_clock = cyg_var_baud_generator(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD);
 
     HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_IER, 0);
 
-    // Disable and clear FIFOs (need to enable to clear).
+    /* Disable and clear FIFOs (need to enable to clear). */
     HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR,
                     (SIO_FCR_FCR0 | SIO_FCR_FCR1 | SIO_FCR_FCR2));
     HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR, 0);
 
-    // 8-1-no parity.
+    /* 8-1-no parity. */
     HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, SIO_LCR_WLS0 | SIO_LCR_WLS1);
 
-    // Set speed to the default baud rate
+    /* Set DLAB Bit */
     HAL_READ_UINT8(base+CYG_DEV_SERIAL_LCR, lcr);
     lcr |= SIO_LCR_DLAB;
     HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, lcr);
 
-    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLL, baud_clock & 0xFF);
-    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLM, (baud_clock >> 8) & 0xFF);
+    /* Set speed to the default baud rate */
+    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLL, baud_clock);
+    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLM, baud_clock >> 8);
+
+    /* Clear DLAB Bit */
     lcr &= ~SIO_LCR_DLAB;
     HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, lcr);
 
-    // Enable FIFOs (and clear them).
+    /* Enable FIFOs (and clear them). */
     HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR,
                     (SIO_FCR_FCR0 | SIO_FCR_FCR1 | SIO_FCR_FCR2));
 
-    // Assert handshake signals
+    /* Assert handshake signals */
     HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_MCR, (SIO_MCR_DTR|SIO_MCR_RTS));
+
+    /* Clear scratchpad */
+    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_SCR, 0);
 }
 
 static cyg_bool

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]