Index: c/src/lib/libcpu/bfin/ChangeLog
===================================================================
--- c/src/lib/libcpu/bfin/ChangeLog	(revision 5eb50f38e943e831f528d68eb0d09910cf2548ae)
+++ c/src/lib/libcpu/bfin/ChangeLog	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
@@ -1,2 +1,16 @@
+2011-04-20  Rohan Kangralkar <rkangral@ece.neu.edu>
+
+	PR 1781/bsps
+	* bf52x/include: Added additional MMR. 
+	* bf52x/interrupt: The BF52X processors have a different
+	System interrupt controller than present in the 53X range of
+	processors. The 52X have 8 interrupt assignment registers. The
+	implementation uses tables to increase predictability.
+	* serial/uart.?: Added DMA based and interrupt based transfer
+	support. The uart code used a single ISR for TX and RX and tried
+	to identify and multiplex inside the ISR. In the new code the
+	type of interrupt is identified by the central ISR dispatcher
+	bf52x/interrupt or interrupt/.	This simplifies the UART ISR.
+
 2011-02-11	Ralf CorsÃ©pius <ralf.corsepius@rtems.org>
 
Index: c/src/lib/libcpu/bfin/Makefile.am
===================================================================
--- c/src/lib/libcpu/bfin/Makefile.am	(revision 5eb50f38e943e831f528d68eb0d09910cf2548ae)
+++ c/src/lib/libcpu/bfin/Makefile.am	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
@@ -11,6 +11,28 @@
 noinst_PROGRAMS =
 
+include_bspdir = $(includedir)/bsp
 include_libcpudir = $(includedir)/libcpu
+
+include_bsp_HEADERS =
 include_libcpu_HEADERS =
+
+
+############
+# Start of bf52x files
+if bf52x
+
+include_HEADERS = bf52x/include/bf52x.h
+
+## INTERRUPT
+include_bsp_HEADERS += bf52x/interrupt/interrupt.h
+noinst_PROGRAMS += bf52x/interrupt.rel
+bf52x_interrupt_rel_SOURCES = bf52x/interrupt/interrupt.c \
+                              bf52x/interrupt/interrupt.h
+bf52x_interrupt_rel_CPPFLAGS = $(AM_CPPFLAGS)
+bf52x_interrupt_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
+
+endif
+# endof bf52x
+############
 
 include_libcpu_HEADERS += include/bf533.h
@@ -48,4 +70,7 @@
 mmu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
 
+if bf52x
+
+else
 include_libcpu_HEADERS += interrupt/interrupt.h
 noinst_PROGRAMS += interrupt.rel
@@ -53,4 +78,6 @@
 interrupt_rel_CPPFLAGS = $(AM_CPPFLAGS)
 interrupt_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
+
+endif
 
 noinst_PROGRAMS += clock.rel
