Index: c/src/lib/libbsp/sparc/ChangeLog
===================================================================
--- c/src/lib/libbsp/sparc/ChangeLog	(revision 5b42368a5c59ce3b5f6312cc7f2fc289dff4ed80)
+++ c/src/lib/libbsp/sparc/ChangeLog	(revision 0da39987060f7c4432febe617b89261a144252b7)
@@ -1,2 +1,8 @@
+2007-11-30	Daniel Hellstrom <daniel@gaisler.com>
+
+	* shared/include/grspw.h, shared/spw/grspw.c: GRSPW SpaceWire Driver.
+	Fixes typecast to volatile integer instead of to integer. Added
+	scanning for GRSPW2 Core, The GRSPW2 core is run in legacy mode.
+
 2007-11-30	Daniel Hellstrom <daniel@gaisler.com>
 
Index: c/src/lib/libbsp/sparc/shared/include/grspw.h
===================================================================
--- c/src/lib/libbsp/sparc/shared/include/grspw.h	(revision 5b42368a5c59ce3b5f6312cc7f2fc289dff4ed80)
+++ c/src/lib/libbsp/sparc/shared/include/grspw.h	(revision 0da39987060f7c4432febe617b89261a144252b7)
@@ -55,5 +55,5 @@
    unsigned int nodeaddr;
    unsigned int destkey;
-   unsigned int clkdiv;
+   unsigned int clkdiv; /* Note: contain both CLKDIVSTART and CLKDIVRUN, but IOCTL_SET_CLKDIV* commands are split into two */
    unsigned int rxmaxlen;
    unsigned int timer;
@@ -77,4 +77,6 @@
    unsigned int is_rxunaligned;
    unsigned int is_rmapcrc;
+   
+   unsigned int nodemask;
 } spw_config;
 
@@ -104,4 +106,6 @@
 #define SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL 31
 #define SPACEWIRE_IOCTRL_SET_COREFREQ        32
+#define SPACEWIRE_IOCTRL_SET_CLKDIVSTART     33
+#define SPACEWIRE_IOCTRL_SET_NODEMASK        34
 
 #define SPACEWIRE_IOCTRL_START               64
Index: c/src/lib/libbsp/sparc/shared/spw/grspw.c
===================================================================
--- c/src/lib/libbsp/sparc/shared/spw/grspw.c	(revision 5b42368a5c59ce3b5f6312cc7f2fc289dff4ed80)
+++ c/src/lib/libbsp/sparc/shared/spw/grspw.c	(revision 0da39987060f7c4432febe617b89261a144252b7)
@@ -11,4 +11,7 @@
  * Changes:
  * 
+ * 2007-09-27, Daniel Hellstrom <daniel@gaisler.com>
+ *  Added basic support for GRSPW2 core.
+ *
  * 2007-07-12, Daniel Hellstrom <daniel@gaisler.com>
  *  Fixed bug in TXBLOCK mode (normally called flush).
@@ -116,4 +119,8 @@
    volatile unsigned int dma0txdesc;
    volatile unsigned int dma0rxdesc;
+   
+   /* For GRSPW core 2 and onwards */
+   volatile unsigned int dma0addr;
+   
 } LEON3_SPACEWIRE_Regs_Map;
 
@@ -166,4 +173,5 @@
    unsigned int irq;
    int minor;
+   int core_ver;
    int open;
    int running;
@@ -189,10 +197,11 @@
 
 static int spw_cores;
+static int spw_cores2;
 static unsigned int sys_freq_khz;
 static GRSPW_DEV *grspw_devs;
 
 #ifdef GRSPW_DONT_BYPASS_CACHE
