mbed library sources, include can_api for nucleo-f091rc
Dependents: CanNucleoF0_example
Fork of mbed-src by
Diff: targets/hal/TARGET_NXP/TARGET_LPC43XX/ethernet_api.c
- Revision:
- 467:4961165abe5d
- Parent:
- 285:31249416b6f9
--- a/targets/hal/TARGET_NXP/TARGET_LPC43XX/ethernet_api.c Fri Feb 06 08:30:07 2015 +0000 +++ b/targets/hal/TARGET_NXP/TARGET_LPC43XX/ethernet_api.c Mon Feb 09 08:45:07 2015 +0000 @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-2015 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Ported to NXP LPC43XX by Micromint USA <support@micromint.com> + * Contribution by Nitin Bhaskar(nitin.bhaskar.27.09@gmail.com) */ #include "ethernet_api.h" @@ -22,6 +22,7 @@ #include "mbed_interface.h" #include "toolchain.h" #include "mbed_error.h" +#include "pinmap.h" #define NEW_LOGIC 0 #define NEW_ETH_BUFFER 0 @@ -54,83 +55,76 @@ #define ETHERNET_ADDR_SIZE 6 +/* Descriptors Fields bits */ +#define TRDES_OWN_BIT (1U<<31) /* Own bit in RDES0 & TDES0 */ +#define RX_END_RING (1<<15) /* Receive End of Ring bit in RDES1 */ +#define RX_NXTDESC_FLAG (1<<14) /* Second Address Chained bit in RDES1 */ +#define TX_LAST_SEGM (1<<29) /* Last Segment bit in TDES0 */ +#define TX_FIRST_SEGM (1<<28) /* First Segment bit in TDES0 */ +#define TX_END_RING (1<<21) /* Transmit End of Ring bit in TDES0 */ +#define TX_NXTDESC_FLAG (1<<20) /* Second Address Chained bit in TDES0 */ + PACKED struct RX_DESC_TypeDef { /* RX Descriptor struct */ - unsigned int Packet; - unsigned int Ctrl; + unsigned int Status; + unsigned int Ctrl; + unsigned int BufAddr1; + unsigned int NextDescAddr; }; typedef struct RX_DESC_TypeDef RX_DESC_TypeDef; -PACKED struct RX_STAT_TypeDef { /* RX Status struct */ - unsigned int Info; - unsigned int HashCRC; -}; -typedef struct RX_STAT_TypeDef RX_STAT_TypeDef; - PACKED struct TX_DESC_TypeDef { /* TX Descriptor struct */ - unsigned int Packet; - unsigned int Ctrl; + unsigned int Status; + unsigned int Ctrl; + unsigned int BufAddr1; + unsigned int NextDescAddr; }; typedef struct TX_DESC_TypeDef TX_DESC_TypeDef; -PACKED struct TX_STAT_TypeDef { /* TX Status struct */ - unsigned int Info; -}; -typedef struct TX_STAT_TypeDef TX_STAT_TypeDef; +/* ETHMODE RMII SELECT */ +#define RMII_SELECT 0x04 +/* define to tell PHY about write operation */ +#define MII_WRITE (1 << 1) +/* define to tell PHY about read operation */ +#define MII_READ (0 << 1) +/* define to enable duplex mode */ +#define MAC_DUPLEX_MODE (1 << 11) -/* MAC Configuration Register 1 */ -#define MAC1_REC_EN 0x00000001 /* Receive Enable */ -#define MAC1_PASS_ALL 0x00000002 /* Pass All Receive Frames */ -#define MAC1_RX_FLOWC 0x00000004 /* RX Flow Control */ -#define MAC1_TX_FLOWC 0x00000008 /* TX Flow Control */ -#define MAC1_LOOPB 0x00000010 /* Loop Back Mode */ -#define MAC1_RES_TX 0x00000100 /* Reset TX Logic */ -#define MAC1_RES_MCS_TX 0x00000200 /* Reset MAC TX Control Sublayer */ -#define MAC1_RES_RX 0x00000400 /* Reset RX Logic */ -#define MAC1_RES_MCS_RX 0x00000800 /* Reset MAC RX Control Sublayer */ -#define MAC1_SIM_RES 0x00004000 /* Simulation Reset */ -#define MAC1_SOFT_RES 0x00008000 /* Soft Reset MAC */ +/* MAC_FRAME_FILTER register bit defines */ +#define MAC_FRAME_FILTER_PR (1 << 0) /* Promiscuous Mode */ +#define MAC_FRAME_FILTER_RA (1UL << 31) /* Receive all */ + +/* MAC_CONFIG register bit defines */ +#define MAC_CONFIG_RE (1 << 2) /* Receiver enable */ +#define MAC_CONFIG_TE (1 << 3) /* Transmitter Enable */ -/* MAC Configuration Register 2 */ -#define MAC2_FULL_DUP 0x00000001 /* Full Duplex Mode */ -#define MAC2_FRM_LEN_CHK 0x00000002 /* Frame Length Checking */ -#define MAC2_HUGE_FRM_EN 0x00000004 /* Huge Frame Enable */ -#define MAC2_DLY_CRC 0x00000008 /* Delayed CRC Mode */ -#define MAC2_CRC_EN 0x00000010 /* Append CRC to every Frame */ -#define MAC2_PAD_EN 0x00000020 /* Pad all Short Frames */ -#define MAC2_VLAN_PAD_EN 0x00000040 /* VLAN Pad Enable */ -#define MAC2_ADET_PAD_EN 0x00000080 /* Auto Detect Pad Enable */ -#define MAC2_PPREAM_ENF 0x00000100 /* Pure Preamble Enforcement */ -#define MAC2_LPREAM_ENF 0x00000200 /* Long Preamble Enforcement */ -#define MAC2_NO_BACKOFF 0x00001000 /* No Backoff Algorithm */ -#define MAC2_BACK_PRESSURE 0x00002000 /* Backoff Presurre / No Backoff */ -#define MAC2_EXCESS_DEF 0x00004000 /* Excess Defer */ +/* DMA_OP_MODE register bit defines */ +#define DMA_OP_MODE_SSR (1 << 1) /* Start/stop receive */ +#define DMA_OP_MODE_SST (1 << 13) /* Start/Stop Transmission Command */ -/* Back-to-Back Inter-Packet-Gap Register */ -#define IPGT_FULL_DUP 0x00000015 /* Recommended value for Full Duplex */ -#define IPGT_HALF_DUP 0x00000012 /* Recommended value for Half Duplex */ +/* DMA_INT_EN register bit defines */ +#define DMA_INT_EN_TIE (1 << 0) /* Transmit interrupt enable */ +#define DMA_INT_EN_TSE (1 << 1) /* Transmit stopped enable */ +#define DMA_INT_EN_TUE (1 << 2) /* Transmit buffer unavailable enable */ +#define DMA_INT_EN_TJE (1 << 3) /* Transmit jabber timeout enable */ +#define DMA_INT_EN_OVE (1 << 4) /* Overflow interrupt enable */ +#define DMA_INT_EN_UNE (1 << 5) /* Underflow interrupt enable */ +#define DMA_INT_EN_RIE (1 << 6) /* Receive interrupt enable */ +#define DMA_INT_EN_RUE (1 << 7) /* Receive buffer unavailable enable */ +#define DMA_INT_EN_RSE (1 << 8) /* Received stopped enable */ +#define DMA_INT_EN_RWE (1 << 9) /* Receive watchdog timeout enable */ +#define DMA_INT_EN_ETE (1 << 10) /* Early transmit interrupt enable */ +#define DMA_INT_EN_FBE (1 << 13) /* Fatal bus error enable */ +#define DMA_INT_EN_ERE (1 << 14) /* Early receive interrupt enable */ +#define DMA_INT_EN_AIE (1 << 15) /* Abnormal interrupt summary enable */ +#define DMA_INT_EN_NIE (1 << 16) /* Normal interrupt summary enable */ -/* Non Back-to-Back Inter-Packet-Gap Register */ -#define IPGR_DEF 0x00000012 /* Recommended value */ -/* Collision Window/Retry Register */ -#define CLRT_DEF 0x0000370F /* Default value */ /* PHY Support Register */ -#define SUPP_SPEED 0x00000100 /* Reduced MII Logic Current Speed */ +#define SUPP_SPEED 0x00004000 /* Reduced MII Logic Current Speed */ //#define SUPP_RES_RMII 0x00000800 /* Reset Reduced MII Logic */ #define SUPP_RES_RMII 0x00000000 /* Reset Reduced MII Logic */ -/* Test Register */ -#define TEST_SHCUT_PQUANTA 0x00000001 /* Shortcut Pause Quanta */ -#define TEST_TST_PAUSE 0x00000002 /* Test Pause */ -#define TEST_TST_BACKP 0x00000004 /* Test Back Pressure */ - -/* MII Management Configuration Register */ -#define MCFG_SCAN_INC 0x00000001 /* Scan Increment PHY Address */ -#define MCFG_SUPP_PREAM 0x00000002 /* Suppress Preamble */ -#define MCFG_CLK_SEL 0x0000003C /* Clock Select Mask */ -#define MCFG_RES_MII 0x00008000 /* Reset MII Management Hardware */ - /* MII Management Command Register */ #define MCMD_READ 0x00000001 /* MII Read */ #define MCMD_SCAN 0x00000002 /* MII Scan continuously */ @@ -148,157 +142,6 @@ #define MIND_NOT_VAL 0x00000004 /* MII Read Data not valid */ #define MIND_MII_LINK_FAIL 0x00000008 /* MII Link Failed */ -/* Command Register */ -#define CR_RX_EN 0x00000001 /* Enable Receive */ -#define CR_TX_EN 0x00000002 /* Enable Transmit */ -#define CR_REG_RES 0x00000008 /* Reset Host Registers */ -#define CR_TX_RES 0x00000010 /* Reset Transmit Datapath */ -#define CR_RX_RES 0x00000020 /* Reset Receive Datapath */ -#define CR_PASS_RUNT_FRM 0x00000040 /* Pass Runt Frames */ -#define CR_PASS_RX_FILT 0x00000080 /* Pass RX Filter */ -#define CR_TX_FLOW_CTRL 0x00000100 /* TX Flow Control */ -#define CR_RMII 0x00000200 /* Reduced MII Interface */ -#define CR_FULL_DUP 0x00000400 /* Full Duplex */ - -/* Status Register */ -#define SR_RX_EN 0x00000001 /* Enable Receive */ -#define SR_TX_EN 0x00000002 /* Enable Transmit */ - -/* Transmit Status Vector 0 Register */ -#define TSV0_CRC_ERR 0x00000001 /* CRC error */ -#define TSV0_LEN_CHKERR 0x00000002 /* Length Check Error */ -#define TSV0_LEN_OUTRNG 0x00000004 /* Length Out of Range */ -#define TSV0_DONE 0x00000008 /* Tramsmission Completed */ -#define TSV0_MCAST 0x00000010 /* Multicast Destination */ -#define TSV0_BCAST 0x00000020 /* Broadcast Destination */ -#define TSV0_PKT_DEFER 0x00000040 /* Packet Deferred */ -#define TSV0_EXC_DEFER 0x00000080 /* Excessive Packet Deferral */ -#define TSV0_EXC_COLL 0x00000100 /* Excessive Collision */ -#define TSV0_LATE_COLL 0x00000200 /* Late Collision Occured */ -#define TSV0_GIANT 0x00000400 /* Giant Frame */ -#define TSV0_UNDERRUN 0x00000800 /* Buffer Underrun */ -#define TSV0_BYTES 0x0FFFF000 /* Total Bytes Transferred */ -#define TSV0_CTRL_FRAME 0x10000000 /* Control Frame */ -#define TSV0_PAUSE 0x20000000 /* Pause Frame */ -#define TSV0_BACK_PRESS 0x40000000 /* Backpressure Method Applied */ -#define TSV0_VLAN 0x80000000 /* VLAN Frame */ - -/* Transmit Status Vector 1 Register */ -#define TSV1_BYTE_CNT 0x0000FFFF /* Transmit Byte Count */ -#define TSV1_COLL_CNT 0x000F0000 /* Transmit Collision Count */ - -/* Receive Status Vector Register */ -#define RSV_BYTE_CNT 0x0000FFFF /* Receive Byte Count */ -#define RSV_PKT_IGNORED 0x00010000 /* Packet Previously Ignored */ -#define RSV_RXDV_SEEN 0x00020000 /* RXDV Event Previously Seen */ -#define RSV_CARR_SEEN 0x00040000 /* Carrier Event Previously Seen */ -#define RSV_REC_CODEV 0x00080000 /* Receive Code Violation */ -#define RSV_CRC_ERR 0x00100000 /* CRC Error */ -#define RSV_LEN_CHKERR 0x00200000 /* Length Check Error */ -#define RSV_LEN_OUTRNG 0x00400000 /* Length Out of Range */ -#define RSV_REC_OK 0x00800000 /* Frame Received OK */ -#define RSV_MCAST 0x01000000 /* Multicast Frame */ -#define RSV_BCAST 0x02000000 /* Broadcast Frame */ -#define RSV_DRIB_NIBB 0x04000000 /* Dribble Nibble */ -#define RSV_CTRL_FRAME 0x08000000 /* Control Frame */ -#define RSV_PAUSE 0x10000000 /* Pause Frame */ -#define RSV_UNSUPP_OPC 0x20000000 /* Unsupported Opcode */ -#define RSV_VLAN 0x40000000 /* VLAN Frame */ - -/* Flow Control Counter Register */ -#define FCC_MIRR_CNT 0x0000FFFF /* Mirror Counter */ -#define FCC_PAUSE_TIM 0xFFFF0000 /* Pause Timer */ - -/* Flow Control Status Register */ -#define FCS_MIRR_CNT 0x0000FFFF /* Mirror Counter Current */ - -/* Receive Filter Control Register */ -#define RFC_UCAST_EN 0x00000001 /* Accept Unicast Frames Enable */ -#define RFC_BCAST_EN 0x00000002 /* Accept Broadcast Frames Enable */ -#define RFC_MCAST_EN 0x00000004 /* Accept Multicast Frames Enable */ -#define RFC_UCAST_HASH_EN 0x00000008 /* Accept Unicast Hash Filter Frames */ -#define RFC_MCAST_HASH_EN 0x00000010 /* Accept Multicast Hash Filter Fram.*/ -#define RFC_PERFECT_EN 0x00000020 /* Accept Perfect Match Enable */ -#define RFC_MAGP_WOL_EN 0x00001000 /* Magic Packet Filter WoL Enable */ -#define RFC_PFILT_WOL_EN 0x00002000 /* Perfect Filter WoL Enable */ - -/* Receive Filter WoL Status/Clear Registers */ -#define WOL_UCAST 0x00000001 /* Unicast Frame caused WoL */ -#define WOL_BCAST 0x00000002 /* Broadcast Frame caused WoL */ -#define WOL_MCAST 0x00000004 /* Multicast Frame caused WoL */ -#define WOL_UCAST_HASH 0x00000008 /* Unicast Hash Filter Frame WoL */ -#define WOL_MCAST_HASH 0x00000010 /* Multicast Hash Filter Frame WoL */ -#define WOL_PERFECT 0x00000020 /* Perfect Filter WoL */ -#define WOL_RX_FILTER 0x00000080 /* RX Filter caused WoL */ -#define WOL_MAG_PACKET 0x00000100 /* Magic Packet Filter caused WoL */ - -/* Interrupt Status/Enable/Clear/Set Registers */ -#define INT_RX_OVERRUN 0x00000001 /* Overrun Error in RX Queue */ -#define INT_RX_ERR 0x00000002 /* Receive Error */ -#define INT_RX_FIN 0x00000004 /* RX Finished Process Descriptors */ -#define INT_RX_DONE 0x00000008 /* Receive Done */ -#define INT_TX_UNDERRUN 0x00000010 /* Transmit Underrun */ -#define INT_TX_ERR 0x00000020 /* Transmit Error */ -#define INT_TX_FIN 0x00000040 /* TX Finished Process Descriptors */ -#define INT_TX_DONE 0x00000080 /* Transmit Done */ -#define INT_SOFT_INT 0x00001000 /* Software Triggered Interrupt */ -#define INT_WAKEUP 0x00002000 /* Wakeup Event Interrupt */ - -/* Power Down Register */ -#define PD_POWER_DOWN 0x80000000 /* Power Down MAC */ - -/* RX Descriptor Control Word */ -#define RCTRL_SIZE 0x000007FF /* Buffer size mask */ -#define RCTRL_INT 0x80000000 /* Generate RxDone Interrupt */ - -/* RX Status Hash CRC Word */ -#define RHASH_SA 0x000001FF /* Hash CRC for Source Address */ -#define RHASH_DA 0x001FF000 /* Hash CRC for Destination Address */ - -/* RX Status Information Word */ -#define RINFO_SIZE 0x000007FF /* Data size in bytes */ -#define RINFO_CTRL_FRAME 0x00040000 /* Control Frame */ -#define RINFO_VLAN 0x00080000 /* VLAN Frame */ -#define RINFO_FAIL_FILT 0x00100000 /* RX Filter Failed */ -#define RINFO_MCAST 0x00200000 /* Multicast Frame */ -#define RINFO_BCAST 0x00400000 /* Broadcast Frame */ -#define RINFO_CRC_ERR 0x00800000 /* CRC Error in Frame */ -#define RINFO_SYM_ERR 0x01000000 /* Symbol Error from PHY */ -#define RINFO_LEN_ERR 0x02000000 /* Length Error */ -#define RINFO_RANGE_ERR 0x04000000 /* Range Error (exceeded max. size) */ -#define RINFO_ALIGN_ERR 0x08000000 /* Alignment Error */ -#define RINFO_OVERRUN 0x10000000 /* Receive overrun */ -#define RINFO_NO_DESCR 0x20000000 /* No new Descriptor available */ -#define RINFO_LAST_FLAG 0x40000000 /* Last Fragment in Frame */ -#define RINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */ - -//#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_CRC_ERR | RINFO_SYM_ERR | RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN) -#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_SYM_ERR | \ - RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN) - - -/* TX Descriptor Control Word */ -#define TCTRL_SIZE 0x000007FF /* Size of data buffer in bytes */ -#define TCTRL_OVERRIDE 0x04000000 /* Override Default MAC Registers */ -#define TCTRL_HUGE 0x08000000 /* Enable Huge Frame */ -#define TCTRL_PAD 0x10000000 /* Pad short Frames to 64 bytes */ -#define TCTRL_CRC 0x20000000 /* Append a hardware CRC to Frame */ -#define TCTRL_LAST 0x40000000 /* Last Descriptor for TX Frame */ -#define TCTRL_INT 0x80000000 /* Generate TxDone Interrupt */ - -/* TX Status Information Word */ -#define TINFO_COL_CNT 0x01E00000 /* Collision Count */ -#define TINFO_DEFER 0x02000000 /* Packet Deferred (not an error) */ -#define TINFO_EXCESS_DEF 0x04000000 /* Excessive Deferral */ -#define TINFO_EXCESS_COL 0x08000000 /* Excessive Collision */ -#define TINFO_LATE_COL 0x10000000 /* Late Collision Occured */ -#define TINFO_UNDERRUN 0x20000000 /* Transmit Underrun */ -#define TINFO_NO_DESCR 0x40000000 /* No new Descriptor available */ -#define TINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */ - -/* ENET Device Revision ID */ -#define OLD_EMAC_MODULE_ID 0x39022000 /* Rev. ID for first rev '-' */ - /* DP83848C PHY Registers */ #define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */ #define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */ @@ -329,9 +172,9 @@ #define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */ #define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */ #define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */ -#define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */ +#define PHY_AUTO_NEG 0x1000 /* Select Auto Negotiation */ -#define DP83848C_DEF_ADR 0x0100 /* Default PHY device address */ +#define DP83848C_DEF_ADR 0x01 /* Default PHY device address */ #define DP83848C_ID 0x20005C90 /* PHY Identifier - DP83848C */ #define LAN8720_ID 0x0007C0F0 /* PHY Identifier - LAN8720 */ @@ -347,6 +190,12 @@ #define PHY_SCSR_100MBIT 0x0008 /* Speed: 1=100 MBit, 0=10Mbit */ #define PHY_SCSR_DUPLEX 0x0010 /* PHY Duplex Mask */ +static int phy_read(unsigned int PhyReg); +static int phy_write(unsigned int PhyReg, unsigned short Data); + +static void txdscr_init(void); +static void rxdscr_init(void); + #if defined (__ICCARM__) # define AHBSRAM1 #elif defined(TOOLCHAIN_GCC_CR) @@ -358,78 +207,322 @@ AHBSRAM1 volatile uint8_t rxbuf[NUM_RX_FRAG][ETH_FRAG_SIZE]; AHBSRAM1 volatile uint8_t txbuf[NUM_TX_FRAG][ETH_FRAG_SIZE]; AHBSRAM1 volatile RX_DESC_TypeDef rxdesc[NUM_RX_FRAG]; -AHBSRAM1 volatile RX_STAT_TypeDef rxstat[NUM_RX_FRAG]; AHBSRAM1 volatile TX_DESC_TypeDef txdesc[NUM_TX_FRAG]; -AHBSRAM1 volatile TX_STAT_TypeDef txstat[NUM_TX_FRAG]; #ifndef min #define min(x, y) (((x)<(y))?(x):(y)) #endif +static uint32_t phy_id = 0; +static uint32_t TxDescIndex = 0; +static uint32_t RxDescIndex = 0; +static uint32_t RxOffset = 0; + /*---------------------------------------------------------------------------- Ethernet Device initialize *----------------------------------------------------------------------------*/ -int ethernet_init() { - return 0; +int ethernet_init() +{ + int regv, tout; + char mac[ETHERNET_ADDR_SIZE]; + + pin_function(PC_0, (SCU_MODE_INACT | FUNC3)); /* Enable ENET RX CLK */ + pin_function(P1_19, (SCU_MODE_INACT | FUNC0)); /* Enable ENET TX CLK */ + + /* Ethernet pinmuxing */ + pin_function(P2_0, SCU_PINIO_FAST | FUNC7); /* ENET_MDC */ + pin_function(P1_17, SCU_PINIO_FAST | FUNC3); /* ENET_MDIO */ + pin_function(P1_18, SCU_PINIO_FAST | FUNC3); /* ENET_TXD0 */ + pin_function(P1_20, SCU_PINIO_FAST | FUNC3); /* ENET_TXD1 */ + pin_function(P1_19, SCU_PINIO_FAST | FUNC0); /* ENET_REF */ + pin_function(P0_1, SCU_PINIO_FAST | FUNC6); /* ENET_TX_EN */ + pin_function(P1_15, SCU_PINIO_FAST | FUNC3); /* ENET_RXD0 */ + pin_function(P0_0, SCU_PINIO_FAST | FUNC2); /* ENET_RXD1 */ + pin_function(P1_16, SCU_PINIO_FAST | FUNC3); /* ENET_CRS */ + pin_function(PC_9, SCU_PINIO_FAST | FUNC3); /* ENET_RX_ER */ + pin_function(P1_16, SCU_PINIO_FAST | FUNC7); /* ENET_RXDV */ + + LPC_CREG->CREG6 |= RMII_SELECT; + + /* perform RGU soft reset */ + LPC_RGU->RESET_CTRL0 = 1 << 22; + LPC_RGU->RESET_CTRL0 = 0; + + /* Wait until reset is performed */ + while(1) { + if (LPC_RGU->RESET_ACTIVE_STATUS0 & (1 << 22)) + break; + } + + /* Reset MAC DMA Controller */ + LPC_ETHERNET->DMA_BUS_MODE |= 0x01; + while(LPC_ETHERNET->DMA_BUS_MODE & 0x01); + + phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */ + + for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */ + regv = phy_read(PHY_REG_BMCR); + if(regv < 0 || tout == 0) { + return -1; /* Error */ + } + if(!(regv & PHY_BMCR_RESET)) { + break; /* Reset complete. */ + } + } + + phy_id = (phy_read(PHY_REG_IDR1) << 16); + phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0); + + if (phy_id != DP83848C_ID && phy_id != LAN8720_ID) { + error("Unknown Ethernet PHY (%x)", (unsigned int)phy_id); + } + + ethernet_set_link(-1, 0); + + /* Set the Ethernet MAC Address registers */ + ethernet_address(mac); + LPC_ETHERNET->MAC_ADDR0_HIGH = (mac[5] << 8) | mac[4]; + LPC_ETHERNET->MAC_ADDR0_LOW = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0]; + + txdscr_init(); /* initialize DMA TX Descriptor */ + rxdscr_init(); /* initialize DMA RX Descriptor */ + + /* Configure Filter */ + LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FRAME_FILTER_PR | MAC_FRAME_FILTER_RA; + + /* Enable Receiver and Transmitter */ + LPC_ETHERNET->MAC_CONFIG |= (MAC_CONFIG_RE | MAC_CONFIG_TE); + + //LPC_ETHERNET->DMA_INT_EN = DMA_INT_EN_NIE | DMA_INT_EN_RIE | DMA_INT_EN_TJE; /* Enable EMAC interrupts. */ + + /* Start Transmission & Receive processes */ + LPC_ETHERNET->DMA_OP_MODE |= (DMA_OP_MODE_SST | DMA_OP_MODE_SSR); + + return 0; } /*---------------------------------------------------------------------------- Ethernet Device Uninitialize *----------------------------------------------------------------------------*/ -void ethernet_free() { +void ethernet_free() +{ +} + +/*---------------------------------------------------------------------------- + Ethernet write + *----------------------------------------------------------------------------*/ +int ethernet_write(const char *data, int slen) +{ + if (slen > ETH_FRAG_SIZE) + return -1; + + txdesc[TxDescIndex].Ctrl = slen; + memcpy((void *)txdesc[TxDescIndex].BufAddr1, data, slen); + return slen; } -// if(TxProduceIndex == TxConsumeIndex) buffer array is empty -// if(TxProduceIndex == TxConsumeIndex - 1) buffer is full, should not fill -// TxProduceIndex - The buffer that will/is being fileld by driver, s/w increment -// TxConsumeIndex - The buffer that will/is beign sent by hardware +/*---------------------------------------------------------------------------- + Ethernet Send + *----------------------------------------------------------------------------*/ +int ethernet_send() +{ + int s = txdesc[TxDescIndex].Ctrl; + txdesc[TxDescIndex].Status |= TRDES_OWN_BIT; + LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1; // Wake Up the DMA if it's in Suspended Mode + TxDescIndex++; + if (TxDescIndex == NUM_TX_FRAG) + TxDescIndex = 0; -int ethernet_write(const char *data, int slen) { - return -1; + return s; } -int ethernet_send() { - return -1; +/*---------------------------------------------------------------------------- + Ethernet receive + *----------------------------------------------------------------------------*/ +int ethernet_receive() +{ + int i, slen = 0; + for (i = RxDescIndex;; i++) { + if (rxdesc[i].Status & TRDES_OWN_BIT) + return (slen - RxOffset); + else + slen += (rxdesc[i].Status >> 16) & 0x03FFF; + } + return 0; } -// RxConsmeIndex - The index of buffer the driver will/is reading from. Driver should inc once read -// RxProduceIndex - The index of buffer that will/is being filled by MAC. H/w will inc once rxd -// -// if(RxConsumeIndex == RxProduceIndex) buffer array is empty -// if(RxConsumeIndex == RxProduceIndex + 1) buffer array is full + +/*---------------------------------------------------------------------------- + Ethernet read + *----------------------------------------------------------------------------*/ +int ethernet_read(char *data, int dlen) +{ + int copylen; + uint32_t *pSrc = (uint32_t *)rxdesc[RxDescIndex].BufAddr1; + copylen = (rxdesc[RxDescIndex].Status >> 16) & 0x03FFF; + if (rxdesc[RxDescIndex].Status & TRDES_OWN_BIT || (dlen + RxOffset) > copylen) + return -1; -// Recevies an arrived ethernet packet. -// Receiving an ethernet packet will drop the last received ethernet packet -// and make a new ethernet packet ready to read. -// Returns size of packet, else 0 if nothing to receive - -// We read from RxConsumeIndex from position rx_consume_offset -// if rx_consume_offset < 0, then we have not recieved the RxConsumeIndex packet for reading -// rx_consume_offset = -1 // no frame -// rx_consume_offset = 0 // start of frame -// Assumption: A fragment should alway be a whole frame - -int ethernet_receive() { - return -1; + if ((dlen + RxOffset) == copylen) { + memcpy(&pSrc[RxOffset], data, copylen); + rxdesc[RxDescIndex].Status = TRDES_OWN_BIT; + RxDescIndex++; + RxOffset = 0; + if (RxDescIndex == NUM_RX_FRAG) + RxDescIndex = 0; + } else if ((dlen + RxOffset) < copylen) { + copylen = dlen; + memcpy(&pSrc[RxOffset], data, copylen); + RxOffset += dlen; + } + return copylen; } -// Read from an recevied ethernet packet. -// After receive returnd a number bigger than 0 it is -// possible to read bytes from this packet. -// Read will write up to size bytes into data. -// It is possible to use read multible times. -// Each time read will start reading after the last read byte before. +int ethernet_link(void) +{ + + if (phy_id == DP83848C_ID) { + return (phy_read(PHY_REG_STS) & PHY_STS_LINK); + } else { // LAN8720_ID + return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK); + } +} -int ethernet_read(char *data, int dlen) { +static int phy_write(unsigned int PhyReg, unsigned short Data) +{ + unsigned int timeOut; + + while(LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY); + LPC_ETHERNET->MAC_MII_ADDR = (DP83848C_DEF_ADR<<11) | (PhyReg<<6) | MII_WRITE; + LPC_ETHERNET->MAC_MII_DATA = Data; + LPC_ETHERNET->MAC_MII_ADDR |= MIND_BUSY; // Start PHY Write Cycle + + /* Wait utill operation completed */ + for (timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) { + if ((LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY) == 0) { + break; + } + } + return -1; } -int ethernet_link(void) { +static int phy_read(unsigned int PhyReg) +{ + unsigned int timeOut; + + while(LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY); + LPC_ETHERNET->MAC_MII_ADDR = (DP83848C_DEF_ADR<<11) | (PhyReg<<6) | MII_READ; + LPC_ETHERNET->MAC_MII_ADDR |= MIND_BUSY; + + for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */ + if((LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY) == 0) { + return LPC_ETHERNET->MAC_MII_DATA; /* Return a 16-bit value. */ + } + } + return -1; } -void ethernet_address(char *mac) { +static void txdscr_init() +{ + int i; + + for(i = 0; i < NUM_TX_FRAG; i++) { + txdesc[i].Status = TX_LAST_SEGM | TX_FIRST_SEGM;; + txdesc[i].Ctrl = 0; + txdesc[i].BufAddr1 = (uint32_t)&txbuf[i]; + if (i == (NUM_RX_FRAG - 1)) { + txdesc[i].Status |= TX_END_RING; + } + } + + LPC_ETHERNET->DMA_TRANS_DES_ADDR = (uint32_t)txdesc; /* Set EMAC Transmit Descriptor Registers. */ +} + + +static void rxdscr_init() +{ + int i; + + for(i = 0; i < NUM_RX_FRAG; i++) { + rxdesc[i].Status = TRDES_OWN_BIT; + rxdesc[i].Ctrl = ETH_FRAG_SIZE; + rxdesc[i].BufAddr1 = (uint32_t)&rxbuf[i]; + if (i == (NUM_RX_FRAG - 1)) { + rxdesc[i].Ctrl |= RX_END_RING; + } + } + + LPC_ETHERNET->DMA_REC_DES_ADDR = (uint32_t)rxdesc; /* Set EMAC Receive Descriptor Registers. */ +} + +void ethernet_address(char *mac) +{ + mbed_mac_address(mac); } -void ethernet_set_link(int speed, int duplex) { +void ethernet_set_link(int speed, int duplex) +{ + volatile unsigned short phy_data; + int tout; + + if((speed < 0) || (speed > 1)) { + + phy_data = PHY_AUTO_NEG; + + } else { + + phy_data = (((unsigned short) speed << 13) | + ((unsigned short) duplex << 8)); + } + + phy_write(PHY_REG_BMCR, phy_data); + + for(tout = 100; tout; tout--) { + __NOP(); /* A short delay */ + } + + switch(phy_id) { + case DP83848C_ID: + + phy_data = phy_read(PHY_REG_STS); + + if(phy_data & PHY_STS_DUPLEX) { + /* Full duplex is enabled. */ + LPC_ETHERNET->MAC_CONFIG |= MAC_DUPLEX_MODE; + } else { + LPC_ETHERNET->MAC_CONFIG &= ~MAC_DUPLEX_MODE; + } + + if(phy_data & PHY_STS_SPEED) { + LPC_ETHERNET->MAC_CONFIG &= ~SUPP_SPEED; + } else { + LPC_ETHERNET->MAC_CONFIG |= SUPP_SPEED; + } + break; + + case LAN8720_ID: + + for(tout = 100; tout; tout--) { + phy_data = phy_read(PHY_REG_BMSR); + if (phy_data & PHY_STS_DUPLEX) + break; + } + + if (phy_data & PHY_STS_DUPLEX) { + /* Full duplex is enabled. */ + LPC_ETHERNET->MAC_CONFIG |= MAC_DUPLEX_MODE; + } else { + LPC_ETHERNET->MAC_CONFIG &= ~MAC_DUPLEX_MODE; + } + + if(phy_data & PHY_STS_SPEED) { + LPC_ETHERNET->MAC_CONFIG &= ~SUPP_SPEED; + } else { + LPC_ETHERNET->MAC_CONFIG |= SUPP_SPEED; + } + break; + } } +