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