|
|
|
@ -283,18 +283,18 @@ |
|
|
|
|
#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned char encReadReg(unsigned char regNo); |
|
|
|
|
static void encWriteReg(unsigned char regNo, unsigned char data); |
|
|
|
|
static void encWriteRegRetry(unsigned char regNo, unsigned char data, int c); |
|
|
|
|
static void encReadBuff(unsigned short length, unsigned char *pBuff); |
|
|
|
|
static void encWriteBuff(unsigned short length, unsigned char *pBuff); |
|
|
|
|
static void encBitSet(unsigned char regNo, unsigned char data); |
|
|
|
|
static void encBitClr(unsigned char regNo, unsigned char data); |
|
|
|
|
static void encReset(void); |
|
|
|
|
static void encInit(unsigned char *pEthAddr); |
|
|
|
|
static unsigned short phyRead(unsigned char addr); |
|
|
|
|
static void encPoll(void); |
|
|
|
|
static void encRx(void); |
|
|
|
|
static unsigned char encReadReg (unsigned char regNo); |
|
|
|
|
static void encWriteReg (unsigned char regNo, unsigned char data); |
|
|
|
|
static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c); |
|
|
|
|
static void encReadBuff (unsigned short length, unsigned char *pBuff); |
|
|
|
|
static void encWriteBuff (unsigned short length, unsigned char *pBuff); |
|
|
|
|
static void encBitSet (unsigned char regNo, unsigned char data); |
|
|
|
|
static void encBitClr (unsigned char regNo, unsigned char data); |
|
|
|
|
static void encReset (void); |
|
|
|
|
static void encInit (unsigned char *pEthAddr); |
|
|
|
|
static unsigned short phyRead (unsigned char addr); |
|
|
|
|
static void encPoll (void); |
|
|
|
|
static void encRx (void); |
|
|
|
|
|
|
|
|
|
#define m_nic_read(reg) encReadReg(reg) |
|
|
|
|
#define m_nic_write(reg, data) encWriteReg(reg, data) |
|
|
|
@ -314,57 +314,58 @@ static unsigned char next_pointer_msb; |
|
|
|
|
|
|
|
|
|
static unsigned char buffer[ENC_MAX_FRM_LEN]; |
|
|
|
|
static int rxResetCounter = 0; |
|
|
|
|
|
|
|
|
|
#define RX_RESET_COUNTER 1000; |
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
|
|
|
* Returns 0 when failes otherwize 1 |
|
|
|
|
*/ |
|
|
|
|
int eth_init(bd_t *bis) |
|
|
|
|
int eth_init (bd_t * bis) |
|
|
|
|
{ |
|
|
|
|
/* configure GPIO */ |
|
|
|
|
(*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS; |
|
|
|
|
(*((volatile unsigned long *) IO1DIR)) |= ENC_RESET; |
|
|
|
|
|
|
|
|
|
/* CS and RESET active low */ |
|
|
|
|
PUT32(IO1SET, ENC_SPI_SLAVE_CS); |
|
|
|
|
PUT32(IO1SET, ENC_RESET); |
|
|
|
|
PUT32 (IO1SET, ENC_SPI_SLAVE_CS); |
|
|
|
|
PUT32 (IO1SET, ENC_RESET); |
|
|
|
|
|
|
|
|
|
spi_init(); |
|
|
|
|
spi_init (); |
|
|
|
|
|
|
|
|
|
/* initialize controller */ |
|
|
|
|
encReset(); |
|
|
|
|
encInit(bis->bi_enetaddr); |
|
|
|
|
encReset (); |
|
|
|
|
encInit (bis->bi_enetaddr); |
|
|
|
|
|
|
|
|
|
m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */
|
|
|
|
|
m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */ |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int eth_send(volatile void *packet, int length) |
|
|
|
|
int eth_send (volatile void *packet, int length) |
|
|
|
|
{ |
|
|
|
|
/* check frame length, etc. */ |
|
|
|
|
/* TODO: */ |
|
|
|
|
|
|
|
|
|
/* switch to bank 0 */ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
|
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); |
|
|
|
|
|
|
|
|
|
/* set EWRPT */ |
|
|
|
|
m_nic_write(CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff)); |
|
|
|
|
m_nic_write(CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8)); |
|
|
|
|
m_nic_write (CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff)); |
|
|
|
|
m_nic_write (CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8)); |
|
|
|
|
|
|
|
|
|
/* set ETXST */ |
|
|
|
|
m_nic_write(CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF); |
|
|
|
|
m_nic_write(CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8); |
|
|
|
|
m_nic_write (CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF); |
|
|
|
|
m_nic_write (CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8); |
|
|
|
|
|
|
|
|
|
/* write packet */ |
|
|
|
|
m_nic_write_data(length, (unsigned char*)packet); |
|
|
|
|
m_nic_write_data (length, (unsigned char *) packet); |
|
|
|
|
|
|
|
|
|
/* set ETXND */ |
|
|
|
|
m_nic_write(CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF); |
|
|
|
|
m_nic_write(CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8); |
|
|
|
|
m_nic_write (CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF); |
|
|
|
|
m_nic_write (CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8); |
|
|
|
|
|
|
|
|
|
/* set ECON1.TXRTS */ |
|
|
|
|
m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_TXRTS); |
|
|
|
|
m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_TXRTS); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
@ -374,13 +375,13 @@ int eth_send(volatile void *packet, int length) |
|
|
|
|
* This function resets the receiver only. This function may be called from |
|
|
|
|
* interrupt-context. |
|
|
|
|
*/ |
|
|
|
|
static void encReceiverReset(void) |
|
|
|
|
static void encReceiverReset (void) |
|
|
|
|
{ |
|
|
|
|
unsigned char econ1; |
|
|
|
|
|
|
|
|
|
econ1 = m_nic_read(CTL_REG_ECON1); |
|
|
|
|
if((econ1 & ENC_ECON1_RXRST) == 0) { |
|
|
|
|
m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_RXRST); |
|
|
|
|
econ1 = m_nic_read (CTL_REG_ECON1); |
|
|
|
|
if ((econ1 & ENC_ECON1_RXRST) == 0) { |
|
|
|
|
m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXRST); |
|
|
|
|
rxResetCounter = RX_RESET_COUNTER; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -388,85 +389,84 @@ static void encReceiverReset(void) |
|
|
|
|
/*****************************************************************************
|
|
|
|
|
* receiver reset timer |
|
|
|
|
*/ |
|
|
|
|
static void encReceiverResetCallback(void) |
|
|
|
|
static void encReceiverResetCallback (void) |
|
|
|
|
{ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_RXRST); |
|
|
|
|
m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */ |
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXRST); |
|
|
|
|
m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
|
|
|
* Check for received packets. Call NetReceive for each packet. The return |
|
|
|
|
* value is ignored by the caller. |
|
|
|
|
*/ |
|
|
|
|
int eth_rx(void) |
|
|
|
|
int eth_rx (void) |
|
|
|
|
{ |
|
|
|
|
if(rxResetCounter > 0 && --rxResetCounter == 0) |
|
|
|
|
{ |
|
|
|
|
encReceiverResetCallback(); |
|
|
|
|
if (rxResetCounter > 0 && --rxResetCounter == 0) { |
|
|
|
|
encReceiverResetCallback (); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
encPoll(); |
|
|
|
|
encPoll (); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void eth_halt(void) |
|
|
|
|
void eth_halt (void) |
|
|
|
|
{ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_RXEN); /* disable receive */ |
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXEN); /* disable receive */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*****************************************************************************/ |
|
|
|
|
|
|
|
|
|
static void encPoll(void)
|
|
|
|
|
static void encPoll (void) |
|
|
|
|
{ |
|
|
|
|
unsigned char eir_reg; |
|
|
|
|
volatile unsigned char estat_reg; |
|
|
|
|
unsigned char pkt_cnt; |
|
|
|
|
|
|
|
|
|
/* clear global interrupt enable bit in enc28j60 */ |
|
|
|
|
m_nic_bfc(CTL_REG_EIE, ENC_EIE_INTIE); |
|
|
|
|
estat_reg = m_nic_read(CTL_REG_ESTAT); |
|
|
|
|
m_nic_bfc (CTL_REG_EIE, ENC_EIE_INTIE); |
|
|
|
|
estat_reg = m_nic_read (CTL_REG_ESTAT); |
|
|
|
|
|
|
|
|
|
eir_reg = m_nic_read(CTL_REG_EIR); |
|
|
|
|
eir_reg = m_nic_read (CTL_REG_EIR); |
|
|
|
|
|
|
|
|
|
if (eir_reg & ENC_EIR_TXIF){ |
|
|
|
|
if (eir_reg & ENC_EIR_TXIF) { |
|
|
|
|
/* clear TXIF bit in EIR */ |
|
|
|
|
m_nic_bfc(CTL_REG_EIR, ENC_EIR_TXIF); |
|
|
|
|
m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXIF); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* We have to use pktcnt and not pktif bit, see errata pt. 6 */ |
|
|
|
|
|
|
|
|
|
/* move to bank 1 */ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL1); |
|
|
|
|
m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0); |
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1); |
|
|
|
|
m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0); |
|
|
|
|
|
|
|
|
|
/* read pktcnt */ |
|
|
|
|
pkt_cnt = m_nic_read(CTL_REG_EPKTCNT); |
|
|
|
|
pkt_cnt = m_nic_read (CTL_REG_EPKTCNT); |
|
|
|
|
|
|
|
|
|
if (pkt_cnt > 0) { |
|
|
|
|
if ((eir_reg & ENC_EIR_PKTIF) == 0) { |
|
|
|
|
/*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */ |
|
|
|
|
} |
|
|
|
|
encRx(); |
|
|
|
|
encRx (); |
|
|
|
|
/* clear PKTIF bit in EIR, this should not need to be done but it
|
|
|
|
|
seems like we get problems if we do not */ |
|
|
|
|
m_nic_bfc(CTL_REG_EIR, ENC_EIR_PKTIF); |
|
|
|
|
m_nic_bfc (CTL_REG_EIR, ENC_EIR_PKTIF); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (eir_reg & ENC_EIR_RXERIF) { |
|
|
|
|
printf("encPoll: rx error\n"); |
|
|
|
|
m_nic_bfc(CTL_REG_EIR, ENC_EIR_RXERIF); |
|
|
|
|
printf ("encPoll: rx error\n"); |
|
|
|
|
m_nic_bfc (CTL_REG_EIR, ENC_EIR_RXERIF); |
|
|
|
|
} |
|
|
|
|
if (eir_reg & ENC_EIR_TXERIF) { |
|
|
|
|
printf("encPoll: tx error\n"); |
|
|
|
|
m_nic_bfc(CTL_REG_EIR, ENC_EIR_TXERIF); |
|
|
|
|
printf ("encPoll: tx error\n"); |
|
|
|
|
m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXERIF); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* set global interrupt enable bit in enc28j60 */ |
|
|
|
|
m_nic_bfs(CTL_REG_EIE, ENC_EIE_INTIE); |
|
|
|
|
m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void encRx(void) |
|
|
|
|
static void encRx (void) |
|
|
|
|
{ |
|
|
|
|
unsigned short pkt_len; |
|
|
|
|
unsigned short copy_len; |
|
|
|
@ -475,19 +475,19 @@ static void encRx(void) |
|
|
|
|
unsigned char pkt_cnt = 0; |
|
|
|
|
|
|
|
|
|
/* switch to bank 0 */ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); |
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); |
|
|
|
|
|
|
|
|
|
m_nic_write(CTL_REG_ERDPTL, next_pointer_lsb); |
|
|
|
|
m_nic_write(CTL_REG_ERDPTH, next_pointer_msb); |
|
|
|
|
m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb); |
|
|
|
|
m_nic_write (CTL_REG_ERDPTH, next_pointer_msb); |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
m_nic_read_data(6, buffer); |
|
|
|
|
m_nic_read_data (6, buffer); |
|
|
|
|
next_pointer_lsb = buffer[0]; |
|
|
|
|
next_pointer_msb = buffer[1]; |
|
|
|
|
pkt_len = buffer[2]; |
|
|
|
|
pkt_len |= (unsigned short)buffer[3] << 8; |
|
|
|
|
pkt_len |= (unsigned short) buffer[3] << 8; |
|
|
|
|
status = buffer[4]; |
|
|
|
|
status |= (unsigned short)buffer[5] << 8; |
|
|
|
|
status |= (unsigned short) buffer[5] << 8; |
|
|
|
|
|
|
|
|
|
if (pkt_len <= ENC_MAX_FRM_LEN) { |
|
|
|
|
copy_len = pkt_len; |
|
|
|
@ -503,218 +503,218 @@ static void encRx(void) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (copy_len > 0) { |
|
|
|
|
m_nic_read_data(copy_len, buffer); |
|
|
|
|
m_nic_read_data (copy_len, buffer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* advance read pointer to next pointer */ |
|
|
|
|
m_nic_write(CTL_REG_ERDPTL, next_pointer_lsb); |
|
|
|
|
m_nic_write(CTL_REG_ERDPTH, next_pointer_msb); |
|
|
|
|
m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb); |
|
|
|
|
m_nic_write (CTL_REG_ERDPTH, next_pointer_msb); |
|
|
|
|
|
|
|
|
|
/* decrease packet counter */ |
|
|
|
|
m_nic_bfs(CTL_REG_ECON2, ENC_ECON2_PKTDEC); |
|
|
|
|
m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_PKTDEC); |
|
|
|
|
|
|
|
|
|
/* move to bank 1 */ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL1); |
|
|
|
|
m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0); |
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1); |
|
|
|
|
m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0); |
|
|
|
|
|
|
|
|
|
/* read pktcnt */ |
|
|
|
|
pkt_cnt = m_nic_read(CTL_REG_EPKTCNT); |
|
|
|
|
pkt_cnt = m_nic_read (CTL_REG_EPKTCNT); |
|
|
|
|
|
|
|
|
|
/* switch to bank 0 */ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
|
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, |
|
|
|
|
(ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); |
|
|
|
|
|
|
|
|
|
if (copy_len == 0) { |
|
|
|
|
eir_reg = m_nic_read(CTL_REG_EIR); |
|
|
|
|
encReceiverReset(); |
|
|
|
|
printf("eth_rx: copy_len=0\n"); |
|
|
|
|
eir_reg = m_nic_read (CTL_REG_EIR); |
|
|
|
|
encReceiverReset (); |
|
|
|
|
printf ("eth_rx: copy_len=0\n"); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
NetReceive((unsigned char *)buffer, pkt_len); |
|
|
|
|
NetReceive ((unsigned char *) buffer, pkt_len); |
|
|
|
|
|
|
|
|
|
eir_reg = m_nic_read(CTL_REG_EIR); |
|
|
|
|
eir_reg = m_nic_read (CTL_REG_EIR); |
|
|
|
|
} while (pkt_cnt); /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */ |
|
|
|
|
m_nic_write(CTL_REG_ERXRDPTL, next_pointer_lsb); |
|
|
|
|
m_nic_write(CTL_REG_ERXRDPTH, next_pointer_msb); |
|
|
|
|
m_nic_write (CTL_REG_ERXRDPTL, next_pointer_lsb); |
|
|
|
|
m_nic_write (CTL_REG_ERXRDPTH, next_pointer_msb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void encWriteReg(unsigned char regNo, unsigned char data) |
|
|
|
|
static void encWriteReg (unsigned char regNo, unsigned char data) |
|
|
|
|
{ |
|
|
|
|
spi_lock(); |
|
|
|
|
enc_cfg_spi(); |
|
|
|
|
enc_enable(); |
|
|
|
|
spi_lock (); |
|
|
|
|
enc_cfg_spi (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(0x40 | regNo); /* write in regNo */ |
|
|
|
|
spi_write(data); |
|
|
|
|
spi_write (0x40 | regNo); /* write in regNo */ |
|
|
|
|
spi_write (data); |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
enc_enable(); |
|
|
|
|
enc_disable (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(0x1f); /* write reg 0x1f */ |
|
|
|
|
spi_write (0x1f); /* write reg 0x1f */ |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
spi_unlock(); |
|
|
|
|
enc_disable (); |
|
|
|
|
spi_unlock (); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void encWriteRegRetry(unsigned char regNo, unsigned char data, int c) |
|
|
|
|
static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c) |
|
|
|
|
{ |
|
|
|
|
unsigned char readback; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
spi_lock(); |
|
|
|
|
spi_lock (); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < c; i++) { |
|
|
|
|
enc_cfg_spi(); |
|
|
|
|
enc_enable(); |
|
|
|
|
enc_cfg_spi (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(0x40 | regNo); /* write in regNo */ |
|
|
|
|
spi_write(data); |
|
|
|
|
spi_write (0x40 | regNo); /* write in regNo */ |
|
|
|
|
spi_write (data); |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
enc_enable(); |
|
|
|
|
enc_disable (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(0x1f); /* write reg 0x1f */ |
|
|
|
|
spi_write (0x1f); /* write reg 0x1f */ |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
enc_disable (); |
|
|
|
|
|
|
|
|
|
spi_unlock(); /* we must unlock spi first */ |
|
|
|
|
spi_unlock (); /* we must unlock spi first */ |
|
|
|
|
|
|
|
|
|
readback = encReadReg(regNo); |
|
|
|
|
readback = encReadReg (regNo); |
|
|
|
|
|
|
|
|
|
spi_lock(); |
|
|
|
|
spi_lock (); |
|
|
|
|
|
|
|
|
|
if (readback == data) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
spi_unlock(); |
|
|
|
|
spi_unlock (); |
|
|
|
|
|
|
|
|
|
if (i == c) { |
|
|
|
|
printf("enc28j60: write reg %d failed\n", regNo); |
|
|
|
|
printf ("enc28j60: write reg %d failed\n", regNo); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static unsigned char encReadReg(unsigned char regNo) |
|
|
|
|
static unsigned char encReadReg (unsigned char regNo) |
|
|
|
|
{ |
|
|
|
|
unsigned char rxByte; |
|
|
|
|
|
|
|
|
|
spi_lock(); |
|
|
|
|
enc_cfg_spi(); |
|
|
|
|
enc_enable(); |
|
|
|
|
spi_lock (); |
|
|
|
|
enc_cfg_spi (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(0x1f); /* read reg 0x1f */ |
|
|
|
|
spi_write (0x1f); /* read reg 0x1f */ |
|
|
|
|
|
|
|
|
|
bank = spi_read() & 0x3; |
|
|
|
|
bank = spi_read () & 0x3; |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
enc_enable(); |
|
|
|
|
enc_disable (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(regNo); |
|
|
|
|
rxByte = spi_read(); |
|
|
|
|
spi_write (regNo); |
|
|
|
|
rxByte = spi_read (); |
|
|
|
|
|
|
|
|
|
/* check if MAC or MII register */ |
|
|
|
|
if (((bank == 2) && (regNo <= 0x1a)) || |
|
|
|
|
((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) { |
|
|
|
|
/* ignore first byte and read another byte */ |
|
|
|
|
rxByte = spi_read(); |
|
|
|
|
rxByte = spi_read (); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
spi_unlock(); |
|
|
|
|
enc_disable (); |
|
|
|
|
spi_unlock (); |
|
|
|
|
|
|
|
|
|
return rxByte; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void encReadBuff(unsigned short length, unsigned char *pBuff) |
|
|
|
|
static void encReadBuff (unsigned short length, unsigned char *pBuff) |
|
|
|
|
{ |
|
|
|
|
spi_lock(); |
|
|
|
|
enc_cfg_spi(); |
|
|
|
|
enc_enable(); |
|
|
|
|
spi_lock (); |
|
|
|
|
enc_cfg_spi (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(0x20 | 0x1a); /* read buffer memory */ |
|
|
|
|
spi_write (0x20 | 0x1a); /* read buffer memory */ |
|
|
|
|
|
|
|
|
|
while(length--) { |
|
|
|
|
if(pBuff != NULL) |
|
|
|
|
*pBuff++ = spi_read(); |
|
|
|
|
while (length--) { |
|
|
|
|
if (pBuff != NULL) |
|
|
|
|
*pBuff++ = spi_read (); |
|
|
|
|
else |
|
|
|
|
spi_write(0); |
|
|
|
|
spi_write (0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
spi_unlock(); |
|
|
|
|
enc_disable (); |
|
|
|
|
spi_unlock (); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void encWriteBuff(unsigned short length,
|
|
|
|
|
unsigned char *pBuff) |
|
|
|
|
static void encWriteBuff (unsigned short length, unsigned char *pBuff) |
|
|
|
|
{ |
|
|
|
|
spi_lock(); |
|
|
|
|
enc_cfg_spi(); |
|
|
|
|
enc_enable(); |
|
|
|
|
spi_lock (); |
|
|
|
|
enc_cfg_spi (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(0x60 | 0x1a); /* write buffer memory */ |
|
|
|
|
spi_write (0x60 | 0x1a); /* write buffer memory */ |
|
|
|
|
|
|
|
|
|
spi_write(0x00); /* control byte */ |
|
|
|
|
spi_write (0x00); /* control byte */ |
|
|
|
|
|
|
|
|
|
while(length--) |
|
|
|
|
spi_write(*pBuff++); |
|
|
|
|
while (length--) |
|
|
|
|
spi_write (*pBuff++); |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
spi_unlock(); |
|
|
|
|
enc_disable (); |
|
|
|
|
spi_unlock (); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void encBitSet(unsigned char regNo, unsigned char data) |
|
|
|
|
static void encBitSet (unsigned char regNo, unsigned char data) |
|
|
|
|
{ |
|
|
|
|
spi_lock(); |
|
|
|
|
enc_cfg_spi(); |
|
|
|
|
enc_enable(); |
|
|
|
|
spi_lock (); |
|
|
|
|
enc_cfg_spi (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(0x80 | regNo); /* bit field set */ |
|
|
|
|
spi_write(data); |
|
|
|
|
spi_write (0x80 | regNo); /* bit field set */ |
|
|
|
|
spi_write (data); |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
spi_unlock(); |
|
|
|
|
enc_disable (); |
|
|
|
|
spi_unlock (); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void encBitClr(unsigned char regNo, unsigned char data) |
|
|
|
|
static void encBitClr (unsigned char regNo, unsigned char data) |
|
|
|
|
{ |
|
|
|
|
spi_lock(); |
|
|
|
|
enc_cfg_spi(); |
|
|
|
|
enc_enable(); |
|
|
|
|
spi_lock (); |
|
|
|
|
enc_cfg_spi (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(0xA0 | regNo); /* bit field clear */ |
|
|
|
|
spi_write(data); |
|
|
|
|
spi_write (0xA0 | regNo); /* bit field clear */ |
|
|
|
|
spi_write (data); |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
spi_unlock(); |
|
|
|
|
enc_disable (); |
|
|
|
|
spi_unlock (); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void encReset(void) |
|
|
|
|
static void encReset (void) |
|
|
|
|
{ |
|
|
|
|
spi_lock(); |
|
|
|
|
enc_cfg_spi(); |
|
|
|
|
enc_enable(); |
|
|
|
|
spi_lock (); |
|
|
|
|
enc_cfg_spi (); |
|
|
|
|
enc_enable (); |
|
|
|
|
|
|
|
|
|
spi_write(0xff); /* soft reset */ |
|
|
|
|
spi_write (0xff); /* soft reset */ |
|
|
|
|
|
|
|
|
|
enc_disable(); |
|
|
|
|
spi_unlock(); |
|
|
|
|
enc_disable (); |
|
|
|
|
spi_unlock (); |
|
|
|
|
|
|
|
|
|
/* sleep 1 ms. See errata pt. 2 */ |
|
|
|
|
udelay(1000); |
|
|
|
|
udelay (1000); |
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
(*((volatile unsigned long*)IO1CLR)) &= ENC_RESET; |
|
|
|
|
mdelay(5); |
|
|
|
|
(*((volatile unsigned long*)IO1SET)) &= ENC_RESET; |
|
|
|
|
(*((volatile unsigned long *) IO1CLR)) &= ENC_RESET; |
|
|
|
|
mdelay (5); |
|
|
|
|
(*((volatile unsigned long *) IO1SET)) &= ENC_RESET; |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void encInit(unsigned char *pEthAddr) |
|
|
|
|
static void encInit (unsigned char *pEthAddr) |
|
|
|
|
{ |
|
|
|
|
unsigned short phid1 = 0; |
|
|
|
|
unsigned short phid2 = 0; |
|
|
|
|
|
|
|
|
|
/* switch to bank 0 */ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); |
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Setup the buffer space. The reset values are valid for the |
|
|
|
@ -723,11 +723,11 @@ static void encInit(unsigned char *pEthAddr) |
|
|
|
|
#if 0 |
|
|
|
|
/* We shall not write to ERXST, see errata pt. 5. Instead we
|
|
|
|
|
have to make sure that ENC_RX_BUS_START is 0. */ |
|
|
|
|
m_nic_write_retry(CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1); |
|
|
|
|
m_nic_write_retry(CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1); |
|
|
|
|
#endif |
|
|
|
|
m_nic_write_retry(CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1); |
|
|
|
|
m_nic_write_retry(CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1); |
|
|
|
|
|
|
|
|
|
next_pointer_lsb = (ENC_RX_BUF_START & 0xFF); |
|
|
|
|
next_pointer_msb = (ENC_RX_BUF_START >> 8); |
|
|
|
@ -736,37 +736,38 @@ static void encInit(unsigned char *pEthAddr) |
|
|
|
|
* For tracking purposes, the ERXRDPT registers should be programmed with |
|
|
|
|
* the same value. This is the read pointer. |
|
|
|
|
*/ |
|
|
|
|
m_nic_write(CTL_REG_ERXRDPTL, (ENC_RX_BUF_START & 0xFF)); |
|
|
|
|
m_nic_write_retry(CTL_REG_ERXRDPTH, (ENC_RX_BUF_START >> 8), 1); |
|
|
|
|
m_nic_write (CTL_REG_ERXRDPTL, (ENC_RX_BUF_START & 0xFF)); |
|
|
|
|
m_nic_write_retry (CTL_REG_ERXRDPTH, (ENC_RX_BUF_START >> 8), 1); |
|
|
|
|
|
|
|
|
|
/* Setup receive filters. */ |
|
|
|
|
|
|
|
|
|
/* move to bank 1 */ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL1); |
|
|
|
|
m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0); |
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1); |
|
|
|
|
m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0); |
|
|
|
|
|
|
|
|
|
/* OR-filtering, Unicast, CRC-check and broadcast */ |
|
|
|
|
m_nic_write_retry(CTL_REG_ERXFCON,
|
|
|
|
|
(ENC_RFR_UCEN|ENC_RFR_CRCEN|ENC_RFR_BCEN), 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_ERXFCON, |
|
|
|
|
(ENC_RFR_UCEN | ENC_RFR_CRCEN | ENC_RFR_BCEN), 1); |
|
|
|
|
|
|
|
|
|
/* Wait for Oscillator Start-up Timer (OST). */ |
|
|
|
|
while((m_nic_read(CTL_REG_ESTAT) & ENC_ESTAT_CLKRDY) == 0) { |
|
|
|
|
while ((m_nic_read (CTL_REG_ESTAT) & ENC_ESTAT_CLKRDY) == 0) { |
|
|
|
|
static int cnt = 0; |
|
|
|
|
if(cnt++ >= 1000){ |
|
|
|
|
|
|
|
|
|
if (cnt++ >= 1000) { |
|
|
|
|
cnt = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* verify identification */ |
|
|
|
|
phid1 = phyRead(PHY_REG_PHID1); |
|
|
|
|
phid2 = phyRead(PHY_REG_PHID2); |
|
|
|
|
phid1 = phyRead (PHY_REG_PHID1); |
|
|
|
|
phid2 = phyRead (PHY_REG_PHID2); |
|
|
|
|
|
|
|
|
|
if(phid1 != ENC_PHID1_VALUE
|
|
|
|
|
if (phid1 != ENC_PHID1_VALUE |
|
|
|
|
|| (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) { |
|
|
|
|
printf("ERROR: failed to identify controller\n"); |
|
|
|
|
printf("phid1 = %x, phid2 = %x\n",
|
|
|
|
|
phid1, (phid2&ENC_PHID2_MASK)); |
|
|
|
|
printf("should be phid1 = %x, phid2 = %x\n",
|
|
|
|
|
printf ("ERROR: failed to identify controller\n"); |
|
|
|
|
printf ("phid1 = %x, phid2 = %x\n", |
|
|
|
|
phid1, (phid2 & ENC_PHID2_MASK)); |
|
|
|
|
printf ("should be phid1 = %x, phid2 = %x\n", |
|
|
|
|
ENC_PHID1_VALUE, ENC_PHID2_VALUE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -777,63 +778,63 @@ static void encInit(unsigned char *pEthAddr) |
|
|
|
|
/* Pull MAC out of Reset */ |
|
|
|
|
|
|
|
|
|
/* switch to bank 2 */ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0); |
|
|
|
|
m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1); |
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0); |
|
|
|
|
m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1); |
|
|
|
|
/* clear MAC reset bits */ |
|
|
|
|
m_nic_write_retry(CTL_REG_MACON2, 0, 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_MACON2, 0, 1); |
|
|
|
|
|
|
|
|
|
/* enable MAC to receive frames */ |
|
|
|
|
m_nic_write_retry(CTL_REG_MACON1, ENC_MACON1_MARXEN, 10); |
|
|
|
|
m_nic_write_retry (CTL_REG_MACON1, ENC_MACON1_MARXEN, 10); |
|
|
|
|
|
|
|
|
|
/* configure pad, tx-crc and duplex */ |
|
|
|
|
/* TODO maybe enable FRMLNEN */ |
|
|
|
|
m_nic_write_retry(CTL_REG_MACON3, (ENC_MACON3_PADCFG0|ENC_MACON3_TXCRCEN),
|
|
|
|
|
10); |
|
|
|
|
m_nic_write_retry (CTL_REG_MACON3, |
|
|
|
|
(ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN), 10); |
|
|
|
|
|
|
|
|
|
/* set maximum frame length */ |
|
|
|
|
m_nic_write_retry(CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10); |
|
|
|
|
m_nic_write_retry(CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10); |
|
|
|
|
m_nic_write_retry (CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10); |
|
|
|
|
m_nic_write_retry (CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex |
|
|
|
|
* and 0x15 for full duplex. |
|
|
|
|
*/ |
|
|
|
|
m_nic_write_retry(CTL_REG_MABBIPG, 0x12, 10); |
|
|
|
|
m_nic_write_retry (CTL_REG_MABBIPG, 0x12, 10); |
|
|
|
|
|
|
|
|
|
/* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */ |
|
|
|
|
m_nic_write_retry(CTL_REG_MAIPGL, 0x12, 10); |
|
|
|
|
m_nic_write_retry (CTL_REG_MAIPGL, 0x12, 10); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended |
|
|
|
|
* 0x0c for half-duplex. Nothing for full-duplex |
|
|
|
|
*/ |
|
|
|
|
m_nic_write_retry(CTL_REG_MAIPGH, 0x0C, 10); |
|
|
|
|
m_nic_write_retry (CTL_REG_MAIPGH, 0x0C, 10); |
|
|
|
|
|
|
|
|
|
/* set MAC address */ |
|
|
|
|
|
|
|
|
|
/* switch to bank 3 */ |
|
|
|
|
m_nic_bfs(CTL_REG_ECON1, (ENC_ECON1_BSEL0|ENC_ECON1_BSEL1)); |
|
|
|
|
m_nic_bfs (CTL_REG_ECON1, (ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1)); |
|
|
|
|
|
|
|
|
|
m_nic_write_retry(CTL_REG_MAADR0, pEthAddr[5], 1); |
|
|
|
|
m_nic_write_retry(CTL_REG_MAADR1, pEthAddr[4], 1); |
|
|
|
|
m_nic_write_retry(CTL_REG_MAADR2, pEthAddr[3], 1); |
|
|
|
|
m_nic_write_retry(CTL_REG_MAADR3, pEthAddr[2], 1); |
|
|
|
|
m_nic_write_retry(CTL_REG_MAADR4, pEthAddr[1], 1); |
|
|
|
|
m_nic_write_retry(CTL_REG_MAADR5, pEthAddr[0], 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_MAADR0, pEthAddr[5], 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_MAADR1, pEthAddr[4], 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_MAADR2, pEthAddr[3], 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_MAADR3, pEthAddr[2], 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_MAADR4, pEthAddr[1], 1); |
|
|
|
|
m_nic_write_retry (CTL_REG_MAADR5, pEthAddr[0], 1); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Receive settings |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/* auto-increment RX-pointer when reading a received packet */ |
|
|
|
|
m_nic_bfs(CTL_REG_ECON2, ENC_ECON2_AUTOINC); |
|
|
|
|
m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_AUTOINC); |
|
|
|
|
|
|
|
|
|
/* enable interrupts */ |
|
|
|
|
m_nic_bfs(CTL_REG_EIE, ENC_EIE_PKTIE); |
|
|
|
|
m_nic_bfs(CTL_REG_EIE, ENC_EIE_TXIE); |
|
|
|
|
m_nic_bfs(CTL_REG_EIE, ENC_EIE_RXERIE); |
|
|
|
|
m_nic_bfs(CTL_REG_EIE, ENC_EIE_TXERIE); |
|
|
|
|
m_nic_bfs(CTL_REG_EIE, ENC_EIE_INTIE); |
|
|
|
|
m_nic_bfs (CTL_REG_EIE, ENC_EIE_PKTIE); |
|
|
|
|
m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXIE); |
|
|
|
|
m_nic_bfs (CTL_REG_EIE, ENC_EIE_RXERIE); |
|
|
|
|
m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXERIE); |
|
|
|
|
m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
@ -849,25 +850,25 @@ static void encInit(unsigned char *pEthAddr) |
|
|
|
|
* Returns: |
|
|
|
|
* The value in the register |
|
|
|
|
*/ |
|
|
|
|
static unsigned short phyRead(unsigned char addr) |
|
|
|
|
static unsigned short phyRead (unsigned char addr) |
|
|
|
|
{ |
|
|
|
|
unsigned short ret = 0; |
|
|
|
|
|
|
|
|
|
/* move to bank 2 */ |
|
|
|
|
m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0); |
|
|
|
|
m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1); |
|
|
|
|
m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0); |
|
|
|
|
m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1); |
|
|
|
|
|
|
|
|
|
/* write address to MIREGADR */ |
|
|
|
|
m_nic_write(CTL_REG_MIREGADR, addr); |
|
|
|
|
m_nic_write (CTL_REG_MIREGADR, addr); |
|
|
|
|
|
|
|
|
|
/* set MICMD.MIIRD */ |
|
|
|
|
m_nic_write(CTL_REG_MICMD, ENC_MICMD_MIIRD); |
|
|
|
|
m_nic_write (CTL_REG_MICMD, ENC_MICMD_MIIRD); |
|
|
|
|
|
|
|
|
|
/* poll MISTAT.BUSY bit until operation is complete */ |
|
|
|
|
while((m_nic_read(CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) { |
|
|
|
|
while ((m_nic_read (CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) { |
|
|
|
|
static int cnt = 0; |
|
|
|
|
|
|
|
|
|
if(cnt++ >= 1000) { |
|
|
|
|
if (cnt++ >= 1000) { |
|
|
|
|
/* GJ - this seems extremely dangerous! */ |
|
|
|
|
/* printf("#"); */ |
|
|
|
|
cnt = 0; |
|
|
|
@ -875,10 +876,10 @@ static unsigned short phyRead(unsigned char addr) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* clear MICMD.MIIRD */ |
|
|
|
|
m_nic_write(CTL_REG_MICMD, 0); |
|
|
|
|
m_nic_write (CTL_REG_MICMD, 0); |
|
|
|
|
|
|
|
|
|
ret = (m_nic_read(CTL_REG_MIRDH) << 8); |
|
|
|
|
ret |= (m_nic_read(CTL_REG_MIRDL) & 0xFF); |
|
|
|
|
ret = (m_nic_read (CTL_REG_MIRDH) << 8); |
|
|
|
|
ret |= (m_nic_read (CTL_REG_MIRDL) & 0xFF); |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|