To make CL CS8900a work in 8-bit mode

Sergei Gavrikov w3sg@SoftHome.net
Thu Aug 10 22:23:00 GMT 2006


I finished two eCos ports for new targets: Olimex LPC-E2294 development
board and Olimex LPC-H2294 header board. Olimex LPC-E2294 does have CL
CS8900A ethernet chip had been wired in a 8-bit mode by Olimex designers.

Only with this minimal patch I get an ethernet support for the
LPC-E2294. RedBoot for this board does an upload via tftp just pretty
well in that 8-bit mode. If this patch will be committed, I send my
ports for these boards. It's very important to fulfil all accesses to
CL CS8900A registers via CS_IN(), CS_OUT() macros.

Sergei
-------------- next part --------------
diff -ur devs/eth/cl/cs8900a.orig/current/ChangeLog devs/eth/cl/cs8900a/current/ChangeLog
--- devs/eth/cl/cs8900a.orig/current/ChangeLog	2005-11-23 23:26:50.000000000 +0200
+++ devs/eth/cl/cs8900a/current/ChangeLog	2006-08-11 00:52:49.000000000 +0300
@@ -1,3 +1,11 @@
+2006-02-11  Sergei Gavrikov <sg@sgs.gomel.by>
+	* cdl/cl_cs8900a_eth_drivers.cdl: Added
+	CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT option.
+	* include/cs8900a.h:
+	* src/if_cs8900a.c: Added support to make CL CS8900A work in 8-bit
+	mode. All calls of HAL_READ_UINT16, HAL_WRITE_UINT16 replaced by
+	CS_IN, CS_OUT calls.
+
 2005-11-10  Laurent Gonzalez <laurent.gonzalez@trango-systems.com>
 
 	* include/cs8900a.h:
diff -ur devs/eth/cl/cs8900a.orig/current/cdl/cl_cs8900a_eth_drivers.cdl devs/eth/cl/cs8900a/current/cdl/cl_cs8900a_eth_drivers.cdl
--- devs/eth/cl/cs8900a.orig/current/cdl/cl_cs8900a_eth_drivers.cdl	2005-05-08 12:29:39.000000000 +0300
+++ devs/eth/cl/cs8900a/current/cdl/cl_cs8900a_eth_drivers.cdl	2006-08-10 23:57:45.000000000 +0300
@@ -80,6 +80,23 @@
             carefully chosen decision, hence this option."
     }
 