Index: c/src/lib/libcpu/bfin/bf52x/include/bf52x.h
===================================================================
--- c/src/lib/libcpu/bfin/bf52x/include/bf52x.h	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
+++ c/src/lib/libcpu/bfin/bf52x/include/bf52x.h	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
@@ -0,0 +1,133 @@
+/**
+ *@file bf52x.h
+ *
+ *@brief
+ *  - This file provides the register address for the 52X model. The file is
+ *  based on the 533 implementation with some addition to support 52X range of
+ *  processors.
+ *
+ * Target:   TLL6527v1-0
+ * Compiler:
+ *
+ * COPYRIGHT (c) 2010 by ECE Northeastern University.
+ *
+ * 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
+ *
+ * @author Rohan Kangralkar, ECE, Northeastern University
+ *         (kangralkar.r@husky.neu.edu)
+ *
+ * LastChange:
+ * $Id$
+ *
+ */
+
+#ifndef _BF52X_H_
+#define _BF52X_H_
+
+/* register (or register block) addresses */
+
+#define SIC_BASE_ADDRESS                          0xffc00100
+#define WDOG_BASE_ADDRESS                         0xffc00200
+#define RTC_BASE_ADDRESS                          0xffc00300
+#define UART0_BASE_ADDRESS                        0xffc00400
+#define UART1_BASE_ADDRESS                        0xffc02000
+#define SPI_BASE_ADDRESS                          0xffc00500
+#define TIMER_BASE_ADDRESS                        0xffc00600
+#define TIMER_CHANNELS                                     3
+#define TIMER_PITCH                                     0x10
+#define TIMER0_BASE_ADDRESS                       0xffc00600
+#define TIMER1_BASE_ADDRESS                       0xffc00610
+#define TIMER2_BASE_ADDRESS                       0xffc00620
+#define TIMER_ENABLE                              0xffc00640
+#define TIMER_DISABLE                             0xffc00644
+#define TIMER_STATUS                              0xffc00648
+#define PORTFIO_BASE_ADDRESS                      0xffc00700
+#define SPORT0_BASE_ADDRESS                       0xffc00800
+#define SPORT1_BASE_ADDRESS                       0xffc00900
+#define EBIU_BASE_ADDRESS                         0xffc00a00
+#define DMA_TC_PER                                0xffc00b0c
+#define DMA_TC_CNT                                0xffc00b10
+#define DMA_BASE_ADDRESS                          0xffc00c00
+#define DMA_CHANNELS                                       8
+#define DMA_PITCH                                       0x40
+#define DMA0_BASE_ADDRESS                         0xffc00c00
+#define DMA1_BASE_ADDRESS                         0xffc00c40
+#define DMA2_BASE_ADDRESS                         0xffc00c80
+#define DMA3_BASE_ADDRESS                         0xffc00cc0
+#define DMA4_BASE_ADDRESS                         0xffc00d00
+#define DMA5_BASE_ADDRESS                         0xffc00d40
+#define DMA6_BASE_ADDRESS                         0xffc00d80
+#define DMA7_BASE_ADDRESS                         0xffc00dc0
+#define DMA8_BASE_ADDRESS                         0xffc00e00
+#define DMA9_BASE_ADDRESS                         0xffc00e40
+#define DMA10_BASE_ADDRESS                        0xffc00e80
+#define DMA11_BASE_ADDRESS                        0xffc00ec0
+#define MDMA_BASE_ADDRESS                         0xffc00e00
+#define MDMA_CHANNELS                                      2
+#define MDMA_D_S                                        0x40
+#define MDMA_PITCH                                      0x80
+#define MDMA0D_BASE_ADDRESS                       0xffc00e00
+#define MDMA0S_BASE_ADDRESS                       0xffc00e40
+#define MDMA1D_BASE_ADDRESS                       0xffc00e80
+#define MDMA1S_BASE_ADDRESS                       0xffc00ec0
+#define PPI_BASE_ADDRESS                          0xffc01000
+
+
+/* register fields */
+
+#define DMA_TC_PER_MDMA_ROUND_ROBIN_PERIOD_MASK       0xf800
+#define DMA_TC_PER_MDMA_ROUND_ROBIN_PERIOD_SHIFT          11
+#define DMA_TC_PER_DAB_TRAFFIC_PERIOD_MASK            0x0700
+#define DMA_TC_PER_DAB_TRAFFIC_PERIOD_SHIFT                8
+#define DMA_TC_PER_DEB_TRAFFIC_PERIOD_MASK            0x00f0
+#define DMA_TC_PER_DEB_TRAFFIC_PERIOD_SHIFT                4
+#define DMA_TC_PER_DCB_TRAFFIC_PERIOD_MASK            0x000f
+#define DMA_TC_PER_DCB_TRAFFIC_PERIOD_SHIFT                0
+
+#define DMA_TC_CNT_MDMA_ROUND_ROBIN_COUNT_MASK        0xf800
+#define DMA_TC_CNT_MDMA_ROUND_ROBIN_COUNT_SHIFT           11
+#define DMA_TC_CNT_DAB_TRAFFIC_COUNT_MASK             0x0700
+#define DMA_TC_CNT_DAB_TRAFFIC_COUNT_SHIFT                 8
+#define DMA_TC_CNT_DEB_TRAFFIC_COUNT_MASK             0x00f0
+#define DMA_TC_CNT_DEB_TRAFFIC_COUNT_SHIFT                 4
+#define DMA_TC_CNT_DCB_TRAFFIC_COUNT_MASK             0x000f
+#define DMA_TC_CNT_DCB_TRAFFIC_COUNT_SHIFT                 0
+
+#define TIMER_ENABLE_TIMEN2                           0x0004
+#define TIMER_ENABLE_TIMEN1                           0x0002
+#define TIMER_ENABLE_TIMEN0                           0x0001
+
+#define TIMER_DISABLE_TIMDIS2                         0x0004
+#define TIMER_DISABLE_TIMDIS1                         0x0002
+#define TIMER_DISABLE_TIMDIS0                         0x0001
+
+#define TIMER_STATUS_TRUN2                        0x00004000
+#define TIMER_STATUS_TRUN1                        0x00002000
+#define TIMER_STATUS_TRUN0                        0x00001000
+#define TIMER_STATUS_TOVF_ERR2                    0x00000040
+#define TIMER_STATUS_TOVF_ERR1                    0x00000020
+#define TIMER_STATUS_TOVF_ERR0                    0x00000010
+#define TIMER_STATUS_TIMIL2                       0x00000004
+#define TIMER_STATUS_TIMIL1                       0x00000002
+#define TIMER_STATUS_TIMIL0                       0x00000001
+
+/* Core Event Controller vectors */
+
+#define CEC_EMULATION_VECTOR                               0
+#define CEC_RESET_VECTOR                                   1
+#define CEC_NMI_VECTOR                                     2
+#define CEC_EXCEPTIONS_VECTOR                              3
+#define CEC_HARDWARE_ERROR_VECTOR                          5
+#define CEC_CORE_TIMER_VECTOR                              6
+#define CEC_INTERRUPT_BASE_VECTOR                          7
+#define CEC_INTERRUPT_COUNT                                9
+
+
+/* System Interrupt Controller vectors */
+
+#define SIC_IAR_COUNT                                      8
+
+#endif /* _BF52X_H_ */
+
Index: c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.c
===================================================================
--- c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.c	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
+++ c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.c	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
@@ -0,0 +1,643 @@
+/**
+ *@file interrupt.c
+ *
+ *@brief
+ * - This file implements interrupt dispatcher. Most of the code is taken from
+ *  the 533 implementation for blackfin. Since 52X supports 56 line and 2 ISR
+ *  registers some portion is written twice.
+ *
+ * Target:   TLL6527v1-0
+ * Compiler:
+ *
+ * COPYRIGHT (c) 2010 by ECE Northeastern University.
+ *
+ * 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
+ *
+ * @author Rohan Kangralkar, ECE, Northeastern University
+ *         (kangralkar.r@husky.neu.edu)
+ *
+ * LastChange:
+ * $Id$
+ *
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include <bsp.h>
+#include <libcpu/cecRegs.h>
+#include <libcpu/sicRegs.h>
+#include "interrupt.h"
+
+#define SIC_IAR_COUNT_SET0		  4
+#define SIC_IAR_BASE_ADDRESS_0  0xFFC00150
+
+/**
+ * There are two implementations for the interrupt handler.
+ * 1. INTERRUPT_USE_TABLE: uses tables for finding the right ISR.
+ * 2. Uses link list to find the user ISR.
+ *
+ *
+ * 1. INTERRUPT_USE_TABLE
+ * Space requirement:
+ *  - Array to hold CEC masks size: CEC_INTERRUPT_COUNT(9)*(2*int).9*2*4= 72B
+ *  - Array to hold isr function pointers IRQ_MAX(56)*sizeof(bfin_isr_t)= 896B
+ *  - Array for bit twidlling 32 bytes.
+ *  - Global Mask 8 bytes.
+ *  - Total = 1008 Bytes Aprox
+ *
+ * Time requirements
+ *    The worst case time is about the same for jumping to the user ISR. With a
+ *    variance of one conditional statement.
+ *
+ * 2. Using link list.
+ * Space requirement:
+ *  - Array to hold CEC mask CEC_INTERRUPT_COUNT(9)*(sizeof(vectors)).
+ *                                                                 9*3*4= 108B
+ *  - Array to hold isr IRQ_MAX(56)*sizeof(bfin_isr_t) The structure has
+ *    additional pointers                                         56*7*4=1568B
+ *  - Global Mask 8 bytes.
+ *    Total = 1684.
+ * Time requirements
+ *    In the worst case all the lines can be on one CEC line to 56 entries have
+ *    to be traversed to find the right user ISR.
+ *    But this implementation has benefit of being flexible, Providing
+ *    additional user assigned priority. and may consume less space
+ *    if all devices are not supported.
+ */
+
+/**
+ * TODO: To place the dispatcher routine code in L1.
+ */
+
+#if INTERRUPT_USE_TABLE
+
+
+/******************************************************************************
+ * Static variables
+ *****************************************************************************/
+/**
+ * @var sic_isr0_mask
+ * @brief copy of the mask of SIC ISR. The SIC ISR is cleared by the device
+ * the relevant SIC_ISRx bit is not cleared unless the interrupt
+ * service routine clears the mechanism that generated interrupt
+ */
+static uint32_t sic_isr0_mask = 0;
+
+/**
+ * @var sic_isr0_mask
+ * @brief copy of the mask of SIC ISR. The SIC ISR is cleared by the device
+ * the relevant SIC_ISRx bit is not cleared unless the interrupt
+ * service routine clears the mechanism that generated interrupt
+ */
+static uint32_t sic_isr1_mask = 0;
+
+
+/**
+ * @var sic_isr
+ * @brief An array of sic register mask for each of the 16 core interrupt lines
+ */
+static struct {
+  uint32_t mask0;
+  uint32_t mask1;
+} vectors[CEC_INTERRUPT_COUNT];
+
+/**
+ * @var ivt
+ * @brief Contains a table of ISR and arguments. The ISR jumps directly to
+ * these ISR.
+ */
+static bfin_isr_t ivt[IRQ_MAX];
+
+/**
+ * http://graphics.stanford.edu/~seander/bithacks.html for more details
+ */
+static const char clz_table[32] =
+{
+    0, 31, 9, 30, 3, 8, 18, 29, 2, 5, 7, 14, 12, 17,
+    22, 28, 1, 10, 4, 19, 6, 15, 13, 23, 11, 20, 16,
+    24, 21, 25, 26, 27
+};
+
+/**
+ * finds the first bit set from the left. look at
+ * http://graphics.stanford.edu/~seander/bithacks.html for more details
+ * @param n
+ * @return
+ */
+static unsigned long clz(unsigned long n)
+{
+  unsigned long c = 0x7dcd629;       /* magic constant... */
+
+  n |= (n >> 1);
+  n |= (n >> 2);
+  n |= (n >> 4);
+  n |= (n >> 8);
+  n |= (n >> 16);
+  if (n == 0) return 32;
+  n = c + (c * n);
+  return 31 - clz_table[n >> 27];       /* For little endian    */
+}
+
+
+
+/**
+ * Centralized Interrupt dispatcher routine. This routine dispatches interrupts
+ * to the user ISR. The priority is according to the blackfin SIC.
+ * The first level of priority is handled in the hardware at the core event
+ * controller. The second level of interrupt is handled according to the line
+ * number that goes in to the SIC.
+ * * SIC_0 has higher priority than SIC 1.
+ * * Inside the SIC the priority is assigned according to the line number.
+ *   Lower the line number higher the priority.
+ *
+ *   In order to change the interrupt priority we may
+ *   1. change the SIC IAR registers or
+ *   2. Assign priority and extract it inside this function and call the ISR
+ *   according tot the priority.
+ *
+ * @param vector IVG number.
+ * @return
+ */
+static rtems_isr interruptHandler(rtems_vector_number vector) {
+  uint32_t mask = 0;
+  int id = 0;
+  /**
+   * Enable for debugging
+   *
+   * static volatile uint32_t spurious_sic0    = 0;
+   * static volatile uint32_t spurious_source  = 0;
+   * static volatile uint32_t spurious_sic1    = 0;
+   */
+
+  /**
+   * Extract the vector number relative to the SIC start line
+   */
+  vector -= CEC_INTERRUPT_BASE_VECTOR;
+
+  /**
+   * Check for bounds
+   */
+  if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
+
+    /**
+     * Extract information and execute ISR from SIC 0
+     */
+    mask = *(uint32_t volatile *) SIC_ISR &
+        *(uint32_t volatile *) SIC_IMASK & vectors[vector].mask0;
+    id      = clz(mask);
+    if ( SIC_ISR0_MAX > id ) {
+      /** Parameter check */
+      if( NULL != ivt[id].pFunc) {
+        /** Call the relevant function with argument */
+        ivt[id].pFunc( ivt[id].pArg );
+      } else {
+        /**
+         * spurious interrupt we should not be getting this
+         * spurious_sic0++;
+         * spurious_source = id;
+         */
+      }
+    } else {
+      /**
+       * we look at SIC 1
+       */
+    }
+
+
+    /**
+     * Extract information and execute ISR from SIC 1
+     */
+    mask    = *(uint32_t volatile *) (SIC_ISR + SIC_ISR_PITCH) &
+        *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) &
+        vectors[vector].mask1;
+    id      = clz(mask)+SIC_ISR0_MAX;
+    if ( IRQ_MAX > id ) {
+      /** Parameter Check */
+      if( NULL != ivt[id].pFunc ) {
+        /** Call the relevant function with argument */
+        ivt[id].pFunc( ivt[id].pArg );
+      } else {
+        /**
+         * spurious interrupt we should not be getting this
+         *
+         * spurious_sic1++;
+         * spurious_source = id;
+         */
+      }
+    } else {
+      /**
+       * we continue
+       */
+    }
+
+  }
+}
+
+
+
+/**
+ * This routine registers a new ISR. It will write a new entry to the IVT table
+ * @param isr contains a callback function and source
+ * @return rtems status code
+ */
+rtems_status_code bfin_interrupt_register(bfin_isr_t *isr) {
+  rtems_interrupt_level isrLevel;
+  int               id        = 0;
+  int               position  = 0;
+
+  /**
+   * Sanity Check
+   */
+  if ( NULL == isr ){
+    return RTEMS_UNSATISFIED;
+  }
+
+  /**
+   * Sanity check. The register function should at least provide callback func
+   */
+  if ( NULL == isr->pFunc ) {
+    return RTEMS_UNSATISFIED;
+  }
+
+  id = isr->source;
+
+  /**
+   * Parameter Check. We already have a function registered here. First
+   * unregister and then a new function can be allocated.
+   */
+  if ( NULL != ivt[id].pFunc ) {
+    return RTEMS_UNSATISFIED;
+  }
+
+  rtems_interrupt_disable(isrLevel);
+  /**
+   * Assign the new function pointer to the ISR Dispatcher
+   * */
+  ivt[id].pFunc    = isr->pFunc;
+  ivt[id].pArg     = isr->pArg;
+
+
+  /** find out which isr mask has to be set to enable the interrupt */
+  if ( SIC_ISR0_MAX > id ) {
+    sic_isr0_mask |= 0x1<<id;
+    *(uint32_t volatile *) SIC_IMASK  |= 0x1<<id;
+  } else {
+    position = id - SIC_ISR0_MAX;
+    sic_isr1_mask |= 0x1<<position;
+    *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH)  |= 0x1<<position;
+  }
+
+  rtems_interrupt_enable(isrLevel);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+
+/**
+ * This function unregisters a registered interrupt handler.
+ * @param isr
+ */
+rtems_status_code bfin_interrupt_unregister(bfin_isr_t *isr) {
+  rtems_interrupt_level isrLevel;
+  int               id        = 0;
+  int               position  = 0;
+
+  /**
+   * Sanity Check
+   */
+  if ( NULL == isr ){
+    return RTEMS_UNSATISFIED;
+  }
+
+  id = isr->source;
+
+  rtems_interrupt_disable(isrLevel);
+  /**
+   * Assign the new function pointer to the ISR Dispatcher
+   * */
+  ivt[id].pFunc    = NULL;
+  ivt[id].pArg     = NULL;
+
+
+  /** find out which isr mask has to be set to enable the interrupt */
+  if ( SIC_ISR0_MAX > id ) {
+    sic_isr0_mask &= ~(0x1<<id);
+    *(uint32_t volatile *) SIC_IMASK  &= ~(0x1<<id);
+  } else {
+    position = id - SIC_ISR0_MAX;
+    sic_isr1_mask &= ~(0x1<<position);
+    *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH)  &= ~(0x1<<position);
+  }
+
+  rtems_interrupt_enable(isrLevel);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+
+
+
+/**
+ * blackfin interrupt initialization routine. It initializes the bfin ISR
+ * dispatcher. It will also create SIC CEC map which will be used for
+ * identifying the ISR.
+ */
+void bfin_interrupt_init(void) {
+  int source;
+  int vector;
+  uint32_t r;
+  int i;
+  int j;
+
+  *(uint32_t volatile *) SIC_IMASK = 0;
+  *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) = 0;
+
+  memset(vectors, 0, sizeof(vectors));
+  /* build mask0 showing what SIC sources drive each CEC vector */
+  source = 0;
+
+  /**
+   * The bf52x has 8 IAR registers but they do not have a constant pitch.
+   *
+   */
+  for (i = 0; i < SIC_IAR_COUNT; i++) {
+    if ( SIC_IAR_COUNT_SET0 > i ) {
+      r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS + i * SIC_IAR_PITCH);
+    } else {
+      r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS_0 +
+          ((i-SIC_IAR_COUNT_SET0) * SIC_IAR_PITCH));
+    }
+
+    for (j = 0; j < 8; j++) {
+      vector = r & 0x0f;
+      if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
+        /* install our local handler */
+        if (vectors[vector].mask0 == 0 && vectors[vector].mask1 == 0){
+          set_vector(interruptHandler, vector + CEC_INTERRUPT_BASE_VECTOR, 1);
+        }
+        if ( SIC_ISR0_MAX > source ) {
+          vectors[vector].mask0 |= (1 << source);
+        } else {
+          vectors[vector].mask1 |= (1 << (source - SIC_ISR0_MAX));
+        }
+      }
+      r >>= 4;
+      source++;
+    }
+  }
+}
+
+
+
+
+
+#else
+
+static struct {
+  uint32_t mask0;
+  uint32_t mask1;
+  bfin_isr_t *head;
+} vectors[CEC_INTERRUPT_COUNT];
+
+static uint32_t globalMask0;
+static uint32_t globalMask1;
+
+static rtems_isr interruptHandler(rtems_vector_number vector) {
+  bfin_isr_t *isr = NULL;
+  uint32_t sourceMask0 = 0;
+  uint32_t sourceMask1 = 0;
+  rtems_interrupt_level isrLevel;
+
+  rtems_interrupt_disable(isrLevel);
+  vector -= CEC_INTERRUPT_BASE_VECTOR;
+  if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
+    isr = vectors[vector].head;
+    sourceMask0 = *(uint32_t volatile *) SIC_ISR &
+        *(uint32_t volatile *) SIC_IMASK;
+    sourceMask1 = *(uint32_t volatile *) (SIC_ISR + SIC_ISR_PITCH) &
+        *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH);
+    while (isr) {
+      if ((sourceMask0 & isr->mask0) || (sourceMask1 & isr->mask1)) {
+        isr->isr(isr->_arg);
+        sourceMask0 = *(uint32_t volatile *) SIC_ISR &
+            *(uint32_t volatile *) SIC_IMASK;
+        sourceMask1 = *(uint32_t volatile *) (SIC_ISR + SIC_ISR_PITCH) &
+            *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH);
+      }
+      isr = isr->next;
+    }
+  }
+  rtems_interrupt_enable(isrLevel);
+}
+
+/**
+ * Initializes the interrupt module
+ */
+void bfin_interrupt_init(void) {
+  int source;
+  int vector;
+  uint32_t r;
+  int i;
+  int j;
+
+  globalMask0 = ~(uint32_t) 0;
+  globalMask1 = ~(uint32_t) 0;
+  *(uint32_t volatile *) SIC_IMASK = 0;
+  *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) = 0;
+
+  memset(vectors, 0, sizeof(vectors));
+  /* build mask0 showing what SIC sources drive each CEC vector */
+  source = 0;
+
+  /**
+   * The bf52x has 8 IAR registers but they do not have a constant pitch.
+   *
+   */
+  for (i = 0; i < SIC_IAR_COUNT; i++) {
+    if ( SIC_IAR_COUNT_SET0 > i ) {
+      r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS + i * SIC_IAR_PITCH);
+    } else {
+      r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS_0 +
+          ((i-SIC_IAR_COUNT_SET0) * SIC_IAR_PITCH));
+    }
+    for (j = 0; j < 8; j++) {
+      vector = r & 0x0f;
+      if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
+        /* install our local handler */
+        if (vectors[vector].mask0 == 0 && vectors[vector].mask1 == 0){
+          set_vector(interruptHandler, vector + CEC_INTERRUPT_BASE_VECTOR, 1);
+        }
+        if ( SIC_ISR0_MAX > source ) {
+          vectors[vector].mask0 |= (1 << source);
+        } else {
+          vectors[vector].mask1 |= (1 << (source - SIC_ISR0_MAX));
+        }
+      }
+      r >>= 4;
+      source++;
+    }
+  }
+}
+
+/* modify SIC_IMASK based on ISR list for a particular CEC vector */
+static void setMask(uint32_t vector) {
+  bfin_isr_t *isr = NULL;
+  uint32_t mask = 0;
+  uint32_t r    = 0;
+
+  mask = 0;
+  isr = vectors[vector].head;
+  while (isr) {
+    mask |= isr->mask0;
+    isr = isr->next;
+  }
+  r = *(uint32_t volatile *) SIC_IMASK;
+  r &= ~vectors[vector].mask0;
+  r |= mask;
+  r &= globalMask0;
+  *(uint32_t volatile *) SIC_IMASK = r;
+
+
+  mask = 0;
+  isr = vectors[vector].head;
+  while (isr) {
+    mask |= isr->mask1;
+    isr = isr->next;
+  }
+  r = *(uint32_t volatile *) (SIC_IMASK+ SIC_IMASK_PITCH);
+  r &= ~vectors[vector].mask1;
+  r |= mask;
+  r &= globalMask1;
+  *(uint32_t volatile *) (SIC_IMASK+ SIC_IMASK_PITCH) = r;
+}
+
+/* add an ISR to the list for whichever vector it belongs to */
+rtems_status_code bfin_interrupt_register(bfin_isr_t *isr) {
+  bfin_isr_t *walk;
+  rtems_interrupt_level isrLevel;
+
+  /* find the appropriate vector */
+  for (isr->vector = 0; isr->vector < CEC_INTERRUPT_COUNT; isr->vector++)
+    if ( (vectors[isr->vector].mask0 & (1 << isr->source) ) || \
+        (vectors[isr->vector].mask1 & (1 << (isr->source - SIC_ISR0_MAX)) ))
+      break;
+  if (isr->vector < CEC_INTERRUPT_COUNT) {
+    isr->next = NULL;
+    isr->mask0 = 0;
+    isr->mask1 = 0;
+    rtems_interrupt_disable(isrLevel);
+    /* find the current end of the list */
+    walk = vectors[isr->vector].head;
+    while (walk && walk->next)
+      walk = walk->next;
+    /* append new isr to list */
+    if (walk)
+      walk->next = isr;
+    else
+      vectors[isr->vector].head = isr;
+    rtems_interrupt_enable(isrLevel);
+  } else
+    /* we failed, but make vector a legal value so other calls into
+	       this module with this isr descriptor won't do anything bad */
+    isr->vector = 0;
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bfin_interrupt_unregister(bfin_isr_t *isr) {
+  bfin_isr_t *walk, *prev;
+  rtems_interrupt_level isrLevel;
+
+  rtems_interrupt_disable(isrLevel);
+  walk = vectors[isr->vector].head;
+  prev = NULL;
+  /* find this isr in our list */
+  while (walk && walk != isr) {
+    prev = walk;
+    walk = walk->next;
+  }
+  if (walk) {
+    /* if found, remove it */
+    if (prev)
+      prev->next = walk->next;
+    else
+      vectors[isr->vector].head = walk->next;
+    /* fix up SIC_IMASK if necessary */
+    setMask(isr->vector);
+  }
+  rtems_interrupt_enable(isrLevel);
+  return RTEMS_SUCCESSFUL;
+}
+
+void bfin_interrupt_enable(bfin_isr_t *isr, bool enable) {
+  rtems_interrupt_level isrLevel;
+
+  rtems_interrupt_disable(isrLevel);
+  if ( SIC_ISR0_MAX > isr->source ) {
+    isr->mask0 = enable ? (1 << isr->source) : 0;
+    *(uint32_t volatile *) SIC_IMASK |= isr->mask0;
+  }  else {
+    isr->mask1 = enable ? (1 << (isr->source - SIC_ISR0_MAX)) : 0;
+    *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) |= isr->mask1;
+  }
+
+  //setMask(isr->vector);
+  rtems_interrupt_enable(isrLevel);
+}
+
+void bfin_interrupt_enable_all(int source, bool enable) {
+  rtems_interrupt_level isrLevel;
+  int vector;
+  bfin_isr_t *walk;
+
+  for (vector = 0; vector < CEC_INTERRUPT_COUNT; vector++)
+    if ( (vectors[vector].mask0 & (1 << source) ) || \
+        (vectors[vector].mask1 & (1 << (source - SIC_ISR0_MAX)) ))
+      break;
+  if (vector < CEC_INTERRUPT_COUNT) {
+    rtems_interrupt_disable(isrLevel);
+    walk = vectors[vector].head;
+    while (walk) {
+      walk->mask0 = enable ? (1 << source) : 0;
+      walk = walk->next;
+    }
+
+    walk = vectors[vector].head;
+    while (walk) {
+      walk->mask1 = enable ? (1 << (source - SIC_ISR0_MAX)) : 0;
+      walk = walk->next;
+    }
+    setMask(vector);
+    rtems_interrupt_enable(isrLevel);
+  }
+}
+
+void bfin_interrupt_enable_global(int source, bool enable) {
+  int vector;
+  rtems_interrupt_level isrLevel;
+
+  for (vector = 0; vector < CEC_INTERRUPT_COUNT; vector++)
+    if ( (vectors[vector].mask0 & (1 << source) ) || \
+        (vectors[vector].mask1 & (1 << (source - SIC_ISR0_MAX)) ))
+      break;
+  if (vector < CEC_INTERRUPT_COUNT) {
+    rtems_interrupt_disable(isrLevel);
+    if ( SIC_ISR0_MAX > source ) {
+      if (enable)
+        globalMask0 |= 1 << source;
+      else
+        globalMask0 &= ~(1 << source);
+    }else {
+      if (enable)
+        globalMask1 |= 1 << (source - SIC_ISR0_MAX);
+      else
+        globalMask1 &= ~(1 << (source - SIC_ISR0_MAX));
+    }
+    setMask(vector);
+    rtems_interrupt_enable(isrLevel);
+  }
+}
+
+#endif
Index: c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.h
===================================================================
--- c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.h	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
+++ c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.h	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
@@ -0,0 +1,146 @@
+/**
+ *@file interrupt.h
+ *
+ *@brief
+ *  - This file implements interrupt dispatcher. The init code is taken from
+ *  the 533 implementation for blackfin. Since 52X supports 56 line and 2 ISR
+ *  registers some portion is written twice.
+ *
+ * Target:   TLL6527v1-0
+ * Compiler:
+ *
+ * COPYRIGHT (c) 2010 by ECE Northeastern University.
+ *
+ * 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
+ *
+ * @author Rohan Kangralkar, ECE, Northeastern University
+ *         (kangralkar.r@husky.neu.edu)
+ *
+ * LastChange:
+ * $Id$
+ *
+ */
+
+#ifndef _BFIN_INTERRUPT_H_
+#define _BFIN_INTERRUPT_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** The type of interrupts handled by the SIC
+ */
+typedef enum {
+    IRQ_PLL_WAKEUP_INTERRUPT,                 /* 0 */
+    IRQ_DMA_ERROR_0,                          /* 1 */
+    IRQ_DMAR0_BLOCK_INTERRUPT,                /* 2 */
+    IRQ_DMAR1_BLOCK_INTERRUPT,                /* 3 */
+    IRQ_DMAR0_OVERFLOW_ERROR,                 /* 4 */
+    IRQ_DMAR1_OVERFLOW_ERROR,                 /* 5 */
+    IRQ_PPI_STATUS,                           /* 6 */
+    IRQ_MAC_STATUS,                           /* 7 */
+    IRQ_SPORT0_STATUS,                        /* 8 */
+    IRQ_SPORT1_STATUS,                        /* 9 */
+    IRQ_RESERVED_10,                          /* 10 */
+    IRQ_RESERVED_11,                          /* 11 */
+    IRQ_UART0_STATUS,                         /* 12 */
+    IRQ_UART1_STATUS,                         /* 13 */
+    IRQ_REAL_TIME_CLOCK,                      /* 14 */
+    IRQ_DMA0_PPI_NFC,                         /* 15 */
+    IRQ_DMA3_SPORT0_RX,                       /* 16 */
+    IRQ_DMA4_SPORT0_TX,                       /* 17 */
+    IRQ_DMA5_SPORT1_RX,                       /* 18 */
+    IRQ_DMA6_SPORT1_TX,                       /* 19 */
+    IRQ_TWI_INTERRUPT,                        /* 20 */
+    IRQ_DMA7_SPI,                             /* 21 */
+    IRQ_DMA8_UART0_RX,                        /* 22 */
+    IRQ_DMA9_UART0_TX,                        /* 23 */
+    IRQ_DMA10_UART1_RX,                       /* 24 */
+    IRQ_DMA11_UART1_TX,                       /* 25 */
+    IRQ_OTP,                                  /* 26 */
+    IRQ_GP_COUNTER,                           /* 27 */
+    IRQ_DMA1_MAC_RX_HOSTDP,                   /* 28 */
+    IRQ_PORT_H_INTERRUPT_A,                   /* 29 */
+    IRQ_DMA2_MAC_TX_NFC,                      /* 30 */
+    IRQ_PORT_H_INTERRUPT_B,                   /* 31 */
+    SIC_ISR0_MAX,                             /* 32 ***/
+    IRQ_TIMER0 = SIC_ISR0_MAX,                /* 32 */
+    IRQ_TIMER1,                               /* 33 */
+    IRQ_TIMER2,                               /* 34 */
+    IRQ_TIMER3,                               /* 35 */
+    IRQ_TIMER4,                               /* 36 */
+    IRQ_TIMER5,                               /* 37 */
+    IRQ_TIMER6,                               /* 38 */
+    IRQ_TIMER7,                               /* 39 */
+    IRQ_PORT_G_INTERRUPT_A,                   /* 40 */
+    IRQ_PORT_G_INTERRUPT_B,                   /* 41 */
+    IRQ_MDMA0_STREAM_0_INTERRUPT,             /* 42 */
+    IRQ_MDMA1_STREAM_0_INTERRUPT,             /* 43 */
+    IRQ_SOFTWARE_WATCHDOG_INTERRUPT,          /* 44 */
+    IRQ_PORT_F_INTERRUPT_A,                   /* 45 */
+    IRQ_PORT_F_INTERRUPT_B,                   /* 46 */
+    IRQ_SPI_STATUS,                           /* 47 */
+    IRQ_NFC_STATUS,                           /* 48 */
+    IRQ_HOSTDP_STATUS,                        /* 49 */
+    IRQ_HOREAD_DONE_INTERRUPT,                /* 50 */
+    IRQ_RESERVED_19,                          /* 51 */
+    IRQ_USB_INT0_INTERRUPT,                   /* 52 */
+    IRQ_USB_INT1_INTERRUPT,                   /* 53 */
+    IRQ_USB_INT2_INTERRUPT,                   /* 54 */
+    IRQ_USB_DMAINT,                           /* 55 */
+    IRQ_MAX,                                  /* 56 */
+} e_isr_t;
+
+
+
+
+/* source is the source to the SIC (the bit number in SIC_ISR).  isr is
+   the function that will be called when the interrupt is active. */
+typedef struct bfin_isr_s {
+#if INTERRUPT_USE_TABLE
+  e_isr_t source;
+  void (*pFunc)(void *arg);
+  void *pArg;
+  int priority; /** not used */
+#else
+  int source;
+  void (*isr)(void *arg);
+  void *_arg;
+  /* the following are for internal use only */
+  uint32_t mask0;
+  uint32_t mask1;
+  uint32_t vector;
+  struct bfin_isr_s *next;
+#endif
+} bfin_isr_t;
+
+/**
+ * This routine registers a new ISR. It will write a new entry to the IVT table
+ * @param isr contains a callback function and source
+ * @return rtems status code
+ */
+rtems_status_code bfin_interrupt_register(bfin_isr_t *isr);
+
+/**
+ * This function unregisters a registered interrupt handler.
+ * @param isr
+ */
+rtems_status_code bfin_interrupt_unregister(bfin_isr_t *isr);
+
+/**
+ * blackfin interrupt initialization routine. It initializes the bfin ISR
+ * dispatcher. It will also create SIC CEC map which will be used for
+ * identifying the ISR.
+ */
+void bfin_interrupt_init(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BFIN_INTERRUPT_H_ */
+
Index: c/src/lib/libcpu/bfin/configure.ac
===================================================================
--- c/src/lib/libcpu/bfin/configure.ac	(revision 5eb50f38e943e831f528d68eb0d09910cf2548ae)
+++ c/src/lib/libcpu/bfin/configure.ac	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
@@ -25,4 +25,8 @@
 AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")
 
+# AM_CONDITIONAL(shared, test "$RTEMS_CPU_MODEL" = "bf52x")
+AM_CONDITIONAL(bf52x, test "$RTEMS_CPU_MODEL" = "bf52x")
+
+
 RTEMS_AMPOLISH3
 
Index: c/src/lib/libcpu/bfin/include/sicRegs.h
===================================================================
--- c/src/lib/libcpu/bfin/include/sicRegs.h	(revision 5eb50f38e943e831f528d68eb0d09910cf2548ae)
+++ c/src/lib/libcpu/bfin/include/sicRegs.h	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
@@ -17,6 +17,12 @@
 
 #define SIC_IMASK                (SIC_BASE_ADDRESS + 0x000c)
+#define SIC_IMASK_PITCH          (0x40)
+
+#define SIC_ISR                  (SIC_BASE_ADDRESS + 0x0020)
+#define SIC_ISR_PITCH            (0x40)
+
 #define SIC_IAR_BASE_ADDRESS     (SIC_BASE_ADDRESS + 0x0010)
 #define SIC_IAR_PITCH                                   0x04
+
 #define SIC_IAR0                 (SIC_BASE_ADDRESS + 0x0010)
 #if SIC_IAR_COUNT > 1
@@ -29,5 +35,5 @@
 #define SIC_IAR3                 (SIC_BASE_ADDRESS + 0x001c)
 #endif
-#define SIC_ISR                  (SIC_BASE_ADDRESS + 0x0020)
+
 #define SIC_IWR                  (SIC_BASE_ADDRESS + 0x0024)
 
Index: c/src/lib/libcpu/bfin/preinstall.am
===================================================================
--- c/src/lib/libcpu/bfin/preinstall.am	(revision 5eb50f38e943e831f528d68eb0d09910cf2548ae)
+++ c/src/lib/libcpu/bfin/preinstall.am	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
@@ -14,4 +14,14 @@
 CLEANFILES = $(PREINSTALL_FILES)
 
+$(PROJECT_INCLUDE)/$(dirstamp):
+	@$(MKDIR_P) $(PROJECT_INCLUDE)
+	@: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+$(PROJECT_INCLUDE)/bsp/$(dirstamp):
+	@$(MKDIR_P) $(PROJECT_INCLUDE)/bsp
+	@: > $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+
 $(PROJECT_INCLUDE)/libcpu/$(dirstamp):
 	@$(MKDIR_P) $(PROJECT_INCLUDE)/libcpu
@@ -19,4 +29,13 @@
 PREINSTALL_DIRS += $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
 
+if bf52x
+$(PROJECT_INCLUDE)/bf52x.h: bf52x/include/bf52x.h $(PROJECT_INCLUDE)/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bf52x.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bf52x.h
+
+$(PROJECT_INCLUDE)/bsp/interrupt.h: bf52x/interrupt/interrupt.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/interrupt.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/interrupt.h
+endif
 $(PROJECT_INCLUDE)/libcpu/bf533.h: include/bf533.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/bf533.h
@@ -103,8 +122,10 @@
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/mmu.h
 
+if bf52x
+else
 $(PROJECT_INCLUDE)/libcpu/interrupt.h: interrupt/interrupt.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/interrupt.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/interrupt.h
-
+endif
 $(PROJECT_INCLUDE)/libcpu/uart.h: serial/uart.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/uart.h
Index: c/src/lib/libcpu/bfin/serial/uart.c
===================================================================
--- c/src/lib/libcpu/bfin/serial/uart.c	(revision 5eb50f38e943e831f528d68eb0d09910cf2548ae)
+++ c/src/lib/libcpu/bfin/serial/uart.c	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
@@ -7,4 +7,7 @@
  *  found in the file LICENSE in this distribution or at
  *  http://www.rtems.com/license/LICENSE.
+ *
+ *  Modified:
+ *  $ $Author$ Added interrupt support and DMA support
  *
  *  $Id$
@@ -19,6 +22,6 @@
 
 #include <libcpu/uartRegs.h>
+#include <libcpu/dmaRegs.h>
 #include "uart.h"
-
 
 /* flags */
@@ -29,43 +32,14 @@
 
 
-static void initializeHardware(int minor) {
-  uint16_t divisor;
-  char *base;
-  uint16_t r;
-
-  base = uartsConfig->channels[minor].base_address;
-
-  *(uint16_t volatile *) (base + UART_IER_OFFSET) = 0;
-
-  if (uartsConfig->channels[minor].force_baud)
-    divisor = (uint16_t) (uartsConfig->freq /
-                          (uartsConfig->channels[minor].force_baud * 16));
-  else
-    divisor = (uint16_t) (uartsConfig->freq / (9600 * 16));
-  *(uint16_t volatile *) (base + UART_LCR_OFFSET) = UART_LCR_DLAB;
-  *(uint16_t volatile *) (base + UART_DLL_OFFSET) = (divisor & 0xff);
-  *(uint16_t volatile *) (base + UART_DLH_OFFSET) = ((divisor >> 8) & 0xff);
-
-  *(uint16_t volatile *) (base + UART_LCR_OFFSET) = UART_LCR_WLS_8;
-
-  *(uint16_t volatile *) (base + UART_GCTL_OFFSET) = UART_GCTL_UCEN;
-
-  r = *(uint16_t volatile *) (base + UART_LSR_OFFSET);
-  r = *(uint16_t volatile *) (base + UART_RBR_OFFSET);
-  r = *(uint16_t volatile *) (base + UART_IIR_OFFSET);
-
-  return;
-}
-
 static int pollRead(int minor) {
   int c;
-  char *base;
-
-  base = uartsConfig->channels[minor].base_address;
+  uint32_t base;
+
+  base = uartsConfig->channels[minor].uart_baseAddress;
 
   /* check to see if driver is using interrupts so this call will be
      harmless (though non-functional) in case some debug code tries to
      use it */
-  if (!uartsConfig->channels[minor].use_interrupts &&
+  if (!uartsConfig->channels[minor].uart_useInterrupts &&
       *((uint16_t volatile *) (base + UART_LSR_OFFSET)) & UART_LSR_DR)
     c = *((uint16_t volatile *) (base + UART_RBR_OFFSET));
@@ -76,5 +50,5 @@
 }
 
-char bfin_uart_poll_read(int minor) {
+char bfin_uart_poll_read(rtems_device_minor_number minor) {
   int c;
 
@@ -87,7 +61,7 @@
 
 void bfin_uart_poll_write(int minor, char c) {
-  char *base;
-
-  base = uartsConfig->channels[minor].base_address;
+  uint32_t base;
+
+  base = uartsConfig->channels[minor].uart_baseAddress;
 
   while (!(*((uint16_t volatile *) (base + UART_LSR_OFFSET)) & UART_LSR_THRE))
@@ -158,42 +132,84 @@
 }
 
-static void enableInterrupts(int minor) {
-  char *base;
-
-  base = uartsConfig->channels[minor].base_address;
-
-  *(uint16_t volatile *) (base + UART_IER_OFFSET) = UART_IER_ETBEI |
-                                                    UART_IER_ERBFI;
-}
-
-static void disableAllInterrupts(void) {
-  int i;
-  char *base;
-
-  for (i = 0; i < uartsConfig->num_channels; i++) {
-    base = uartsConfig->channels[i].base_address;
-    *(uint16_t volatile *) (base + UART_IER_OFFSET) = 0;
-  }
-}
-
-static ssize_t interruptWrite(int minor, const char *buf, size_t len) {
-  char *base;
-
-  base = uartsConfig->channels[minor].base_address;
-
-  uartsConfig->channels[minor].flags |= BFIN_UART_XMIT_BUSY;
-  *(uint16_t volatile *) (base + UART_THR_OFFSET) = *buf;
-
-  /* one byte written */
-  return 1;
-}
-
+
+/**
+ * Routine to initialize the hardware. It initialize the DMA,
+ * interrupt if required.
+ * @param channel channel information
+ */
+static void initializeHardware(bfin_uart_channel_t *channel) {
+  uint16_t divisor        = 0;
+  uint32_t base           = 0;
+  uint32_t tx_dma_base    = 0;
+
+  if ( NULL == channel ) {
+    return;
+  }
+
+  base        = channel->uart_baseAddress;
+  tx_dma_base = channel->uart_txDmaBaseAddress;
+  /**
+   * RX based DMA and interrupt is not supported yet
+   * uint32_t tx_dma_base    = 0;
+   *
+   * rx_dma_base = channel->uart_rxDmaBaseAddress;
+   */
+
+
+  *(uint16_t volatile *) (base + UART_IER_OFFSET) = 0;
+
+  if ( 0 != channel->uart_baud) {
+    divisor = (uint16_t) (uartsConfig->freq /
+        (channel->uart_baud * 16));
+  } else {
+    divisor = (uint16_t) (uartsConfig->freq / (9600 * 16));
+  }
+
+  *(uint16_t volatile *) (base + UART_LCR_OFFSET) = UART_LCR_DLAB;
+  *(uint16_t volatile *) (base + UART_DLL_OFFSET) = (divisor & 0xff);
+  *(uint16_t volatile *) (base + UART_DLH_OFFSET) = ((divisor >> 8) & 0xff);
+
+  *(uint16_t volatile *) (base + UART_LCR_OFFSET) = UART_LCR_WLS_8;
+
+  *(uint16_t volatile *) (base + UART_GCTL_OFFSET) = UART_GCTL_UCEN;
+
+  /**
+   * To clear previous status
+   * divisor is a temp variable here
+   */
+  divisor = *(uint16_t volatile *) (base + UART_LSR_OFFSET);
+  divisor = *(uint16_t volatile *) (base + UART_RBR_OFFSET);
+  divisor = *(uint16_t volatile *) (base + UART_IIR_OFFSET);
+
+  if ( channel->uart_useDma ) {
+    *(uint16_t  volatile *)(tx_dma_base + DMA_CONFIG_OFFSET) = 0;
+    *(uint16_t  volatile *)(tx_dma_base + DMA_CONFIG_OFFSET) = DMA_CONFIG_DI_EN
+        | DMA_CONFIG_SYNC ;
+    *(uint16_t  volatile *)(tx_dma_base + DMA_IRQ_STATUS_OFFSET) |=
+        DMA_IRQ_STATUS_DMA_DONE | DMA_IRQ_STATUS_DMA_ERR;
+
+  } else {
+    /**
+    * We use polling or interrupts only sending one char at a time :(
+    */
+  }
+
+  return;
+}
+
+
+/**
+ * Set the UART attributes.
+ * @param minor
+ * @param termios
+ * @return
+ */
 static int setAttributes(int minor, const struct termios *termios) {
-  char *base;
+  uint32_t base;
   int baud;
   uint16_t divisor;
   uint16_t lcr;
 
-  base = uartsConfig->channels[minor].base_address;
+  base = uartsConfig->channels[minor].uart_baseAddress;
   switch (termios->c_cflag & CBAUD) {
   case B0:
@@ -261,6 +277,6 @@
     break;
   }
-  if (baud > 0 && uartsConfig->channels[minor].force_baud)
-    baud = uartsConfig->channels[minor].force_baud;
+  if (baud > 0 && uartsConfig->channels[minor].uart_baud)
+    baud = uartsConfig->channels[minor].uart_baud;
   switch (termios->c_cflag & CSIZE) {
   case CS5:
@@ -283,6 +299,6 @@
     break;
   case PARENB | PARODD:
-    lcr |= UART_LCR_PEN;
-    break;
+  lcr |= UART_LCR_PEN;
+  break;
   default:
     break;
@@ -302,55 +318,308 @@
 }
 
-void bfin_uart_isr(int source) {
-  int i;
-  char *base;
-  uint16_t uartStat;
-  char c;
-  uint8_t uartLSR;
-
-  /* Just use one ISR and check for all UART interrupt sources in it.
-     This is less efficient than making use of the vector to narrow down
-     the things we need to check, but not all Blackfins separate the
-     UART interrupt sources in the same ways.  This way we don't have
-     to make this code dependent on the type of Blackfin.  */
-  for (i = 0; i < uartsConfig->num_channels; i++) {
-    if (uartsConfig->channels[i].use_interrupts) {
-      base = uartsConfig->channels[i].base_address;
-      uartStat = *(uint16_t volatile *) (base + UART_IIR_OFFSET);
-      if ((uartStat & UART_IIR_NINT) == 0) {
-        switch (uartStat & UART_IIR_STATUS_MASK) {
-        case UART_IIR_STATUS_THRE:
-          if (uartsConfig->channels[i].termios &&
-              (uartsConfig->channels[i].flags & BFIN_UART_XMIT_BUSY)) {
-            uartsConfig->channels[i].flags &= ~BFIN_UART_XMIT_BUSY;
-            rtems_termios_dequeue_characters(uartsConfig->channels[i].termios,
-                                             1);
-          }
-          break;
-        case UART_IIR_STATUS_RDR:
-          c = *(uint16_t volatile *) (base + UART_RBR_OFFSET);
-          if (uartsConfig->channels[i].termios)
-            rtems_termios_enqueue_raw_characters(
-                uartsConfig->channels[i].termios, &c, 1);
-          break;
-        case UART_IIR_STATUS_LS:
-          uartLSR = *(uint16_t volatile *) (base + UART_LSR_OFFSET);
-          /* break, framing error, parity error, or overrun error
-             has been detected */
-          break;
-        default:
-          break;
-        }
-      }
-    }
-  }
-}
-
+/**
+ * Interrupt based uart tx routine. The routine writes one character at a time.
+ *
+ * @param minor Minor number to indicate uart number
+ * @param buf Character buffer which stores characters to be transmitted.
+ * @param len Length of buffer to be transmitted.
+ * @return
+ */
+static ssize_t uart_interruptWrite(int minor, const char *buf, size_t len) {
+  uint32_t              base      = 0;
+  bfin_uart_channel_t*  channel   = NULL;
+  rtems_interrupt_level isrLevel;
+
+  /**
+   * Sanity Check
+   */
+  if (NULL == buf || NULL == channel || NULL == uartsConfig || minor < 0) {
+    return 0;
+  }
+
+  channel = &(uartsConfig->channels[minor]);
+
+  if ( NULL == channel || channel->flags &  BFIN_UART_XMIT_BUSY ) {
+    return 0;
+  }
+
+  rtems_interrupt_disable(isrLevel);
+
+  base = channel->uart_baseAddress;
+
+  channel->flags |= BFIN_UART_XMIT_BUSY;
+  channel->length = 1;
+  *(uint16_t volatile *) (base + UART_THR_OFFSET) = *buf;
+  *(uint16_t volatile *) (base + UART_IER_OFFSET) = UART_IER_ETBEI;
+
+  rtems_interrupt_enable(isrLevel);
+
+  return 0;
+}
+
+/**
+* This function implements RX ISR
+*/
+void bfinUart_rxIsr(void *_arg)
+{
+  /**
+   * TODO: UART RX ISR implementation.
+   */
+
+}
+
+
+/**
+ * This function implements TX ISR. The function gets called when the TX FIFO is
+ * empty. It clears the interrupt and dequeues the character. It only tx one
+ * character at a time.
+ *
+ * TODO: error handling.
+ * @param _arg gets the channel information.
+ */
+void bfinUart_txIsr(void *_arg) {
+  bfin_uart_channel_t*  channel = NULL;
+  uint32_t              base    = 0;
+
+  /**
+   * Sanity check
+   */
+  if (NULL == _arg) {
+    /** It should never be NULL */
+    return;
+  }
+
+  channel = (bfin_uart_channel_t *) _arg;
+
+  base = channel->uart_baseAddress;
+
+  *(uint16_t volatile *) (base + UART_IER_OFFSET) &= ~UART_IER_ETBEI;
+  channel->flags &= ~BFIN_UART_XMIT_BUSY;
+
+  rtems_termios_dequeue_characters(channel->termios, channel->length);
+
+  return;
+}
+
+
+
+
+/**
+ * interrupt based DMA write Routine. It configure the DMA to write len bytes.
+ * The DMA supports 64K data only.
+ *
+ * @param minor Identification number of the UART.
+ * @param buf Character buffer pointer
+ * @param len length of data items to be written
+ * @return data already written
+ */
+static ssize_t uart_DmaWrite(int minor, const char *buf, size_t len) {
+  uint32_t              base        = 0;
+  bfin_uart_channel_t*  channel     = NULL;
+  uint32_t              tx_dma_base = 0;
+  rtems_interrupt_level isrLevel;
+
+  /**
+   * Sanity Check
+   */
+  if ( NULL == buf || 0 > minor || NULL == uartsConfig ) {
+    return 0;
+  }
+
+  channel = &(uartsConfig->channels[minor]);
+
+  /**
+   * Sanity Check and check for transmit busy.
+   */
+  if ( NULL == channel || BFIN_UART_XMIT_BUSY & channel->flags ) {
+    return 0;
+  }
+
+  rtems_interrupt_disable(isrLevel);
+
+  base        = channel->uart_baseAddress;
+  tx_dma_base = channel->uart_txDmaBaseAddress;
+
+  channel->flags |= BFIN_UART_XMIT_BUSY;
+  channel->length = len;
+
+  *(uint16_t volatile *) (tx_dma_base + DMA_CONFIG_OFFSET) &= ~DMA_CONFIG_DMAEN;
+  *(uint32_t volatile *) (tx_dma_base + DMA_START_ADDR_OFFSET) = (uint32_t)buf;
+  *(uint16_t volatile *) (tx_dma_base + DMA_X_COUNT_OFFSET) = channel->length;
+  *(uint16_t volatile *) (tx_dma_base + DMA_X_MODIFY_OFFSET) = 1;
+  *(uint16_t volatile *) (tx_dma_base + DMA_CONFIG_OFFSET) |= DMA_CONFIG_DMAEN;
+  *(uint16_t volatile *) (base + UART_IER_OFFSET) = UART_IER_ETBEI;
+
+  rtems_interrupt_enable(isrLevel);
+
+  return 0;
+}
+
+
+/**
+ * RX DMA ISR.
+ * The polling route is used for receiving the characters. This is a place
+ * holder for future implementation.
+ * @param _arg
+ */
+void bfinUart_rxDmaIsr(void *_arg) {
+/**
+ * TODO: Implementation of RX DMA
+ */
+}
+
+/**
+ * This function implements TX dma ISR. It clears the IRQ and dequeues a char
+ * The channel argument will have the base address. Since there are two uart
+ * and both the uarts can use the same tx dma isr.
+ *
+ * TODO: 1. Error checking 2. sending correct length ie after looking at the
+ * number of elements the uart transmitted.
+ *
+ * @param _arg argument passed to the interrupt handler. It contains the
+ * channel argument.
+ */
+void bfinUart_txDmaIsr(void *_arg) {
+  bfin_uart_channel_t*  channel     = NULL;
+  uint32_t              tx_dma_base = 0;
+
+  /**
+   * Sanity check
+   */
+  if (NULL == _arg) {
+    /** It should never be NULL */
+    return;
+  }
+
+  channel = (bfin_uart_channel_t *) _arg;
+
+  tx_dma_base = channel->uart_txDmaBaseAddress;
+
+  if ((*(uint16_t volatile *) (tx_dma_base + DMA_IRQ_STATUS_OFFSET)
+      & DMA_IRQ_STATUS_DMA_DONE)) {
+
+    *(uint16_t volatile *) (tx_dma_base + DMA_IRQ_STATUS_OFFSET)
+        		    |= DMA_IRQ_STATUS_DMA_DONE | DMA_IRQ_STATUS_DMA_ERR;
+    channel->flags &= ~BFIN_UART_XMIT_BUSY;
+    rtems_termios_dequeue_characters(channel->termios, channel->length);
+  } else {
+    /* UART DMA did not generate interrupt.
+     * This routine must not be called.
+     */
+  }
+
+  return;
+}
+
+/**
+ * Function called during exit
+ */
+void uart_exit(void)
+{
+  /**
+   * TODO: Flushing of quques
+   */
+
+}
+
+/**
+ * Opens the device in different modes. The supported modes are
+ * 1. Polling
+ * 2. Interrupt
+ * 3. DMA
+ * At exit the uart_Exit function will be called to flush the device.
+ *
+ * @param major Major number of the device
+ * @param minor Minor number of the device
+ * @param arg
+ * @return
+ */
+rtems_device_driver bfin_uart_open(rtems_device_major_number major,
+    rtems_device_minor_number minor, void *arg) {
+  rtems_status_code             sc    = RTEMS_NOT_DEFINED;;
+  rtems_libio_open_close_args_t *args = NULL;
+
+  /**
+   * Callback function for polling
+   */
+  static const rtems_termios_callbacks pollCallbacks = {
+      NULL,                        /* firstOpen */
+      NULL,                        /* lastClose */
+      pollRead,                    /* pollRead */
+      pollWrite,                   /* write */
+      setAttributes,               /* setAttributes */
+      NULL,                        /* stopRemoteTx */
+      NULL,                        /* startRemoteTx */
+      TERMIOS_POLLED               /* outputUsesInterrupts */
+  };
+
+  /**
+   * Callback function for interrupt based transfers without DMA.
+   * We use interrupts for writing only. For reading we use polling.
+   */
+  static const rtems_termios_callbacks interruptCallbacks = {
+      NULL,                        /* firstOpen */
+      NULL,                        /* lastClose */
+      pollRead,                    /* pollRead */
+      uart_interruptWrite,              /* write */
+      setAttributes,               /* setAttributes */
+      NULL,                        /* stopRemoteTx */
+      NULL,                        /* startRemoteTx */
+      TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
+  };
+
+  /**
+   * Callback function for interrupt based DMA transfers.
+   * We use interrupts for writing only. For reading we use polling.
+   */
+  static const rtems_termios_callbacks interruptDmaCallbacks = {
+      NULL,                        /* firstOpen */
+      NULL,                        /* lastClose */
+      NULL,                        /* pollRead */
+      uart_DmaWrite,              /* write */
+      setAttributes,               /* setAttributes */
+      NULL,                        /* stopRemoteTx */
+      NULL,                        /* startRemoteTx */
+      TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
+  };
+
+
+  if ( NULL == uartsConfig || 0 > minor || minor >= uartsConfig->num_channels) {
+    return RTEMS_INVALID_NUMBER;
+  }
+
+  /**
+   * Opens device for handling uart send request either by
+   * 1. interrupt with DMA
+   * 2. interrupt based
+   * 3. Polling
+   */
+  if ( uartsConfig->channels[minor].uart_useDma ) {
+    sc = rtems_termios_open(major, minor, arg, &interruptDmaCallbacks);
+  } else {
+    sc = rtems_termios_open(major, minor, arg,
+        uartsConfig->channels[minor].uart_useInterrupts ?
+            &interruptCallbacks : &pollCallbacks);
+  }
+
+  args = arg;
+  uartsConfig->channels[minor].termios = args->iop->data1;
+
+  atexit(uart_exit);
+
+  return sc;
+}
+
+
+/**
+* Uart initialization function.
+* @param major major number of the device
+* @param config configuration parameters
+* @return rtems status code
+*/
 rtems_status_code bfin_uart_initialize(rtems_device_major_number major,
-                                       bfin_uart_config_t *config) {
-  rtems_status_code status;
-  int i;
-
-  status = RTEMS_SUCCESSFUL;
+    bfin_uart_config_t *config) {
+  rtems_status_code sc = RTEMS_NOT_DEFINED;
+  int               i  = 0;
 
   rtems_termios_initialize();
@@ -359,56 +628,15 @@
    *  Register Device Names
    */
-
   uartsConfig = config;
   for (i = 0; i < config->num_channels; i++) {
     config->channels[i].termios = NULL;
     config->channels[i].flags = 0;
-    initializeHardware(i);
-    status = rtems_io_register_name(config->channels[i].name, major, i);
-  }
-
-   return RTEMS_SUCCESSFUL;
-}
-
-rtems_device_driver bfin_uart_open(rtems_device_major_number major,
-                                   rtems_device_minor_number minor,
-                                   void *arg) {
-  rtems_status_code sc;
-  rtems_libio_open_close_args_t *args;
-  static const rtems_termios_callbacks pollCallbacks = {
-    NULL,                        /* firstOpen */
-    NULL,                        /* lastClose */
-    pollRead,                    /* pollRead */
-    pollWrite,                   /* write */
-    setAttributes,               /* setAttributes */
-    NULL,                        /* stopRemoteTx */
-    NULL,                        /* startRemoteTx */
-    TERMIOS_POLLED               /* outputUsesInterrupts */
-  };
-  static const rtems_termios_callbacks interruptCallbacks = {
-    NULL,                        /* firstOpen */
-    NULL,                        /* lastClose */
-    NULL,                        /* pollRead */
-    interruptWrite,              /* write */
-    setAttributes,               /* setAttributes */
-    NULL,                        /* stopRemoteTx */
-    NULL,                        /* startRemoteTx */
-    TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
-  };
-
-  if (uartsConfig == NULL || minor < 0 || minor >= uartsConfig->num_channels)
-    return RTEMS_INVALID_NUMBER;
-
-  sc = rtems_termios_open(major, minor, arg,
-                          uartsConfig->channels[minor].use_interrupts ?
-                          &interruptCallbacks : &pollCallbacks);
-  args = arg;
-  uartsConfig->channels[minor].termios = args->iop->data1;
-
-  if (uartsConfig->channels[minor].use_interrupts)
-    enableInterrupts(minor);
-  atexit(disableAllInterrupts);
+    initializeHardware(&(config->channels[i]));
+    sc = rtems_io_register_name(config->channels[i].name, major, i);
+    if (RTEMS_SUCCESSFUL != sc) {
+      return sc;
+    }
+  }
 
   return sc;
 }
-
Index: c/src/lib/libcpu/bfin/serial/uart.h
===================================================================
--- c/src/lib/libcpu/bfin/serial/uart.h	(revision 5eb50f38e943e831f528d68eb0d09910cf2548ae)
+++ c/src/lib/libcpu/bfin/serial/uart.h	(revision cb4c90b227661280d5da48ecae0aa62890b55494)
@@ -9,9 +9,13 @@
  *  http://www.rtems.com/license/LICENSE.
  *
+ *  Modified:
+ *  $Author$ Added interrupt support and DMA support
+ *
  *  $Id$
  */
 
-#ifndef _uart_h_
-#define _uart_h_
+
+#ifndef _UART_H_
+#define _UART_H_
 
 
@@ -20,14 +24,20 @@
 #endif
 
+/** bfin_uart_channel object
+ */
+typedef struct {
+  const char        *name;                 /** Holds name of the device */
+  uint32_t          uart_baseAddress;           /** UART base address */
+  uint32_t          uart_rxDmaBaseAddress;      /** RX DMA base address */
+  uint32_t          uart_txDmaBaseAddress;      /** TX DMA base address */
+  bool              uart_useInterrupts;         /** are interrupts used */
+  bool              uart_useDma;                /** is dma used */
+  int               uart_baud;                  /** baud rate, 0 for default */
 
-typedef struct {
-  const char *name;
-  void *base_address;
-  bool  use_interrupts;
-  int force_baud;
-  /* the following are for internal use */
-  void *termios;
-  uint8_t volatile flags;
+  void              *termios;                   /** termios associated */
+  uint8_t volatile  flags;                      /** flags for internal use */
+  uint16_t          length;                     /** length for internal use */
 } bfin_uart_channel_t;
+
 
 typedef struct {
@@ -37,17 +47,88 @@
 } bfin_uart_config_t;
 
+/**
+ * @param base_address defines the UART base address
+ * @param source defines the source that caused the interrupt. This argument
+ * will help us in identifying if Rx or TX caused the interrupt.
+ */
+typedef struct {
+  uint32_t base_address;
+  int source;
+} bfin_uart_arg_t;
 
-char bfin_uart_poll_read(int minor);
+
+
+char bfin_uart_poll_read(rtems_device_minor_number minor);
 
 void bfin_uart_poll_write(int minor, char c);
 
+
+/**
+* Uart initialization function.
+* @param major major number of the device
+* @param config configuration parameters
+* @return rtems status code
+*/
 rtems_status_code bfin_uart_initialize(rtems_device_major_number major,
-                                       bfin_uart_config_t *config);
+    bfin_uart_config_t *config);
 
+
+
+/**
+ * Opens the device in different modes. The supported modes are
+ * 1. Polling
+ * 2. Interrupt
+ * 3. DMA
+ * At exit the uart_Exit function will be called to flush the device.
+ *
+ * @param major Major number of the device
+ * @param minor Minor number of the device
+ * @param arg
+ * @return
+ */
 rtems_device_driver bfin_uart_open(rtems_device_major_number major,
-                                   rtems_device_minor_number minor,
-                                   void *arg);
+    rtems_device_minor_number minor, void *arg);
 
-void bfin_uart_isr(int source);
+
+
+/**
+ * This function implements TX dma ISR. It clears the IRQ and dequeues a char
+ * The channel argument will have the base address. Since there are two uart
+ * and both the uarts can use the same tx dma isr.
+ *
+ * TODO: 1. Error checking 2. sending correct length ie after looking at the
+ * number of elements the uart transmitted.
+ *
+ * @param _arg argument passed to the interrupt handler. It contains the
+ * channel argument.
+ */
+void bfinUart_txDmaIsr(void *_arg);
+
+
+
+/**
+ * RX DMA ISR.
+ * The polling route is used for receiving the characters. This is a place
+ * holder for future implementation.
+ * @param _arg
+ */
+void bfinUart_rxDmaIsr(void *_arg);
+
+
+/**
+ * This function implements TX ISR. The function gets called when the TX FIFO is
+ * empty. It clears the interrupt and dequeues the character. It only tx one
+ * character at a time.
+ *
+ * TODO: error handling.
+ * @param _arg gets the channel information.
+ */
+void bfinUart_txIsr(void *_arg);
+
+
+/**
+* This function implements RX ISR
+*/
+void bfinUart_rxIsr(void *_arg);
 
 
@@ -56,4 +137,4 @@
 #endif
 
-#endif /* _uart_h_ */
+#endif /* _UART_H_ */
 
