]> rtime.felk.cvut.cz Git - rtems-devel.git/blobdiff - rtems-patches/rtems-csb336-20051008-uart.patch
Updates to CSB336 BSP (based on ARM 9328 MX1) from Jay Monkman.
[rtems-devel.git] / rtems-patches / rtems-csb336-20051008-uart.patch
diff --git a/rtems-patches/rtems-csb336-20051008-uart.patch b/rtems-patches/rtems-csb336-20051008-uart.patch
new file mode 100644 (file)
index 0000000..292feea
--- /dev/null
@@ -0,0 +1,664 @@
+Index: rtems/c/src/lib/libbsp/arm/csb336/console/uart.c
+===================================================================
+--- rtems.orig/c/src/lib/libbsp/arm/csb336/console/uart.c
++++ rtems/c/src/lib/libbsp/arm/csb336/console/uart.c
+@@ -1,262 +1,453 @@
+ /*
+- *  console driver for MC9328XML UARTs
++ * Console driver for MC9328XML UARTs.
+  *
+- *  This driver uses the shared console driver in 
+- *  ...../libbsp/shared/console.c
++ * Written Jay Monkman <jtm@lopingdog.com>
++ * Copyright (c) 2005 by Loping Dog Embedded Systems
+  *
+- *  If you want the driver to be interrupt driven, you 
+- *  need to write the ISR, and in the ISR insert the
+- *  chars into termios's queue.
++ * The license and distribution terms for this file may be
++ * found in the file LICENSE in this distribution or at
++ *    http://www.rtems.com/license
+  *
+- *  Copyright (c) 2004 Cogent Computer Systems
+- *  Written by Jay Monkman <jtm@lopingdog.com>
+- *
+- *  The license and distribution terms for this file may be
+- *  found in the file LICENSE in this distribution or at
+- *
+- *  http://www.OARcorp.com/rtems/license.html.
+- *
+- *
+- *  $Id: uart.c,v 1.1 2004/07/15 06:12:05 jtm Exp $
+-*/
+-#include <bsp.h>                /* Must be before libio.h */
++ * $Id:$
++ */
++#include <bsp.h>
+ #include <rtems/libio.h>
+-#include <termios.h>
++#include <libchip/sersupp.h>
++#include <rtems/error.h>
+ #include <rtems/bspIo.h>
+-
+-/* Put the CPU (or UART) specific header file #include here */
++#include <termios.h>
++#include <irq.h>
+ #include <mc9328mxl.h>
+-#include <libchip/serial.h>
+-#include <libchip/sersupp.h>
++
++
++/* Define this to use interrupt driver UART driver */
++#define USE_INTERRUPTS 1
+ /* How many serial ports? */
+ #define NUM_DEVS       2
++#define poll_write(c)  imx_uart_poll_write_char(0, c)
++#define poll_read()  imx_uart_poll_read_char(0)
+-int     uart_poll_read(int minor);
++static int imx_uart_first_open(int, int, void *);
++static int imx_uart_last_close(int, int, void *);
++static int imx_uart_poll_read(int);
++static int imx_uart_set_attrs(int, const struct termios *);
++static void imx_uart_init(int minor);
++static void imx_uart_set_baud(int, int);
++static int imx_uart_poll_write(int, const char *, int);
++
++#if defined(USE_INTERRUPTS)
++static void imx_uart_tx_isr(rtems_irq_hdl_param);
++static void imx_uart_rx_isr(rtems_irq_hdl_param);
++static void imx_uart_isr_on(const rtems_irq_connect_data *irq);
++static void imx_uart_isr_off(const rtems_irq_connect_data *irq);
++static int imx_uart_isr_is_on(const rtems_irq_connect_data *irq);
++static int imx_uart_intr_write(int, const char *, int);
++#endif
+-int dbg_dly;
+-/* static function prototypes */
+-static int     uart_first_open(int major, int minor, void *arg);
+-static int     uart_last_close(int major, int minor, void *arg);
+-static int     uart_read(int minor);
+-static int     uart_write(int minor, const char *buf, int len);
+-static void    uart_init(int minor);
+-static void    uart_write_polled(int minor, char c);
+-static int     uart_set_attributes(int minor, const struct termios *t);
+-
+-/* These are used by code in console.c */
+-unsigned long Console_Port_Count = NUM_DEVS;
+-console_data  Console_Port_Data[NUM_DEVS];
+-
+-/* rtems console uses the following minor number */
+-rtems_device_minor_number  Console_Port_Minor = 0;
+-
+-/* Pointers to functions for handling the UART. */
+-console_fns uart_fns = 
+-{ 
+-    libchip_serial_default_probe,
+-    uart_first_open,
+-    uart_last_close,
+-    uart_read,
+-    uart_write,
+-    uart_init,
+-    uart_write_polled,   /* not used in this driver */
+-    uart_set_attributes,
+-    FALSE      /* TRUE if interrupt driven, FALSE if not. */
++
++/* TERMIOS callbacks */
++#if defined(USE_INTERRUPTS)
++rtems_termios_callbacks imx_uart_cbacks = {
++    .firstOpen            = imx_uart_first_open,
++    .lastClose            = imx_uart_last_close,
++    .pollRead             = NULL,
++    .write                = imx_uart_intr_write,
++    .setAttributes        = imx_uart_set_attrs,
++    .stopRemoteTx         = NULL,
++    .startRemoteTx        = NULL,
++    .outputUsesInterrupts = 1,
++};
++#else
++rtems_termios_callbacks imx_uart_cbacks = {
++    .firstOpen            = imx_uart_first_open,
++    .lastClose            = imx_uart_last_close,
++    .pollRead             = imx_uart_poll_read,
++    .write                = imx_uart_poll_write,
++    .setAttributes        = imx_uart_set_attrs,
++    .stopRemoteTx         = NULL,
++    .startRemoteTx        = NULL,
++    .outputUsesInterrupts = 0,
+ };
++#endif
+-/* 
+- * There's one item in array for each UART.
+- *
+- * Some of these fields are marked "NOT USED". They are not used
+- * by console.c, but may be used by drivers in libchip
+- *
+- */
+-console_tbl Console_Port_Tbl[] = {
+-    {
+-        "/dev/com0",                      /* sDeviceName */
+-        SERIAL_CUSTOM,                    /* deviceType */
+-        &uart_fns,                        /* pDeviceFns */
+-        NULL,                             /* deviceProbe */
+-        NULL,                             /* pDeviceFlow */
+-        0,                                /* ulMargin - NOT USED */
+-        0,                                /* ulHysteresis - NOT USED */
+-        NULL,                             /* pDeviceParams */
+-        0,                                /* ulCtrlPort1  - NOT USED */
+-        0,                                /* ulCtrlPort2  - NOT USED */
+-        0,                                /* ulDataPort  - NOT USED */
+-        NULL,                             /* getRegister - NOT USED */
+-        NULL,                             /* setRegister - NOT USED */
+-        NULL,                             /* getData - NOT USED */
+-        NULL,                             /* setData - NOT USED */
+-        0,                                /* ulClock - NOT USED */
+-        0                                 /* ulIntVector - NOT USED */
+-    },
+-    {
+-        "/dev/com1",                      /* sDeviceName */
+-        SERIAL_CUSTOM,                    /* deviceType */
+-        &uart_fns,                        /* pDeviceFns */
+-        NULL,                             /* deviceProbe */
+-        NULL,                             /* pDeviceFlow */
+-        0,                                /* ulMargin - NOT USED */
+-        0,                                /* ulHysteresis - NOT USED */
+-        NULL,                             /* pDeviceParams */
+-        0,                                /* ulCtrlPort1  - NOT USED */
+-        0,                                /* ulCtrlPort2  - NOT USED */
+-        0,                                /* ulDataPort  - NOT USED */
+-        NULL,                             /* getRegister - NOT USED */
+-        NULL,                             /* setRegister - NOT USED */
+-        NULL,                             /* getData - NOT USED */
+-        NULL,                             /* setData - NOT USED */
+-        0,                                /* ulClock - NOT USED */
+-        0                                 /* ulIntVector - NOT USED */
++#if defined(USE_INTERRUPTS)
++static rtems_irq_connect_data imx_uart_tx_isr_data[NUM_DEVS];
++static rtems_irq_connect_data imx_uart_rx_isr_data[NUM_DEVS];
++#endif
++
++typedef struct {
++    int minor;
++    mc9328mxl_uart_regs_t * regs;
++    volatile const char *buf;
++    volatile int len;
++    volatile int idx;
++    void *tty;
++} imx_uart_data_t;
++
++static imx_uart_data_t imx_uart_data[NUM_DEVS];
++
++rtems_device_driver console_initialize(
++    rtems_device_major_number  major,
++    rtems_device_minor_number  minor,
++    void                      *arg
++)
++{
++    rtems_status_code status;
++    int i;
++
++    for (i = 0; i < NUM_DEVS; i++) {
++        imx_uart_init(i);
+     }
+-};
+-/*********************************************************************/
+-/* Functions called via termios callbacks (i.e. the ones in uart_fns */
+-/*********************************************************************/
+-
+-/* 
+- * This is called the first time each device is opened. If the driver 
+- * is interrupt driven, you should enable interrupts here. Otherwise, 
+- * it's probably safe to do nothing.
+- *
+- * Since micromonitor already set up the UART, we do nothing.
+- */
+-static int uart_first_open(int major, int minor, void *arg) 
++    rtems_termios_initialize();
++
++    /* /dev/console and /dev/tty0 are the same */
++    status = rtems_io_register_name("/dev/console", major, 0);
++    if (status != RTEMS_SUCCESSFUL) {
++        rtems_panic("%s:%d Error registering /dev/console :: %d\n",
++                    __FUNCTION__, __LINE__, status);
++    }
++
++    status = rtems_io_register_name("/dev/tty0", major, 0);
++    if (status != RTEMS_SUCCESSFUL) {
++        rtems_panic("%s:%d Error registering /dev/tty0 :: %d\n",
++                    __FUNCTION__, __LINE__, status);
++    }
++
++    status = rtems_io_register_name("/dev/tty1", major, 1);
++    if (status != RTEMS_SUCCESSFUL) {
++        rtems_panic("%s:%d Error registering /dev/tty1 :: %d\n",
++                    __FUNCTION__, __LINE__, status);
++    }
++    return RTEMS_SUCCESSFUL;
++}
++
++rtems_device_driver console_open(
++    rtems_device_major_number major,
++    rtems_device_minor_number minor,
++    void                    * arg
++)
+ {
+-    return 0;
++    rtems_status_code rc;
++
++    if (minor > (NUM_DEVS - 1)) {
++        return RTEMS_INVALID_NUMBER;
++    }
++
++    rc = rtems_termios_open(major, minor, arg, &imx_uart_cbacks);
++
++    return rc;
+ }
++rtems_device_driver console_close(
++    rtems_device_major_number major,
++    rtems_device_minor_number minor,
++    void                    * arg
++)
++{
++    return rtems_termios_close(arg);
++}
+-/* 
+- * This is called the last time each device is closed. If the driver 
+- * is interrupt driven, you should disable interrupts here. Otherwise, 
+- * it's probably safe to do nothing.
+- */
+-static int uart_last_close(int major, int minor, void *arg) 
++rtems_device_driver console_read(
++    rtems_device_major_number major,
++    rtems_device_minor_number minor,
++    void                    * arg
++)
+ {
+-    return 0;
++  return rtems_termios_read(arg);
+ }
++rtems_device_driver console_write(
++    rtems_device_major_number major,
++    rtems_device_minor_number minor,
++    void                    * arg
++)
++{
++  return rtems_termios_write(arg);
++}
+-/*
+- * Read one character from UART.
+- *
+- * Return -1 if there's no data, otherwise return
+- * the character in lowest 8 bits of returned int.
+- */
+-static int uart_read(int minor) 
++rtems_device_driver console_control(
++    rtems_device_major_number major,
++    rtems_device_minor_number minor,
++    void                    * arg
++)
+ {
+-    char c;
++  return rtems_termios_ioctl(arg);
++}
++
++static void imx_uart_init(int minor)
++{
++    imx_uart_data[minor].minor = minor;
++    imx_uart_data[minor].buf   = NULL;
++    imx_uart_data[minor].len   = 0;
++    imx_uart_data[minor].idx   = 0;
+     if (minor == 0) {
+-        if (MC9328MXL_UART1_SR2 & MC9328MXL_UART_SR2_RDR) {
+-            c = MC9328MXL_UART1_RXD & MC9328MXL_UART_RXD_CHARMASK;
+-            return c;
+-        } else {
+-            return -1;
+-        }
++#if defined(USE_INTERRUPTS)
++        imx_uart_tx_isr_data[minor].name = BSP_INT_UART1_TX;
++        imx_uart_rx_isr_data[minor].name = BSP_INT_UART1_RX;
++#endif
++        imx_uart_data[minor].regs =
++            (mc9328mxl_uart_regs_t *) MC9328MXL_UART1_BASE;
+     } else if (minor == 1) {
+-        if (MC9328MXL_UART2_SR2 & MC9328MXL_UART_SR2_RDR) {
+-            c = MC9328MXL_UART2_RXD & MC9328MXL_UART_RXD_CHARMASK;
+-            return c;
+-        } else {
+-            return -1;
+-        }
++#if defined(USE_INTERRUPTS)
++        imx_uart_tx_isr_data[minor].name = BSP_INT_UART2_TX;
++        imx_uart_rx_isr_data[minor].name = BSP_INT_UART2_RX;
++#endif
++        imx_uart_data[minor].regs =
++            (mc9328mxl_uart_regs_t *) MC9328MXL_UART2_BASE;
+     } else {
+-        printk("Unknown console minor number: %d\n", minor);
+-        return -1;
++        rtems_panic("%s:%d Unknown UART minor number %d\n",
++                    __FUNCTION__, __LINE__, minor);
+     }
++#if defined(USE_INTERRUPTS)
++    imx_uart_tx_isr_data[minor].hdl    = imx_uart_tx_isr;
++    imx_uart_tx_isr_data[minor].handle = &imx_uart_data[minor];
++    imx_uart_tx_isr_data[minor].on     = imx_uart_isr_on;
++    imx_uart_tx_isr_data[minor].off    = imx_uart_isr_off;
++    imx_uart_tx_isr_data[minor].isOn   = imx_uart_isr_is_on;
++
++    imx_uart_rx_isr_data[minor].hdl    = imx_uart_rx_isr;
++    imx_uart_rx_isr_data[minor].handle = &imx_uart_data[minor];
++    imx_uart_rx_isr_data[minor].on     = imx_uart_isr_on;
++    imx_uart_rx_isr_data[minor].off    = imx_uart_isr_off;
++    imx_uart_rx_isr_data[minor].isOn   = imx_uart_isr_is_on;
++#endif
++
++    imx_uart_data[minor].regs->cr1 = (
++        MC9328MXL_UART_CR1_UARTCLKEN |
++        MC9328MXL_UART_CR1_UARTEN);
++
++    imx_uart_data[minor].regs->cr2 = (
++        MC9328MXL_UART_CR2_IRTS |
++        MC9328MXL_UART_CR2_WS   |
++        MC9328MXL_UART_CR2_TXEN |
++        MC9328MXL_UART_CR2_RXEN |
++        MC9328MXL_UART_CR2_SRST);
++
++    imx_uart_data[minor].regs->cr3 = 0;
++
++    imx_uart_data[minor].regs->cr4 = 0;
++
++    imx_uart_data[minor].regs->fcr = (
++        MC9328MXL_UART_FCR_TXTL(32) |
++        MC9328MXL_UART_FCR_RFDIV_1 |
++        MC9328MXL_UART_FCR_RXTL(1));
++
++    imx_uart_set_baud(minor, 38400);
++
+ }
++static int imx_uart_first_open(int major, int minor, void *arg)
++{
++    rtems_libio_open_close_args_t *args = arg;
+-/* 
+- * Write buffer to UART 
+- *
+- * return 1 on success, -1 on error
+- */
+-static int uart_write(int minor, const char *buf, int len)
++    imx_uart_data[minor].tty   = args->iop->data1;
++
++#if defined(USE_INTERRUPTS)
++    BSP_install_rtems_irq_handler(&imx_uart_tx_isr_data[minor]);
++    BSP_install_rtems_irq_handler(&imx_uart_rx_isr_data[minor]);
++
++    imx_uart_data[minor].regs->cr1 |= MC9328MXL_UART_CR1_RRDYEN;
++#endif
++
++    return 0;
++}
++
++static int imx_uart_last_close(int major, int minor, void *arg)
+ {
+-    int i;
++#if defined(USE_INTERRUPTS)
++    BSP_remove_rtems_irq_handler(&imx_uart_tx_isr_data[minor]);
++    BSP_remove_rtems_irq_handler(&imx_uart_rx_isr_data[minor]);
++#endif
+-    if (minor == 0) {
+-        for (i = 0; i < len; i++) {
+-            /* Wait for fifo to have room */
+-            while(!(MC9328MXL_UART1_SR2 & MC9328MXL_UART_SR2_TXDC)) {
+-                continue;
+-            }
+-            
+-            MC9328MXL_UART1_TXD = (char) buf[i];
+-        }
+-    } else if (minor == 1) {
+-        for (i = 0; i < len; i++) {
+-            /* Wait for fifo to have room */
+-            while(!(MC9328MXL_UART2_SR2 & MC9328MXL_UART_SR2_TXDC)) {
+-                continue;
+-            }
+-            
+-            MC9328MXL_UART2_TXD = (char) buf[i];
+-        }
++    return 0;
++}
++
++static int imx_uart_poll_read(int minor)
++{
++    if (imx_uart_data[minor].regs->sr2 & MC9328MXL_UART_SR2_RDR) {
++        return imx_uart_data[minor].regs->rxd & 0xff;
+     } else {
+-        printk("Unknown console minor number: %d\n", minor);
+         return -1;
+     }
+-    
+-    return 1;
+ }
+-/* Set up the UART. */
+-static void uart_init(int minor)
++static int imx_uart_poll_write(int minor, const char *buf, int len)
+ {
+-        /* leave the debug sio port as setup by umon */
++    int i;
++    for (i = 0; i < len; i++) {
++        /* Wait for there to be room in the fifo */
++        while (!(imx_uart_data[minor].regs->sr2 & MC9328MXL_UART_SR2_TXDC)) {
++            continue;
++        }
++
++        imx_uart_data[minor].regs->txd = buf[i];
++    }
++    return 1;
++
+ }
+-/* I'm not sure this is needed for the shared console driver. */
+-static void    uart_write_polled(int minor, char c)
++#if defined(USE_INTERRUPTS)
++static int imx_uart_intr_write(int minor, const char *buf, int len)
+ {
+-    uart_write(minor, &c, 1);
++    imx_uart_data[minor].buf = buf;
++    imx_uart_data[minor].len = len;
++    imx_uart_data[minor].idx = 0;
++
++    imx_uart_data[minor].regs->cr1 |= MC9328MXL_UART_CR1_TXMPTYEN;
++
++    return 1;
+ }
++#endif
++
+ /* This is for setting baud rate, bits, etc. */
+-static int     uart_set_attributes(int minor, const struct termios *t) 
++static int imx_uart_set_attrs(int minor, const struct termios *t)
+ {
++    int baud;
++
++    baud = termios_baud_to_number(t->c_cflag & CBAUD);
++    imx_uart_set_baud(minor, baud);
++
+     return 0;
+ }
+-/***********************************************************************/
++#if defined(USE_INTERRUPTS)
++static void imx_uart_isr_on(const rtems_irq_connect_data *irq)
++{
++    MC9328MXL_AITC_INTENNUM = irq->name;
++}
++static void imx_uart_isr_off(const rtems_irq_connect_data *irq)
++{
++    MC9328MXL_AITC_INTDISNUM = irq->name;
++}
++static int imx_uart_isr_is_on(const rtems_irq_connect_data *irq)
++{
++    int irq_num = (int)irq->name;
++    if (irq_num < 32) {
++        return MC9328MXL_AITC_INTENABLEL & (1 << irq_num);
++    } else {
++        return MC9328MXL_AITC_INTENABLEH & (1 << (irq_num - 32));
++    }
++}
++
++static void imx_uart_rx_isr(rtems_irq_hdl_param param)
++{
++    imx_uart_data_t *uart_data = param;
++    char buf[32];
++    int i=0;
++
++    while (uart_data->regs->sr2 & MC9328MXL_UART_SR2_RDR) {
++        buf[i] = uart_data->regs->rxd & 0xff;
++        i++;
++    }
++
++    rtems_termios_enqueue_raw_characters(uart_data->tty, buf, i);
++}
++
++static void imx_uart_tx_isr(rtems_irq_hdl_param param)
++{
++    imx_uart_data_t *uart_data = param;
++    int len;
++    int minor = uart_data->minor;
++
++
++    if (uart_data->idx < uart_data->len) {
++        while ( (uart_data->regs->sr1 & MC9328MXL_UART_SR1_TRDY) &&
++                (uart_data->idx < uart_data->len)) {
++            uart_data->regs->txd = uart_data->buf[uart_data->idx];
++            uart_data->idx++;
++        }
++    } else {
++        len = uart_data->len;
++        uart_data->len = 0;
++        imx_uart_data[minor].regs->cr1 &= ~MC9328MXL_UART_CR1_TXMPTYEN;
++        rtems_termios_dequeue_characters(uart_data->tty, len);
++    }
++}
++#endif
++
+ /*
+- * The following functions are not used by TERMIOS, but other RTEMS
+- * functions use them instead.
++ * Set the UART's baud rate. The calculation is:
++ *   (baud * 16) / ref_freq  = num/demom
++ *
++ *   ref_freq = perclk1 / RFDIV[2:0]
++ *   BIR = num - 1
++ *   BMR = demom - 1
++ *
++ * Setting 'num' to 16 yields this equation:
++ *    demom = ref_freq / baud
+  */
+-/***********************************************************************/
+-/* 
+- * Read from UART. This is used in the exit code, and can't
+- * rely on interrupts.
+-*/
+-int uart_poll_read(int minor)
++static void imx_uart_set_baud(int minor, int baud)
+ {
+-    return uart_read(minor);
++    unsigned int perclk1;
++    unsigned int denom;
++    unsigned int ref_freq = 0;
++    uint32_t fcr;
++
++    perclk1 = get_perclk1_freq();
++    fcr = imx_uart_data[minor].regs->fcr;
++
++    switch(fcr & MC9328MXL_UART_FCR_RFDIV_MASK) {
++    case MC9328MXL_UART_FCR_RFDIV_1:  ref_freq = perclk1/1; break;
++    case MC9328MXL_UART_FCR_RFDIV_2:  ref_freq = perclk1/2; break;
++    case MC9328MXL_UART_FCR_RFDIV_3:  ref_freq = perclk1/3; break;
++    case MC9328MXL_UART_FCR_RFDIV_4:  ref_freq = perclk1/4; break;
++    case MC9328MXL_UART_FCR_RFDIV_5:  ref_freq = perclk1/5; break;
++    case MC9328MXL_UART_FCR_RFDIV_6:  ref_freq = perclk1/6; break;
++    case MC9328MXL_UART_FCR_RFDIV_7:  ref_freq = perclk1/7; break;
++    default:
++        rtems_panic("%s:%d Unknown RFDIV: 0x%x",
++                    __FUNCTION__, __LINE__,
++                    fcr & MC9328MXL_UART_FCR_RFDIV_MASK);
++        break;
++    }
++
++    denom = ref_freq / baud;
++
++    imx_uart_data[minor].regs->bir = 0xf;
++    imx_uart_data[minor].regs->bmr = denom;
+ }
+ /*
+- * Write a character to the console. This is used by printk() and 
+- * maybe other low level functions. It should not use interrupts or any
+- * RTEMS system calls. It needs to be very simple
++ * Polled, non-blocking read from UART
++ */
++int imx_uart_poll_read_char(int minor)
++{
++    return imx_uart_poll_read(minor);
++}
++
++/*
++ * Polled, blocking write from UART
+  */
+-static void _BSP_put_char( char c ) {
+-    uart_write_polled(0, c);
++void  imx_uart_poll_write_char(int minor, char c)
++{
++    imx_uart_poll_write(minor, &c, 1);
++}
++
++/*
++ * Functions for printk() and friends.
++ */
++void _BSP_output_char(char c)
++{
++    poll_write(c);
+     if (c == '\n') {
+-        uart_write_polled(0, '\r');
++        poll_write('\r');
+     }
+ }
++BSP_output_char_function_type BSP_output_char = _BSP_output_char;
+-BSP_output_char_function_type BSP_output_char = _BSP_put_char;
++char _BSP_poll_char()
++{
++    return poll_read();
++}
++BSP_polling_getchar_function_type BSP_poll_char = _BSP_poll_char;
+Index: rtems/c/src/lib/libbsp/arm/csb336/Makefile.am
+===================================================================
+--- rtems.orig/c/src/lib/libbsp/arm/csb336/Makefile.am
++++ rtems/c/src/lib/libbsp/arm/csb336/Makefile.am
+@@ -35,7 +35,7 @@ startup_rel_CPPFLAGS = $(AM_CPPFLAGS)
+ startup_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
+ noinst_PROGRAMS += console.rel
+-console_rel_SOURCES = console/uart.c ../../shared/console.c
++console_rel_SOURCES = console/uart.c
+ console_rel_CPPFLAGS = $(AM_CPPFLAGS)
+ console_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)