+    cdl_option CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT {
+        display "8-bit data bus"
+        flavor        bool
+        requires      !CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
+        requires      !CYGSEM_DEVS_ETH_CL_CS8900A_WRITE_EEPROM
+        requires      CYGSEM_DEVS_ETH_CL_CS8900A_NOINTS
+        default_value 0
+        description   "
+            The CS8900A can been use in 8-bit mode. From AN181 from
+            Cirrus Logic... Unsupported functions in 8-bit mode:
+            Interrupts are not supported. Polled mode must be used;
+            The DMA engine only uses 16 bit memory access and does not
+            support 8 bit transfers; The packet page pointer has an
+            auto increment feature that cannot be used in 8-bit mode;
+            An EEPROM is not supported."
+    }
+
     cdl_option CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED {
 	display "Byte swapped data bus"
 	flavor  bool
diff -ur devs/eth/cl/cs8900a.orig/current/include/cs8900.h devs/eth/cl/cs8900a/current/include/cs8900.h
--- devs/eth/cl/cs8900a.orig/current/include/cs8900.h	2005-11-23 23:26:50.000000000 +0200
+++ devs/eth/cl/cs8900a/current/include/cs8900.h	2006-08-10 23:57:45.000000000 +0300
@@ -80,7 +80,9 @@
 // 2 for added data IO output: get_reg, put_reg
 // 4 for packet allocation/free output
 // 8 for only startup status, so we can tell we're installed OK
-#define DEBUG 0x0
+#ifndef DEBUG
+#  define DEBUG 0x0
+#endif
 
 #if DEBUG & 1
 #define DEBUG_FUNCTION() do { diag_printf("%s\n", __FUNCTION__); } while (0)
@@ -440,10 +442,10 @@
 get_reg(cyg_addrword_t base, int regno)
 {
     cyg_uint16 val;
-    HAL_WRITE_UINT16(base+CS8900A_PPTR, regno);
-    HAL_READ_UINT16(base+CS8900A_PDATA, val);
+    CS_OUT(base, CS8900A_PPTR, regno);
+    CS_IN(base, CS8900A_PDATA, val);
 #if DEBUG & 2
-    diag_printf("get_reg(%p, %d) => 0x%04x\n", base, regno, val);
+    diag_printf("get_reg(%p, %d) => 0x%04x\n", (void *)base, regno, val);
 #endif
     return val;
 }
@@ -452,10 +454,10 @@
 put_reg(cyg_addrword_t base, int regno, cyg_uint16 val)
 {
 #if DEBUG & 2
-    diag_printf("put_reg(%p, %d, 0x%04x)\n", base, regno, val);
+    diag_printf("put_reg(%p, %d, 0x%04x)\n", (void *)base, regno, val);
 #endif
-    HAL_WRITE_UINT16(base+CS8900A_PPTR, regno);
-    HAL_WRITE_UINT16(base+CS8900A_PDATA, val);
+    CS_OUT(base, CS8900A_PPTR, regno);
+    CS_OUT(base, CS8900A_PDATA, val);
 }
 
 #endif // _CYGONCE_ETH_CL_CS8900_H_
diff -ur devs/eth/cl/cs8900a.orig/current/src/if_cs8900a.c devs/eth/cl/cs8900a/current/src/if_cs8900a.c
--- devs/eth/cl/cs8900a.orig/current/src/if_cs8900a.c	2005-11-23 23:26:50.000000000 +0200
+++ devs/eth/cl/cs8900a/current/src/if_cs8900a.c	2006-08-10 23:57:45.000000000 +0300
@@ -212,7 +212,7 @@
     chip_type = get_reg(base, PP_ChipID);
     chip_rev = get_reg(base, PP_ChipRev);
 #if DEBUG & 8
-    diag_printf("CS8900A[%p] - type: 0x%04x, rev: 0x%04x\n", base, chip_type, chip_rev);
+    diag_printf("CS8900A[%p] - type: 0x%04x, rev: 0x%04x\n", (void *)base, chip_type, chip_rev);
 #endif
     if (chip_type != PP_ChipID_CL) {
 #if DEBUG & 8
@@ -353,10 +353,12 @@
     put_reg(base, PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);
     // Clear Interrupt Status Queue before enabling interrupts
     do {
-        HAL_READ_UINT16(cpd->base+CS8900A_ISQ, stat);
+        CS_IN(cpd->base, CS8900A_ISQ, stat);
     }  while (stat != 0) ;
     cpd->txbusy = false;
+#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT
     put_reg(base, PP_BusCtl, PP_BusCtl_EnableIRQ);
+#endif
 }
 
 // This routine is called to perform special "control" opertions
@@ -473,6 +475,7 @@
     cyg_uint8 *data;
     cyg_uint16 saved_data = 0, *sdata;
     cyg_uint16 stat;
+    bool force_coping_by_byte;
     bool odd_byte = false;
 
     // Mark xmitter busy
@@ -487,6 +490,12 @@
     total_len = CYG_SWAP16(total_len);
 #endif
         
+#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT
+    force_coping_by_byte = true;
+#else
+    force_coping_by_byte = false;
+#endif
+
     // The hardware indicates that there are options as to when the actual
     // packet transmission will start wrt moving of data into the transmit
     // buffer.  However, impirical results seem to indicate that if the
@@ -498,12 +507,12 @@
     // not all of the data was provided before the transmission should
     // have completed (i.e. buffer underrun).
     // For now, the solution is to not allow this overlap.
-    //HAL_WRITE_UINT16(cpd->base+CS8900A_TxCMD, PP_TxCmd_TxStart_5)
+    //CS_OUT(cpd->base, CS8900A_TxCMD, PP_TxCmd_TxStart_5)
 
     // Start only when all data sent to chip
-    HAL_WRITE_UINT16(cpd->base+CS8900A_TxCMD, PP_TxCmd_TxStart_Full);
+    CS_OUT(cpd->base, CS8900A_TxCMD, PP_TxCmd_TxStart_Full);
 
-    HAL_WRITE_UINT16(cpd->base+CS8900A_TxLEN, total_len);
+    CS_OUT(cpd->base, CS8900A_TxLEN, total_len);
     // Wait for controller ready signal
     do {
         stat = get_reg(base, PP_BusStat);
@@ -524,20 +533,20 @@
 #else
                 saved_data |= ((cyg_uint16)*data++) << 8;
 #endif
-                HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data);
+                CS_OUT(cpd->base, CS8900A_RTDATA, saved_data);
                 len--;
                 odd_byte = false;
             }