-#define _SPW_READ(address) (*(unsigned int *)(address))
-#define _MEM_READ(address) (*(unsigned char *)(address))
+#define _SPW_READ(address) (*(volatile unsigned int *)(address))
+#define _MEM_READ(address) (*(volatile unsigned char *)(address))
 #else
 static unsigned int _SPW_READ(void *addr) {
@@ -509,5 +518,5 @@
         int minor;
 
-        for(minor = 0; minor < spw_cores; minor++) {
+        for(minor = 0; minor < spw_cores+spw_cores2; minor++) {
                 if (v == (grspw_devs[minor].irq+0x10) ) {
                         grspw_interrupt(&grspw_devs[minor]);
@@ -602,4 +611,5 @@
         char console_name[20];
 				amba_apb_device dev;
+                                
         SPACEWIRE_DBG2("spacewire driver initialization\n");        
         
@@ -608,8 +618,9 @@
         
         /* Get the number of GRSPW cores */
-        i=0; spw_cores = 0;
+        i=0; spw_cores = 0; spw_cores2 = 0;
 
         /* get number of GRSPW cores */
         spw_cores = amba_get_number_apbslv_devices(amba_bus,VENDOR_GAISLER,GAISLER_SPACEWIRE);
+        spw_cores2 = amba_get_number_apbslv_devices(amba_bus,VENDOR_GAISLER,GAISLER_GRSPW2);
 #if 0
 				if ( spw_cores > SPACEWIRE_MAX_CORENR )
@@ -624,5 +635,5 @@
 #endif
         
-        if ( spw_cores < 1 ){
+        if ( (spw_cores+spw_cores2) < 1 ){
                 /* No GRSPW cores around... */
                 return RTEMS_SUCCESSFUL;
@@ -630,16 +641,23 @@
         
         /* Allocate memory for all spacewire cores */
-        grspw_devs = (GRSPW_DEV *)malloc(spw_cores * sizeof(GRSPW_DEV));
+        grspw_devs = (GRSPW_DEV *)malloc((spw_cores+spw_cores2) * sizeof(GRSPW_DEV));
         
         /* Zero out all memory */
-        memset(grspw_devs,0,spw_cores * sizeof(GRSPW_DEV));
+        memset(grspw_devs,0,(spw_cores+spw_cores2) * sizeof(GRSPW_DEV));
         
         /* loop all found spacewire cores */
         i = 0;
-        for(minor=0; minor<spw_cores; minor++){
+        for(minor=0; minor<(spw_cores+spw_cores2); minor++){
+
+                pDev = &grspw_devs[minor];
+                
                 /* Get device */
-                amba_find_next_apbslv(amba_bus,VENDOR_GAISLER,GAISLER_SPACEWIRE,&dev,minor);
-                
-                pDev = &grspw_devs[minor];
+                if ( spw_cores > minor ) {
+                        amba_find_next_apbslv(amba_bus,VENDOR_GAISLER,GAISLER_SPACEWIRE,&dev,minor);
+                        pDev->core_ver = 1;
+                } else {
+                        amba_find_next_apbslv(amba_bus,VENDOR_GAISLER,GAISLER_GRSPW2,&dev,minor-spw_cores);
+                        pDev->core_ver = 2;
+                }
                 
                 pDev->regs = (LEON3_SPACEWIRE_Regs_Map *)dev.start;
@@ -684,5 +702,5 @@
   
         /*  Register Device Names, /dev/grspw0, /dev/grspw1  ... */
-        for (i = 0; i < spw_cores; i++) {
+        for (i = 0; i < spw_cores+spw_cores2; i++) {
            GRSPW_DEVNAME_NO(console_name,i);
            SPACEWIRE_DBG("registering minor %i as %s\n", i, console_name);
@@ -695,5 +713,5 @@
         /* Initialize Hardware and semaphores*/
         c = 'a';
-        for (i = 0; i < spw_cores; i++) {
+        for (i = 0; i < spw_cores+spw_cores2; i++) {
                 pDev = &grspw_devs[i];
                 rtems_semaphore_create(
@@ -726,5 +744,5 @@
         GRSPW_DEV *pDev;
         SPACEWIRE_DBGC(DBGSPW_IOCALLS, "open [%i,%i]\n", major, minor);
-        if ( minor >= spw_cores ) {
+        if ( minor >= (spw_cores+spw_cores2) ) {
                 SPACEWIRE_DBG("minor %i too big\n", minor);
                 return RTEMS_INVALID_NAME;
@@ -883,5 +901,5 @@
         spw_ioctl_packetsize *ps;
         int status;
-        unsigned int tmp;
+        unsigned int tmp,nodeaddr,nodemask;
         int timeout;
         rtems_device_driver ret;
@@ -897,13 +915,37 @@
                 case SPACEWIRE_IOCTRL_SET_NODEADDR:
                         /*set node address*/
-                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_NODEADDR %i\n", (unsigned int)ioarg->buffer);
+                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_NODEADDR %i\n",(unsigned int)ioarg->buffer);
                         if ((unsigned int)ioarg->buffer > 255) {
                                 return RTEMS_INVALID_NAME;
                         }
-                        SPW_WRITE(&pDev->regs->nodeaddr, (unsigned int)ioarg->buffer);  
-                        if (SPW_READ(&pDev->regs->nodeaddr) != (unsigned int)ioarg->buffer) {
+                        nodeaddr = ((unsigned int)ioarg->buffer) & 0xff;
+                        tmp = SPW_READ(&pDev->regs->nodeaddr);
+                        tmp &= 0xffffff00; /* Remove old address */
+                        tmp |= nodeaddr;
+                        SPW_WRITE(&pDev->regs->nodeaddr, tmp);
+                        if ((SPW_READ(&pDev->regs->nodeaddr)&0xff) != nodeaddr) {
                                 return RTEMS_IO_ERROR;
                         }
-                        pDev->config.nodeaddr = (unsigned int) ioarg->buffer;
+                        pDev->config.nodeaddr = nodeaddr;
+                        break;
+                case SPACEWIRE_IOCTRL_SET_NODEMASK:
+                        /*set node address*/
+                        SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_NODEMASK %i\n",(unsigned int)ioarg->buffer);
+                        if ( pDev->core_ver > 1 ){
+                          if ((unsigned int)ioarg->buffer > 255) {
+                                  return RTEMS_INVALID_NAME;
+                          }
+                          nodemask = ((unsigned int)ioarg->buffer) & 0xff;
+                          tmp = SPW_READ(&pDev->regs->nodeaddr);
+                          tmp &= 0xffff00ff; /* Remove old mask */
+                          tmp |= nodemask<<8;
+                          SPW_WRITE(&pDev->regs->nodeaddr, tmp);
+                          if (((SPW_READ(&pDev->regs->nodeaddr)>>8)&0xff) != nodemask) {
+                                  return RTEMS_IO_ERROR;
+                          }
+                          pDev->config.nodemask = nodemask;
+                        }else{
+                          SPACEWIRE_DBG("SPACEWIRE_IOCTRL_SET_NODEMASK: not implemented in GRSPW1 HW\n");
+                        }
                         break;
                 case SPACEWIRE_IOCTRL_SET_RXBLOCK:
@@ -933,31 +975,56 @@
                                 return RTEMS_INVALID_NAME;
                         }
-                        SPW_WRITE(&pDev->regs->clkdiv, (unsigned int)ioarg->buffer);
-                        if (SPW_READ(&pDev->regs->clkdiv) != (unsigned int)ioarg->buffer) {
+                        tmp = SPW_READ(&pDev->regs->clkdiv);
+                        tmp &= ~0xff; /* Remove old Clockdiv Setting */
+                        tmp |= ((unsigned int)ioarg->buffer) & 0xff; /* add new clockdiv setting */
+                        SPW_WRITE(&pDev->regs->clkdiv, tmp);
+                        if (SPW_READ(&pDev->regs->clkdiv) != tmp) {
                                 return RTEMS_IO_ERROR;
                         }
-                        pDev->config.clkdiv = (unsigned int)ioarg->buffer;
-                        break;
+                        pDev->config.clkdiv = tmp;
+                        break;
+                case SPACEWIRE_IOCTRL_SET_CLKDIVSTART:
+                        SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_CLKDIVSTART %i\n", (unsigned int)ioarg->buffer);
+                        if ((unsigned int)ioarg->buffer > 255) {
+                                return RTEMS_INVALID_NAME;
+                        }
+                        tmp = SPW_READ(&pDev->regs->clkdiv);
+                        tmp &= ~0xff00; /* Remove old Clockdiv Start Setting */
+                        tmp |= (((unsigned int)ioarg->buffer) & 0xff)<<8; /* add new clockdiv start setting */
+                        SPW_WRITE(&pDev->regs->clkdiv, tmp);
+                        if (SPW_READ(&pDev->regs->clkdiv) != tmp) {
+                                return RTEMS_IO_ERROR;
+                        }
+                        pDev->config.clkdiv = tmp;
+                        break;                        
                 case SPACEWIRE_IOCTRL_SET_TIMER:
                         SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_TIMER %i\n", (unsigned int)ioarg->buffer);
-                        if ((unsigned int)ioarg->buffer > 4095) {
-                                return RTEMS_INVALID_NAME;
-                        }
-                        SPW_WRITE(&pDev->regs->timer, (SPW_READ(&pDev->regs->timer) & 0xFFFFF000) | ((unsigned int)ioarg->buffer & 0xFFF));
-                        if ((SPW_READ(&pDev->regs->timer) & 0xFFF) != (unsigned int)ioarg->buffer) {
-                                return RTEMS_IO_ERROR;
-                        }
-                        pDev->config.timer = (unsigned int)ioarg->buffer;
+                        if ( pDev->core_ver <= 1 ) {
+                          if ((unsigned int)ioarg->buffer > 4095) {
+                                  return RTEMS_INVALID_NAME;
+                          }
+                          SPW_WRITE(&pDev->regs->timer, (SPW_READ(&pDev->regs->timer) & 0xFFFFF000) | ((unsigned int)ioarg->buffer & 0xFFF));
+                          if ((SPW_READ(&pDev->regs->timer) & 0xFFF) != (unsigned int)ioarg->buffer) {
+                                  return RTEMS_IO_ERROR;
+                          }
+                          pDev->config.timer = (unsigned int)ioarg->buffer;
+                        }else{
+                          SPACEWIRE_DBG("SPACEWIRE_IOCTRL_SET_TIMER: removed in GRSPW2 HW\n");
+                        }
                         break;
                 case SPACEWIRE_IOCTRL_SET_DISCONNECT:
                         SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_DISCONNECT %i\n", (unsigned int)ioarg->buffer);
-                        if ((unsigned int)ioarg->buffer > 1023) {
-                                return RTEMS_INVALID_NAME;
-                        }
-                        SPW_WRITE(&pDev->regs->timer, (SPW_READ(&pDev->regs->timer) & 0xFFC00FFF) | (((unsigned int)ioarg->buffer & 0x3FF) << 12));
-                        if (((SPW_READ(&pDev->regs->timer) >> 12) & 0x3FF) != (unsigned int)ioarg->buffer) {
-                                return RTEMS_IO_ERROR;
-                        }
-                        pDev->config.disconnect = (unsigned int)ioarg->buffer;
+                        if ( pDev->core_ver <= 1 ) {
+                          if ((unsigned int)ioarg->buffer > 1023) {
+                                  return RTEMS_INVALID_NAME;
+                          }
+                          SPW_WRITE(&pDev->regs->timer, (SPW_READ(&pDev->regs->timer) & 0xFFC00FFF) | (((unsigned int)ioarg->buffer & 0x3FF) << 12));
+                          if (((SPW_READ(&pDev->regs->timer) >> 12) & 0x3FF) != (unsigned int)ioarg->buffer) {
+                                  return RTEMS_IO_ERROR;
+                          }
+                          pDev->config.disconnect = (unsigned int)ioarg->buffer;
+                        }else{
+                          SPACEWIRE_DBG("SPACEWIRE_IOCTRL_SET_DISCONNECT: not implemented for GRSPW2\n");
+                        }
                         break;
                 case SPACEWIRE_IOCTRL_SET_PROMISCUOUS:        
@@ -1106,4 +1173,5 @@
                         SPACEWIRE_DBG2("SPACEWIRE_IOCTRL_GET_CONFIG \n");
                         (*(spw_config *)ioarg->buffer).nodeaddr = pDev->config.nodeaddr;
+                        (*(spw_config *)ioarg->buffer).nodemask = pDev->config.nodemask;
                         (*(spw_config *)ioarg->buffer).destkey = pDev->config.destkey;
                         (*(spw_config *)ioarg->buffer).clkdiv = pDev->config.clkdiv;
@@ -1232,19 +1300,24 @@
                         }
                         
-                        /* Calculate Timer64 & Disconnect */
-                        pDev->config.timer = grspw_calc_timer64(pDev->core_freq_khz);
-                        pDev->config.disconnect = grspw_calc_disconnect(pDev->core_freq_khz);
-                        
-                        /* Set Timer64 & Disconnect Register */
-                        SPW_WRITE(&pDev->regs->timer, 
+                        /* Only GRSPW1 needs the Timer64 and Disconnect values 
+                         * GRSPW2 and onwards doesn't have this register.
+                         */
+                        if ( pDev->core_ver <= 1 ){
+                          /* Calculate Timer64 & Disconnect */
+                          pDev->config.timer = grspw_calc_timer64(pDev->core_freq_khz);
+                          pDev->config.disconnect = grspw_calc_disconnect(pDev->core_freq_khz);
+                          
+                          /* Set Timer64 & Disconnect Register */
+                          SPW_WRITE(&pDev->regs->timer, 
                                  (SPW_READ(&pDev->regs->timer) & 0xFFC00000) |
                                  ((pDev->config.disconnect & 0x3FF)<<12) |
                                  (pDev->config.timer & 0xFFF));
                         
-                        /* Check that the registers were written successfully */
-                        tmp = SPW_READ(&pDev->regs->timer) & 0x003fffff;
-                        if ( ((tmp & 0xFFF) != pDev->config.timer) ||
-                             (((tmp >> 12) & 0x3FF) != pDev->config.disconnect) ) {
-                                return RTEMS_IO_ERROR;
+                          /* Check that the registers were written successfully */
+                          tmp = SPW_READ(&pDev->regs->timer) & 0x003fffff;
+                          if ( ((tmp & 0xFFF) != pDev->config.timer) ||
+                               (((tmp >> 12) & 0x3FF) != pDev->config.disconnect) ) {
+                                  return RTEMS_IO_ERROR;
+                          }
                         }
                         break;
@@ -1358,7 +1431,9 @@
         unsigned int tmp;
         
-        pDev->config.nodeaddr = 0xFF & SPW_READ(&pDev->regs->nodeaddr);
+        tmp = SPW_READ(&pDev->regs->nodeaddr);
+        pDev->config.nodeaddr = 0xFF & tmp;
+        pDev->config.nodemask = 0xFF & (tmp>>8);
         pDev->config.destkey = 0xFF & SPW_READ(&pDev->regs->destkey);
-        pDev->config.clkdiv = 0xFF & SPW_READ(&pDev->regs->clkdiv);
+        pDev->config.clkdiv = 0xFFFF & SPW_READ(&pDev->regs->clkdiv);
         
         tmp = SPW_CTRL_READ(pDev);
@@ -1372,7 +1447,12 @@
         pDev->config.linkstart = 1 & (tmp >> 1);
         
-        tmp = SPW_READ(&pDev->regs->timer);
-        pDev->config.timer = 0xFFF & tmp;
-        pDev->config.disconnect = 0x3FF & (tmp >> 12);
+        if ( pDev->core_ver <= 1 ){
+          tmp = SPW_READ(&pDev->regs->timer);
+          pDev->config.timer = 0xFFF & tmp;
+          pDev->config.disconnect = 0x3FF & (tmp >> 12);
+        }else{
+          pDev->config.timer = 0;
+          pDev->config.disconnect = 0;
+        }
         
         return;