-            if (((CYG_ADDRESS)data & 0x1) == 0) {
+            if (!force_coping_by_byte && ((CYG_ADDRESS)data & 0x1) == 0) {
                 /* Aligned on 16-bit boundary, so output contiguous words. */
                 sdata = (cyg_uint16 *)data;
                 while (len > 1) {
 					// Make sure data get on the bus in Big Endian format
 #if((CYG_BYTEORDER == CYG_MSBFIRST) && defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED) || \
     (CYG_BYTEORDER == CYG_LSBFIRST) && !defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED ))
-                    HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, *sdata++);
+                    CS_OUT(cpd->base, CS8900A_RTDATA, *sdata++);
 #else
-                    HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, CYG_SWAP16(*sdata++));
+                    CS_OUT(cpd->base, CS8900A_RTDATA, CYG_SWAP16(*sdata++));
 #endif
                     len -= sizeof(cyg_uint16);
                 }
@@ -553,7 +562,7 @@
 #else
                     saved_data |= ((cyg_uint16)*data++) << 8;
 #endif
-                    HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data);
+                    CS_OUT(cpd->base, CS8900A_RTDATA, saved_data);
                     len -= sizeof(cyg_uint16);
                 }
             }
@@ -570,7 +579,7 @@
         }
     }
     if (odd_byte) {
-        HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data);
+        CS_OUT(cpd->base, CS8900A_RTDATA, saved_data);
     }
 }
 
@@ -588,8 +597,18 @@
 
     if(stat & PP_RxCFG_RxOK) {
         // Only start reading a message if one has been received
-        HAL_READ_UINT16(base+CS8900A_RTDATA, stat);
-        HAL_READ_UINT16(base+CS8900A_RTDATA, len);
+#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT
+        CS_IN(base, CS8900A_RTDATA, stat);
+        CS_IN(base, CS8900A_RTDATA, len);
+#else
+        // From AN181 Using the Crystal CS8900A in 8-bit mode.
+        // Note: it is very important to read the RxStatus and RxLength hight
+        // order byte first.
+        stat = *(volatile CYG_BYTE *)(base + CS8900A_RTDATA + 1) << 8;
+        stat |= *(volatile CYG_BYTE *)(base + CS8900A_RTDATA);
+        len = *(volatile CYG_BYTE *)(base + CS8900A_RTDATA + 1) << 8;
+        len |= *(volatile CYG_BYTE *)(base + CS8900A_RTDATA);
+#endif
 
 #ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
         len = CYG_SWAP16(len);
@@ -624,7 +643,7 @@
         data = (cyg_uint16 *)sg_list[i].buf;
         mlen = sg_list[i].len;
         while (mlen >= sizeof(*data)) {
-            HAL_READ_UINT16(base+CS8900A_RTDATA, val);
+            CS_IN(base, CS8900A_RTDATA, val);
             if (data) {
 #if((CYG_BYTEORDER == CYG_MSBFIRST) && defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED) || \
     (CYG_BYTEORDER == CYG_LSBFIRST) && !defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED ))
@@ -636,7 +655,7 @@
             mlen -= sizeof(*data);
         }
         if (mlen) {
-            HAL_READ_UINT16(base+CS8900A_RTDATA, val);
+            CS_IN(base, CS8900A_RTDATA, val);
 #ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED 
             // last odd byte will be in the LSB
             cval = (cyg_uint8)(val);
@@ -684,7 +703,7 @@
     cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
     cyg_addrword_t base = cpd->base;
 
-    HAL_READ_UINT16(base+CS8900A_ISQ, event);
+    CS_IN(base, CS8900A_ISQ, event);
     while (event != 0) {
         switch (event & ISQ_EventMask) {
         case ISQ_RxEvent:
@@ -708,7 +727,7 @@
 #endif
             break;
         }
-        HAL_READ_UINT16(base+CS8900A_ISQ, event);
+        CS_IN(base, CS8900A_ISQ, event);
     }
 
     CYGHWR_CL_CS8900A_PLF_INT_CLEAR(cpd);


More information about the Ecos-patches mailing list