Fawwaz Nadzmy / mbed-dev

Fork of mbed-dev by mbed official

Committer:
bogdanm
Date:
Thu Oct 01 15:25:22 2015 +0300
Revision:
0:9b334a45a8ff
Child:
144:ef7eb2e8f9f7
Initial commit on mbed-dev

Replaces mbed-src (now inactive)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 0:9b334a45a8ff 1 /* mbed Microcontroller Library
bogdanm 0:9b334a45a8ff 2 * Copyright (c) 2006-2015 ARM Limited
bogdanm 0:9b334a45a8ff 3 *
bogdanm 0:9b334a45a8ff 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 0:9b334a45a8ff 5 * you may not use this file except in compliance with the License.
bogdanm 0:9b334a45a8ff 6 * You may obtain a copy of the License at
bogdanm 0:9b334a45a8ff 7 *
bogdanm 0:9b334a45a8ff 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 0:9b334a45a8ff 9 *
bogdanm 0:9b334a45a8ff 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 0:9b334a45a8ff 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 0:9b334a45a8ff 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 0:9b334a45a8ff 13 * See the License for the specific language governing permissions and
bogdanm 0:9b334a45a8ff 14 * limitations under the License.
bogdanm 0:9b334a45a8ff 15 *
bogdanm 0:9b334a45a8ff 16 * Contribution by Nitin Bhaskar(nitin.bhaskar.27.09@gmail.com)
bogdanm 0:9b334a45a8ff 17 */
bogdanm 0:9b334a45a8ff 18 #include "ethernet_api.h"
bogdanm 0:9b334a45a8ff 19
bogdanm 0:9b334a45a8ff 20 #include <string.h>
bogdanm 0:9b334a45a8ff 21 #include "cmsis.h"
bogdanm 0:9b334a45a8ff 22 #include "mbed_interface.h"
bogdanm 0:9b334a45a8ff 23 #include "toolchain.h"
bogdanm 0:9b334a45a8ff 24 #include "mbed_error.h"
bogdanm 0:9b334a45a8ff 25 #include "pinmap.h"
bogdanm 0:9b334a45a8ff 26
bogdanm 0:9b334a45a8ff 27 #define NEW_LOGIC 0
bogdanm 0:9b334a45a8ff 28 #define NEW_ETH_BUFFER 0
bogdanm 0:9b334a45a8ff 29
bogdanm 0:9b334a45a8ff 30 #if NEW_ETH_BUFFER
bogdanm 0:9b334a45a8ff 31
bogdanm 0:9b334a45a8ff 32 #define NUM_RX_FRAG 4 // Number of Rx Fragments (== packets)
bogdanm 0:9b334a45a8ff 33 #define NUM_TX_FRAG 3 // Number of Tx Fragments (== packets)
bogdanm 0:9b334a45a8ff 34
bogdanm 0:9b334a45a8ff 35 #define ETH_MAX_FLEN 1536 // Maximum Ethernet Frame Size
bogdanm 0:9b334a45a8ff 36 #define ETH_FRAG_SIZE ETH_MAX_FLEN // Packet Fragment size (same as packet length)
bogdanm 0:9b334a45a8ff 37
bogdanm 0:9b334a45a8ff 38 #else
bogdanm 0:9b334a45a8ff 39
bogdanm 0:9b334a45a8ff 40 // Memfree calculation:
bogdanm 0:9b334a45a8ff 41 // (16 * 1024) - ((2 * 4 * NUM_RX) + (2 * 4 * NUM_RX) + (0x300 * NUM_RX) +
bogdanm 0:9b334a45a8ff 42 // (2 * 4 * NUM_TX) + (1 * 4 * NUM_TX) + (0x300 * NUM_TX)) = 8556
bogdanm 0:9b334a45a8ff 43 /* EMAC Memory Buffer configuration for 16K Ethernet RAM. */
bogdanm 0:9b334a45a8ff 44 #define NUM_RX_FRAG 4 /* Num.of RX Fragments 4*1536= 6.0kB */
bogdanm 0:9b334a45a8ff 45 #define NUM_TX_FRAG 3 /* Num.of TX Fragments 3*1536= 4.6kB */
bogdanm 0:9b334a45a8ff 46 //#define ETH_FRAG_SIZE 1536 /* Packet Fragment size 1536 Bytes */
bogdanm 0:9b334a45a8ff 47
bogdanm 0:9b334a45a8ff 48 //#define ETH_MAX_FLEN 1536 /* Max. Ethernet Frame Size */
bogdanm 0:9b334a45a8ff 49 #define ETH_FRAG_SIZE 0x300 /* Packet Fragment size 1536/2 Bytes */
bogdanm 0:9b334a45a8ff 50 #define ETH_MAX_FLEN 0x300 /* Max. Ethernet Frame Size */
bogdanm 0:9b334a45a8ff 51
bogdanm 0:9b334a45a8ff 52 const int ethernet_MTU_SIZE = 0x300;
bogdanm 0:9b334a45a8ff 53
bogdanm 0:9b334a45a8ff 54 #endif
bogdanm 0:9b334a45a8ff 55
bogdanm 0:9b334a45a8ff 56 #define ETHERNET_ADDR_SIZE 6
bogdanm 0:9b334a45a8ff 57
bogdanm 0:9b334a45a8ff 58 /* Descriptors Fields bits */
bogdanm 0:9b334a45a8ff 59 #define TRDES_OWN_BIT (1U<<31) /* Own bit in RDES0 & TDES0 */
bogdanm 0:9b334a45a8ff 60 #define RX_END_RING (1<<15) /* Receive End of Ring bit in RDES1 */
bogdanm 0:9b334a45a8ff 61 #define RX_NXTDESC_FLAG (1<<14) /* Second Address Chained bit in RDES1 */
bogdanm 0:9b334a45a8ff 62 #define TX_LAST_SEGM (1<<29) /* Last Segment bit in TDES0 */
bogdanm 0:9b334a45a8ff 63 #define TX_FIRST_SEGM (1<<28) /* First Segment bit in TDES0 */
bogdanm 0:9b334a45a8ff 64 #define TX_END_RING (1<<21) /* Transmit End of Ring bit in TDES0 */
bogdanm 0:9b334a45a8ff 65 #define TX_NXTDESC_FLAG (1<<20) /* Second Address Chained bit in TDES0 */
bogdanm 0:9b334a45a8ff 66
bogdanm 0:9b334a45a8ff 67 PACKED struct RX_DESC_TypeDef { /* RX Descriptor struct */
bogdanm 0:9b334a45a8ff 68 unsigned int Status;
bogdanm 0:9b334a45a8ff 69 unsigned int Ctrl;
bogdanm 0:9b334a45a8ff 70 unsigned int BufAddr1;
bogdanm 0:9b334a45a8ff 71 unsigned int NextDescAddr;
bogdanm 0:9b334a45a8ff 72 };
bogdanm 0:9b334a45a8ff 73 typedef struct RX_DESC_TypeDef RX_DESC_TypeDef;
bogdanm 0:9b334a45a8ff 74
bogdanm 0:9b334a45a8ff 75 PACKED struct TX_DESC_TypeDef { /* TX Descriptor struct */
bogdanm 0:9b334a45a8ff 76 unsigned int Status;
bogdanm 0:9b334a45a8ff 77 unsigned int Ctrl;
bogdanm 0:9b334a45a8ff 78 unsigned int BufAddr1;
bogdanm 0:9b334a45a8ff 79 unsigned int NextDescAddr;
bogdanm 0:9b334a45a8ff 80 };
bogdanm 0:9b334a45a8ff 81 typedef struct TX_DESC_TypeDef TX_DESC_TypeDef;
bogdanm 0:9b334a45a8ff 82
bogdanm 0:9b334a45a8ff 83 /* ETHMODE RMII SELECT */
bogdanm 0:9b334a45a8ff 84 #define RMII_SELECT 0x04
bogdanm 0:9b334a45a8ff 85 /* define to tell PHY about write operation */
bogdanm 0:9b334a45a8ff 86 #define MII_WRITE (1 << 1)
bogdanm 0:9b334a45a8ff 87 /* define to tell PHY about read operation */
bogdanm 0:9b334a45a8ff 88 #define MII_READ (0 << 1)
bogdanm 0:9b334a45a8ff 89 /* define to enable duplex mode */
bogdanm 0:9b334a45a8ff 90 #define MAC_DUPLEX_MODE (1 << 11)
bogdanm 0:9b334a45a8ff 91
bogdanm 0:9b334a45a8ff 92 /* MAC_FRAME_FILTER register bit defines */
bogdanm 0:9b334a45a8ff 93 #define MAC_FRAME_FILTER_PR (1 << 0) /* Promiscuous Mode */
bogdanm 0:9b334a45a8ff 94 #define MAC_FRAME_FILTER_RA (1UL << 31) /* Receive all */
bogdanm 0:9b334a45a8ff 95
bogdanm 0:9b334a45a8ff 96 /* MAC_CONFIG register bit defines */
bogdanm 0:9b334a45a8ff 97 #define MAC_CONFIG_RE (1 << 2) /* Receiver enable */
bogdanm 0:9b334a45a8ff 98 #define MAC_CONFIG_TE (1 << 3) /* Transmitter Enable */
bogdanm 0:9b334a45a8ff 99
bogdanm 0:9b334a45a8ff 100 /* DMA_OP_MODE register bit defines */
bogdanm 0:9b334a45a8ff 101 #define DMA_OP_MODE_SSR (1 << 1) /* Start/stop receive */
bogdanm 0:9b334a45a8ff 102 #define DMA_OP_MODE_SST (1 << 13) /* Start/Stop Transmission Command */
bogdanm 0:9b334a45a8ff 103
bogdanm 0:9b334a45a8ff 104 /* DMA_INT_EN register bit defines */
bogdanm 0:9b334a45a8ff 105 #define DMA_INT_EN_TIE (1 << 0) /* Transmit interrupt enable */
bogdanm 0:9b334a45a8ff 106 #define DMA_INT_EN_TSE (1 << 1) /* Transmit stopped enable */
bogdanm 0:9b334a45a8ff 107 #define DMA_INT_EN_TUE (1 << 2) /* Transmit buffer unavailable enable */
bogdanm 0:9b334a45a8ff 108 #define DMA_INT_EN_TJE (1 << 3) /* Transmit jabber timeout enable */
bogdanm 0:9b334a45a8ff 109 #define DMA_INT_EN_OVE (1 << 4) /* Overflow interrupt enable */
bogdanm 0:9b334a45a8ff 110 #define DMA_INT_EN_UNE (1 << 5) /* Underflow interrupt enable */
bogdanm 0:9b334a45a8ff 111 #define DMA_INT_EN_RIE (1 << 6) /* Receive interrupt enable */
bogdanm 0:9b334a45a8ff 112 #define DMA_INT_EN_RUE (1 << 7) /* Receive buffer unavailable enable */
bogdanm 0:9b334a45a8ff 113 #define DMA_INT_EN_RSE (1 << 8) /* Received stopped enable */
bogdanm 0:9b334a45a8ff 114 #define DMA_INT_EN_RWE (1 << 9) /* Receive watchdog timeout enable */
bogdanm 0:9b334a45a8ff 115 #define DMA_INT_EN_ETE (1 << 10) /* Early transmit interrupt enable */
bogdanm 0:9b334a45a8ff 116 #define DMA_INT_EN_FBE (1 << 13) /* Fatal bus error enable */
bogdanm 0:9b334a45a8ff 117 #define DMA_INT_EN_ERE (1 << 14) /* Early receive interrupt enable */
bogdanm 0:9b334a45a8ff 118 #define DMA_INT_EN_AIE (1 << 15) /* Abnormal interrupt summary enable */
bogdanm 0:9b334a45a8ff 119 #define DMA_INT_EN_NIE (1 << 16) /* Normal interrupt summary enable */
bogdanm 0:9b334a45a8ff 120
bogdanm 0:9b334a45a8ff 121
bogdanm 0:9b334a45a8ff 122
bogdanm 0:9b334a45a8ff 123 /* PHY Support Register */
bogdanm 0:9b334a45a8ff 124 #define SUPP_SPEED 0x00004000 /* Reduced MII Logic Current Speed */
bogdanm 0:9b334a45a8ff 125 //#define SUPP_RES_RMII 0x00000800 /* Reset Reduced MII Logic */
bogdanm 0:9b334a45a8ff 126 #define SUPP_RES_RMII 0x00000000 /* Reset Reduced MII Logic */
bogdanm 0:9b334a45a8ff 127
bogdanm 0:9b334a45a8ff 128 /* MII Management Command Register */
bogdanm 0:9b334a45a8ff 129 #define MCMD_READ 0x00000001 /* MII Read */
bogdanm 0:9b334a45a8ff 130 #define MCMD_SCAN 0x00000002 /* MII Scan continuously */
bogdanm 0:9b334a45a8ff 131
bogdanm 0:9b334a45a8ff 132 #define MII_WR_TOUT 0x00050000 /* MII Write timeout count */
bogdanm 0:9b334a45a8ff 133 #define MII_RD_TOUT 0x00050000 /* MII Read timeout count */
bogdanm 0:9b334a45a8ff 134
bogdanm 0:9b334a45a8ff 135 /* MII Management Address Register */
bogdanm 0:9b334a45a8ff 136 #define MADR_REG_ADR 0x0000001F /* MII Register Address Mask */
bogdanm 0:9b334a45a8ff 137 #define MADR_PHY_ADR 0x00001F00 /* PHY Address Mask */
bogdanm 0:9b334a45a8ff 138
bogdanm 0:9b334a45a8ff 139 /* MII Management Indicators Register */
bogdanm 0:9b334a45a8ff 140 #define MIND_BUSY 0x00000001 /* MII is Busy */
bogdanm 0:9b334a45a8ff 141 #define MIND_SCAN 0x00000002 /* MII Scanning in Progress */
bogdanm 0:9b334a45a8ff 142 #define MIND_NOT_VAL 0x00000004 /* MII Read Data not valid */
bogdanm 0:9b334a45a8ff 143 #define MIND_MII_LINK_FAIL 0x00000008 /* MII Link Failed */
bogdanm 0:9b334a45a8ff 144
bogdanm 0:9b334a45a8ff 145 /* DP83848C PHY Registers */
bogdanm 0:9b334a45a8ff 146 #define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */
bogdanm 0:9b334a45a8ff 147 #define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */
bogdanm 0:9b334a45a8ff 148 #define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */
bogdanm 0:9b334a45a8ff 149 #define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */
bogdanm 0:9b334a45a8ff 150 #define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */
bogdanm 0:9b334a45a8ff 151 #define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */
bogdanm 0:9b334a45a8ff 152 #define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */
bogdanm 0:9b334a45a8ff 153 #define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */
bogdanm 0:9b334a45a8ff 154
bogdanm 0:9b334a45a8ff 155 /* PHY Extended Registers */
bogdanm 0:9b334a45a8ff 156 #define PHY_REG_STS 0x10 /* Status Register */
bogdanm 0:9b334a45a8ff 157 #define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */
bogdanm 0:9b334a45a8ff 158 #define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */
bogdanm 0:9b334a45a8ff 159 #define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */
bogdanm 0:9b334a45a8ff 160 #define PHY_REG_RECR 0x15 /* Receive Error Counter */
bogdanm 0:9b334a45a8ff 161 #define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */
bogdanm 0:9b334a45a8ff 162 #define PHY_REG_RBR 0x17 /* RMII and Bypass Register */
bogdanm 0:9b334a45a8ff 163 #define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */
bogdanm 0:9b334a45a8ff 164 #define PHY_REG_PHYCR 0x19 /* PHY Control Register */
bogdanm 0:9b334a45a8ff 165 #define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */
bogdanm 0:9b334a45a8ff 166 #define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */
bogdanm 0:9b334a45a8ff 167 #define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */
bogdanm 0:9b334a45a8ff 168
bogdanm 0:9b334a45a8ff 169 #define PHY_REG_SCSR 0x1F /* PHY Special Control/Status Register */
bogdanm 0:9b334a45a8ff 170
bogdanm 0:9b334a45a8ff 171 #define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */
bogdanm 0:9b334a45a8ff 172 #define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */
bogdanm 0:9b334a45a8ff 173 #define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */
bogdanm 0:9b334a45a8ff 174 #define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */
bogdanm 0:9b334a45a8ff 175 #define PHY_AUTO_NEG 0x1000 /* Select Auto Negotiation */
bogdanm 0:9b334a45a8ff 176
bogdanm 0:9b334a45a8ff 177 #define DP83848C_DEF_ADR 0x01 /* Default PHY device address */
bogdanm 0:9b334a45a8ff 178 #define DP83848C_ID 0x20005C90 /* PHY Identifier - DP83848C */
bogdanm 0:9b334a45a8ff 179
bogdanm 0:9b334a45a8ff 180 #define LAN8720_ID 0x0007C0F0 /* PHY Identifier - LAN8720 */
bogdanm 0:9b334a45a8ff 181
bogdanm 0:9b334a45a8ff 182 #define PHY_STS_LINK 0x0001 /* PHY Status Link Mask */
bogdanm 0:9b334a45a8ff 183 #define PHY_STS_SPEED 0x0002 /* PHY Status Speed Mask */
bogdanm 0:9b334a45a8ff 184 #define PHY_STS_DUPLEX 0x0004 /* PHY Status Duplex Mask */
bogdanm 0:9b334a45a8ff 185
bogdanm 0:9b334a45a8ff 186 #define PHY_BMCR_RESET 0x8000 /* PHY Reset */
bogdanm 0:9b334a45a8ff 187
bogdanm 0:9b334a45a8ff 188 #define PHY_BMSR_LINK 0x0004 /* PHY BMSR Link valid */
bogdanm 0:9b334a45a8ff 189
bogdanm 0:9b334a45a8ff 190 #define PHY_SCSR_100MBIT 0x0008 /* Speed: 1=100 MBit, 0=10Mbit */
bogdanm 0:9b334a45a8ff 191 #define PHY_SCSR_DUPLEX 0x0010 /* PHY Duplex Mask */
bogdanm 0:9b334a45a8ff 192
bogdanm 0:9b334a45a8ff 193 static int phy_read(unsigned int PhyReg);
bogdanm 0:9b334a45a8ff 194 static int phy_write(unsigned int PhyReg, unsigned short Data);
bogdanm 0:9b334a45a8ff 195
bogdanm 0:9b334a45a8ff 196 static void txdscr_init(void);
bogdanm 0:9b334a45a8ff 197 static void rxdscr_init(void);
bogdanm 0:9b334a45a8ff 198
bogdanm 0:9b334a45a8ff 199 #if defined (__ICCARM__)
bogdanm 0:9b334a45a8ff 200 # define AHBSRAM1
bogdanm 0:9b334a45a8ff 201 #elif defined(TOOLCHAIN_GCC_CR)
bogdanm 0:9b334a45a8ff 202 # define AHBSRAM1 __attribute__((section(".data.$RamPeriph32")))
bogdanm 0:9b334a45a8ff 203 #else
bogdanm 0:9b334a45a8ff 204 # define AHBSRAM1 __attribute__((section("AHBSRAM1"),aligned))
bogdanm 0:9b334a45a8ff 205 #endif
bogdanm 0:9b334a45a8ff 206
bogdanm 0:9b334a45a8ff 207 AHBSRAM1 volatile uint8_t rxbuf[NUM_RX_FRAG][ETH_FRAG_SIZE];
bogdanm 0:9b334a45a8ff 208 AHBSRAM1 volatile uint8_t txbuf[NUM_TX_FRAG][ETH_FRAG_SIZE];
bogdanm 0:9b334a45a8ff 209 AHBSRAM1 volatile RX_DESC_TypeDef rxdesc[NUM_RX_FRAG];
bogdanm 0:9b334a45a8ff 210 AHBSRAM1 volatile TX_DESC_TypeDef txdesc[NUM_TX_FRAG];
bogdanm 0:9b334a45a8ff 211
bogdanm 0:9b334a45a8ff 212 #ifndef min
bogdanm 0:9b334a45a8ff 213 #define min(x, y) (((x)<(y))?(x):(y))
bogdanm 0:9b334a45a8ff 214 #endif
bogdanm 0:9b334a45a8ff 215
bogdanm 0:9b334a45a8ff 216 static uint32_t phy_id = 0;
bogdanm 0:9b334a45a8ff 217 static uint32_t TxDescIndex = 0;
bogdanm 0:9b334a45a8ff 218 static uint32_t RxDescIndex = 0;
bogdanm 0:9b334a45a8ff 219 static uint32_t RxOffset = 0;
bogdanm 0:9b334a45a8ff 220
bogdanm 0:9b334a45a8ff 221 /*----------------------------------------------------------------------------
bogdanm 0:9b334a45a8ff 222 Ethernet Device initialize
bogdanm 0:9b334a45a8ff 223 *----------------------------------------------------------------------------*/
bogdanm 0:9b334a45a8ff 224 int ethernet_init()
bogdanm 0:9b334a45a8ff 225 {
bogdanm 0:9b334a45a8ff 226 int regv, tout;
bogdanm 0:9b334a45a8ff 227 char mac[ETHERNET_ADDR_SIZE];
bogdanm 0:9b334a45a8ff 228
bogdanm 0:9b334a45a8ff 229 pin_function(PC_0, (SCU_MODE_INACT | FUNC3)); /* Enable ENET RX CLK */
bogdanm 0:9b334a45a8ff 230 pin_function(P1_19, (SCU_MODE_INACT | FUNC0)); /* Enable ENET TX CLK */
bogdanm 0:9b334a45a8ff 231
bogdanm 0:9b334a45a8ff 232 /* Ethernet pinmuxing */
bogdanm 0:9b334a45a8ff 233 pin_function(P2_0, SCU_PINIO_FAST | FUNC7); /* ENET_MDC */
bogdanm 0:9b334a45a8ff 234 pin_function(P1_17, SCU_PINIO_FAST | FUNC3); /* ENET_MDIO */
bogdanm 0:9b334a45a8ff 235 pin_function(P1_18, SCU_PINIO_FAST | FUNC3); /* ENET_TXD0 */
bogdanm 0:9b334a45a8ff 236 pin_function(P1_20, SCU_PINIO_FAST | FUNC3); /* ENET_TXD1 */
bogdanm 0:9b334a45a8ff 237 pin_function(P1_19, SCU_PINIO_FAST | FUNC0); /* ENET_REF */
bogdanm 0:9b334a45a8ff 238 pin_function(P0_1, SCU_PINIO_FAST | FUNC6); /* ENET_TX_EN */
bogdanm 0:9b334a45a8ff 239 pin_function(P1_15, SCU_PINIO_FAST | FUNC3); /* ENET_RXD0 */
bogdanm 0:9b334a45a8ff 240 pin_function(P0_0, SCU_PINIO_FAST | FUNC2); /* ENET_RXD1 */
bogdanm 0:9b334a45a8ff 241 pin_function(P1_16, SCU_PINIO_FAST | FUNC3); /* ENET_CRS */
bogdanm 0:9b334a45a8ff 242 pin_function(PC_9, SCU_PINIO_FAST | FUNC3); /* ENET_RX_ER */
bogdanm 0:9b334a45a8ff 243 pin_function(P1_16, SCU_PINIO_FAST | FUNC7); /* ENET_RXDV */
bogdanm 0:9b334a45a8ff 244
bogdanm 0:9b334a45a8ff 245 LPC_CREG->CREG6 |= RMII_SELECT;
bogdanm 0:9b334a45a8ff 246
bogdanm 0:9b334a45a8ff 247 /* perform RGU soft reset */
bogdanm 0:9b334a45a8ff 248 LPC_RGU->RESET_CTRL0 = 1 << 22;
bogdanm 0:9b334a45a8ff 249 LPC_RGU->RESET_CTRL0 = 0;
bogdanm 0:9b334a45a8ff 250
bogdanm 0:9b334a45a8ff 251 /* Wait until reset is performed */
bogdanm 0:9b334a45a8ff 252 while(1) {
bogdanm 0:9b334a45a8ff 253 if (LPC_RGU->RESET_ACTIVE_STATUS0 & (1 << 22))
bogdanm 0:9b334a45a8ff 254 break;
bogdanm 0:9b334a45a8ff 255 }
bogdanm 0:9b334a45a8ff 256
bogdanm 0:9b334a45a8ff 257 /* Reset MAC DMA Controller */
bogdanm 0:9b334a45a8ff 258 LPC_ETHERNET->DMA_BUS_MODE |= 0x01;
bogdanm 0:9b334a45a8ff 259 while(LPC_ETHERNET->DMA_BUS_MODE & 0x01);
bogdanm 0:9b334a45a8ff 260
bogdanm 0:9b334a45a8ff 261 phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */
bogdanm 0:9b334a45a8ff 262
bogdanm 0:9b334a45a8ff 263 for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */
bogdanm 0:9b334a45a8ff 264 regv = phy_read(PHY_REG_BMCR);
bogdanm 0:9b334a45a8ff 265 if(regv < 0 || tout == 0) {
bogdanm 0:9b334a45a8ff 266 return -1; /* Error */
bogdanm 0:9b334a45a8ff 267 }
bogdanm 0:9b334a45a8ff 268 if(!(regv & PHY_BMCR_RESET)) {
bogdanm 0:9b334a45a8ff 269 break; /* Reset complete. */
bogdanm 0:9b334a45a8ff 270 }
bogdanm 0:9b334a45a8ff 271 }
bogdanm 0:9b334a45a8ff 272
bogdanm 0:9b334a45a8ff 273 phy_id = (phy_read(PHY_REG_IDR1) << 16);
bogdanm 0:9b334a45a8ff 274 phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);
bogdanm 0:9b334a45a8ff 275
bogdanm 0:9b334a45a8ff 276 if (phy_id != DP83848C_ID && phy_id != LAN8720_ID) {
bogdanm 0:9b334a45a8ff 277 error("Unknown Ethernet PHY (%x)", (unsigned int)phy_id);
bogdanm 0:9b334a45a8ff 278 }
bogdanm 0:9b334a45a8ff 279
bogdanm 0:9b334a45a8ff 280 ethernet_set_link(-1, 0);
bogdanm 0:9b334a45a8ff 281
bogdanm 0:9b334a45a8ff 282 /* Set the Ethernet MAC Address registers */
bogdanm 0:9b334a45a8ff 283 ethernet_address(mac);
bogdanm 0:9b334a45a8ff 284 LPC_ETHERNET->MAC_ADDR0_HIGH = (mac[5] << 8) | mac[4];
bogdanm 0:9b334a45a8ff 285 LPC_ETHERNET->MAC_ADDR0_LOW = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0];
bogdanm 0:9b334a45a8ff 286
bogdanm 0:9b334a45a8ff 287 txdscr_init(); /* initialize DMA TX Descriptor */
bogdanm 0:9b334a45a8ff 288 rxdscr_init(); /* initialize DMA RX Descriptor */
bogdanm 0:9b334a45a8ff 289
bogdanm 0:9b334a45a8ff 290 /* Configure Filter */
bogdanm 0:9b334a45a8ff 291 LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FRAME_FILTER_PR | MAC_FRAME_FILTER_RA;
bogdanm 0:9b334a45a8ff 292
bogdanm 0:9b334a45a8ff 293 /* Enable Receiver and Transmitter */
bogdanm 0:9b334a45a8ff 294 LPC_ETHERNET->MAC_CONFIG |= (MAC_CONFIG_RE | MAC_CONFIG_TE);
bogdanm 0:9b334a45a8ff 295
bogdanm 0:9b334a45a8ff 296 //LPC_ETHERNET->DMA_INT_EN = DMA_INT_EN_NIE | DMA_INT_EN_RIE | DMA_INT_EN_TJE; /* Enable EMAC interrupts. */
bogdanm 0:9b334a45a8ff 297
bogdanm 0:9b334a45a8ff 298 /* Start Transmission & Receive processes */
bogdanm 0:9b334a45a8ff 299 LPC_ETHERNET->DMA_OP_MODE |= (DMA_OP_MODE_SST | DMA_OP_MODE_SSR);
bogdanm 0:9b334a45a8ff 300
bogdanm 0:9b334a45a8ff 301 return 0;
bogdanm 0:9b334a45a8ff 302 }
bogdanm 0:9b334a45a8ff 303
bogdanm 0:9b334a45a8ff 304 /*----------------------------------------------------------------------------
bogdanm 0:9b334a45a8ff 305 Ethernet Device Uninitialize
bogdanm 0:9b334a45a8ff 306 *----------------------------------------------------------------------------*/
bogdanm 0:9b334a45a8ff 307 void ethernet_free()
bogdanm 0:9b334a45a8ff 308 {
bogdanm 0:9b334a45a8ff 309 }
bogdanm 0:9b334a45a8ff 310
bogdanm 0:9b334a45a8ff 311 /*----------------------------------------------------------------------------
bogdanm 0:9b334a45a8ff 312 Ethernet write
bogdanm 0:9b334a45a8ff 313 *----------------------------------------------------------------------------*/
bogdanm 0:9b334a45a8ff 314 int ethernet_write(const char *data, int slen)
bogdanm 0:9b334a45a8ff 315 {
bogdanm 0:9b334a45a8ff 316 if (slen > ETH_FRAG_SIZE)
bogdanm 0:9b334a45a8ff 317 return -1;
bogdanm 0:9b334a45a8ff 318
bogdanm 0:9b334a45a8ff 319 txdesc[TxDescIndex].Ctrl = slen;
bogdanm 0:9b334a45a8ff 320 memcpy((void *)txdesc[TxDescIndex].BufAddr1, data, slen);
bogdanm 0:9b334a45a8ff 321 return slen;
bogdanm 0:9b334a45a8ff 322 }
bogdanm 0:9b334a45a8ff 323
bogdanm 0:9b334a45a8ff 324 /*----------------------------------------------------------------------------
bogdanm 0:9b334a45a8ff 325 Ethernet Send
bogdanm 0:9b334a45a8ff 326 *----------------------------------------------------------------------------*/
bogdanm 0:9b334a45a8ff 327 int ethernet_send()
bogdanm 0:9b334a45a8ff 328 {
bogdanm 0:9b334a45a8ff 329 int s = txdesc[TxDescIndex].Ctrl;
bogdanm 0:9b334a45a8ff 330 txdesc[TxDescIndex].Status |= TRDES_OWN_BIT;
bogdanm 0:9b334a45a8ff 331 LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1; // Wake Up the DMA if it's in Suspended Mode
bogdanm 0:9b334a45a8ff 332 TxDescIndex++;
bogdanm 0:9b334a45a8ff 333 if (TxDescIndex == NUM_TX_FRAG)
bogdanm 0:9b334a45a8ff 334 TxDescIndex = 0;
bogdanm 0:9b334a45a8ff 335
bogdanm 0:9b334a45a8ff 336 return s;
bogdanm 0:9b334a45a8ff 337 }
bogdanm 0:9b334a45a8ff 338
bogdanm 0:9b334a45a8ff 339 /*----------------------------------------------------------------------------
bogdanm 0:9b334a45a8ff 340 Ethernet receive
bogdanm 0:9b334a45a8ff 341 *----------------------------------------------------------------------------*/
bogdanm 0:9b334a45a8ff 342 int ethernet_receive()
bogdanm 0:9b334a45a8ff 343 {
bogdanm 0:9b334a45a8ff 344 int i, slen = 0;
bogdanm 0:9b334a45a8ff 345 for (i = RxDescIndex;; i++) {
bogdanm 0:9b334a45a8ff 346 if (rxdesc[i].Status & TRDES_OWN_BIT)
bogdanm 0:9b334a45a8ff 347 return (slen - RxOffset);
bogdanm 0:9b334a45a8ff 348 else
bogdanm 0:9b334a45a8ff 349 slen += (rxdesc[i].Status >> 16) & 0x03FFF;
bogdanm 0:9b334a45a8ff 350 }
bogdanm 0:9b334a45a8ff 351 return 0;
bogdanm 0:9b334a45a8ff 352 }
bogdanm 0:9b334a45a8ff 353
bogdanm 0:9b334a45a8ff 354
bogdanm 0:9b334a45a8ff 355 /*----------------------------------------------------------------------------
bogdanm 0:9b334a45a8ff 356 Ethernet read
bogdanm 0:9b334a45a8ff 357 *----------------------------------------------------------------------------*/
bogdanm 0:9b334a45a8ff 358 int ethernet_read(char *data, int dlen)
bogdanm 0:9b334a45a8ff 359 {
bogdanm 0:9b334a45a8ff 360 int copylen;
bogdanm 0:9b334a45a8ff 361 uint32_t *pSrc = (uint32_t *)rxdesc[RxDescIndex].BufAddr1;
bogdanm 0:9b334a45a8ff 362 copylen = (rxdesc[RxDescIndex].Status >> 16) & 0x03FFF;
bogdanm 0:9b334a45a8ff 363 if (rxdesc[RxDescIndex].Status & TRDES_OWN_BIT || (dlen + RxOffset) > copylen)
bogdanm 0:9b334a45a8ff 364 return -1;
bogdanm 0:9b334a45a8ff 365
bogdanm 0:9b334a45a8ff 366 if ((dlen + RxOffset) == copylen) {
bogdanm 0:9b334a45a8ff 367 memcpy(&pSrc[RxOffset], data, copylen);
bogdanm 0:9b334a45a8ff 368 rxdesc[RxDescIndex].Status = TRDES_OWN_BIT;
bogdanm 0:9b334a45a8ff 369 RxDescIndex++;
bogdanm 0:9b334a45a8ff 370 RxOffset = 0;
bogdanm 0:9b334a45a8ff 371 if (RxDescIndex == NUM_RX_FRAG)
bogdanm 0:9b334a45a8ff 372 RxDescIndex = 0;
bogdanm 0:9b334a45a8ff 373 } else if ((dlen + RxOffset) < copylen) {
bogdanm 0:9b334a45a8ff 374 copylen = dlen;
bogdanm 0:9b334a45a8ff 375 memcpy(&pSrc[RxOffset], data, copylen);
bogdanm 0:9b334a45a8ff 376 RxOffset += dlen;
bogdanm 0:9b334a45a8ff 377 }
bogdanm 0:9b334a45a8ff 378 return copylen;
bogdanm 0:9b334a45a8ff 379 }
bogdanm 0:9b334a45a8ff 380
bogdanm 0:9b334a45a8ff 381 int ethernet_link(void)
bogdanm 0:9b334a45a8ff 382 {
bogdanm 0:9b334a45a8ff 383
bogdanm 0:9b334a45a8ff 384 if (phy_id == DP83848C_ID) {
bogdanm 0:9b334a45a8ff 385 return (phy_read(PHY_REG_STS) & PHY_STS_LINK);
bogdanm 0:9b334a45a8ff 386 } else { // LAN8720_ID
bogdanm 0:9b334a45a8ff 387 return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);
bogdanm 0:9b334a45a8ff 388 }
bogdanm 0:9b334a45a8ff 389 }
bogdanm 0:9b334a45a8ff 390
bogdanm 0:9b334a45a8ff 391 static int phy_write(unsigned int PhyReg, unsigned short Data)
bogdanm 0:9b334a45a8ff 392 {
bogdanm 0:9b334a45a8ff 393 unsigned int timeOut;
bogdanm 0:9b334a45a8ff 394
bogdanm 0:9b334a45a8ff 395 while(LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY);
bogdanm 0:9b334a45a8ff 396 LPC_ETHERNET->MAC_MII_ADDR = (DP83848C_DEF_ADR<<11) | (PhyReg<<6) | MII_WRITE;
bogdanm 0:9b334a45a8ff 397 LPC_ETHERNET->MAC_MII_DATA = Data;
bogdanm 0:9b334a45a8ff 398 LPC_ETHERNET->MAC_MII_ADDR |= MIND_BUSY; // Start PHY Write Cycle
bogdanm 0:9b334a45a8ff 399
bogdanm 0:9b334a45a8ff 400 /* Wait utill operation completed */
bogdanm 0:9b334a45a8ff 401 for (timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) {
bogdanm 0:9b334a45a8ff 402 if ((LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY) == 0) {
bogdanm 0:9b334a45a8ff 403 break;
bogdanm 0:9b334a45a8ff 404 }
bogdanm 0:9b334a45a8ff 405 }
bogdanm 0:9b334a45a8ff 406
bogdanm 0:9b334a45a8ff 407 return -1;
bogdanm 0:9b334a45a8ff 408 }
bogdanm 0:9b334a45a8ff 409
bogdanm 0:9b334a45a8ff 410 static int phy_read(unsigned int PhyReg)
bogdanm 0:9b334a45a8ff 411 {
bogdanm 0:9b334a45a8ff 412 unsigned int timeOut;
bogdanm 0:9b334a45a8ff 413
bogdanm 0:9b334a45a8ff 414 while(LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY);
bogdanm 0:9b334a45a8ff 415 LPC_ETHERNET->MAC_MII_ADDR = (DP83848C_DEF_ADR<<11) | (PhyReg<<6) | MII_READ;
bogdanm 0:9b334a45a8ff 416 LPC_ETHERNET->MAC_MII_ADDR |= MIND_BUSY;
bogdanm 0:9b334a45a8ff 417
bogdanm 0:9b334a45a8ff 418 for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */
bogdanm 0:9b334a45a8ff 419 if((LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY) == 0) {
bogdanm 0:9b334a45a8ff 420 return LPC_ETHERNET->MAC_MII_DATA; /* Return a 16-bit value. */
bogdanm 0:9b334a45a8ff 421 }
bogdanm 0:9b334a45a8ff 422 }
bogdanm 0:9b334a45a8ff 423
bogdanm 0:9b334a45a8ff 424 return -1;
bogdanm 0:9b334a45a8ff 425 }
bogdanm 0:9b334a45a8ff 426
bogdanm 0:9b334a45a8ff 427 static void txdscr_init()
bogdanm 0:9b334a45a8ff 428 {
bogdanm 0:9b334a45a8ff 429 int i;
bogdanm 0:9b334a45a8ff 430
bogdanm 0:9b334a45a8ff 431 for(i = 0; i < NUM_TX_FRAG; i++) {
bogdanm 0:9b334a45a8ff 432 txdesc[i].Status = TX_LAST_SEGM | TX_FIRST_SEGM;;
bogdanm 0:9b334a45a8ff 433 txdesc[i].Ctrl = 0;
bogdanm 0:9b334a45a8ff 434 txdesc[i].BufAddr1 = (uint32_t)&txbuf[i];
bogdanm 0:9b334a45a8ff 435 if (i == (NUM_RX_FRAG - 1)) {
bogdanm 0:9b334a45a8ff 436 txdesc[i].Status |= TX_END_RING;
bogdanm 0:9b334a45a8ff 437 }
bogdanm 0:9b334a45a8ff 438 }
bogdanm 0:9b334a45a8ff 439
bogdanm 0:9b334a45a8ff 440 LPC_ETHERNET->DMA_TRANS_DES_ADDR = (uint32_t)txdesc; /* Set EMAC Transmit Descriptor Registers. */
bogdanm 0:9b334a45a8ff 441 }
bogdanm 0:9b334a45a8ff 442
bogdanm 0:9b334a45a8ff 443
bogdanm 0:9b334a45a8ff 444 static void rxdscr_init()
bogdanm 0:9b334a45a8ff 445 {
bogdanm 0:9b334a45a8ff 446 int i;
bogdanm 0:9b334a45a8ff 447
bogdanm 0:9b334a45a8ff 448 for(i = 0; i < NUM_RX_FRAG; i++) {
bogdanm 0:9b334a45a8ff 449 rxdesc[i].Status = TRDES_OWN_BIT;
bogdanm 0:9b334a45a8ff 450 rxdesc[i].Ctrl = ETH_FRAG_SIZE;
bogdanm 0:9b334a45a8ff 451 rxdesc[i].BufAddr1 = (uint32_t)&rxbuf[i];
bogdanm 0:9b334a45a8ff 452 if (i == (NUM_RX_FRAG - 1)) {
bogdanm 0:9b334a45a8ff 453 rxdesc[i].Ctrl |= RX_END_RING;
bogdanm 0:9b334a45a8ff 454 }
bogdanm 0:9b334a45a8ff 455 }
bogdanm 0:9b334a45a8ff 456
bogdanm 0:9b334a45a8ff 457 LPC_ETHERNET->DMA_REC_DES_ADDR = (uint32_t)rxdesc; /* Set EMAC Receive Descriptor Registers. */
bogdanm 0:9b334a45a8ff 458 }
bogdanm 0:9b334a45a8ff 459
bogdanm 0:9b334a45a8ff 460 void ethernet_address(char *mac)
bogdanm 0:9b334a45a8ff 461 {
bogdanm 0:9b334a45a8ff 462 mbed_mac_address(mac);
bogdanm 0:9b334a45a8ff 463 }
bogdanm 0:9b334a45a8ff 464
bogdanm 0:9b334a45a8ff 465 void ethernet_set_link(int speed, int duplex)
bogdanm 0:9b334a45a8ff 466 {
bogdanm 0:9b334a45a8ff 467 volatile unsigned short phy_data;
bogdanm 0:9b334a45a8ff 468 int tout;
bogdanm 0:9b334a45a8ff 469
bogdanm 0:9b334a45a8ff 470 if((speed < 0) || (speed > 1)) {
bogdanm 0:9b334a45a8ff 471
bogdanm 0:9b334a45a8ff 472 phy_data = PHY_AUTO_NEG;
bogdanm 0:9b334a45a8ff 473
bogdanm 0:9b334a45a8ff 474 } else {
bogdanm 0:9b334a45a8ff 475
bogdanm 0:9b334a45a8ff 476 phy_data = (((unsigned short) speed << 13) |
bogdanm 0:9b334a45a8ff 477 ((unsigned short) duplex << 8));
bogdanm 0:9b334a45a8ff 478 }
bogdanm 0:9b334a45a8ff 479
bogdanm 0:9b334a45a8ff 480 phy_write(PHY_REG_BMCR, phy_data);
bogdanm 0:9b334a45a8ff 481
bogdanm 0:9b334a45a8ff 482 for(tout = 100; tout; tout--) {
bogdanm 0:9b334a45a8ff 483 __NOP(); /* A short delay */
bogdanm 0:9b334a45a8ff 484 }
bogdanm 0:9b334a45a8ff 485
bogdanm 0:9b334a45a8ff 486 switch(phy_id) {
bogdanm 0:9b334a45a8ff 487 case DP83848C_ID:
bogdanm 0:9b334a45a8ff 488
bogdanm 0:9b334a45a8ff 489 phy_data = phy_read(PHY_REG_STS);
bogdanm 0:9b334a45a8ff 490
bogdanm 0:9b334a45a8ff 491 if(phy_data & PHY_STS_DUPLEX) {
bogdanm 0:9b334a45a8ff 492 /* Full duplex is enabled. */
bogdanm 0:9b334a45a8ff 493 LPC_ETHERNET->MAC_CONFIG |= MAC_DUPLEX_MODE;
bogdanm 0:9b334a45a8ff 494 } else {
bogdanm 0:9b334a45a8ff 495 LPC_ETHERNET->MAC_CONFIG &= ~MAC_DUPLEX_MODE;
bogdanm 0:9b334a45a8ff 496 }
bogdanm 0:9b334a45a8ff 497
bogdanm 0:9b334a45a8ff 498 if(phy_data & PHY_STS_SPEED) {
bogdanm 0:9b334a45a8ff 499 LPC_ETHERNET->MAC_CONFIG &= ~SUPP_SPEED;
bogdanm 0:9b334a45a8ff 500 } else {
bogdanm 0:9b334a45a8ff 501 LPC_ETHERNET->MAC_CONFIG |= SUPP_SPEED;
bogdanm 0:9b334a45a8ff 502 }
bogdanm 0:9b334a45a8ff 503 break;
bogdanm 0:9b334a45a8ff 504
bogdanm 0:9b334a45a8ff 505 case LAN8720_ID:
bogdanm 0:9b334a45a8ff 506
bogdanm 0:9b334a45a8ff 507 for(tout = 100; tout; tout--) {
bogdanm 0:9b334a45a8ff 508 phy_data = phy_read(PHY_REG_BMSR);
bogdanm 0:9b334a45a8ff 509 if (phy_data & PHY_STS_DUPLEX)
bogdanm 0:9b334a45a8ff 510 break;
bogdanm 0:9b334a45a8ff 511 }
bogdanm 0:9b334a45a8ff 512
bogdanm 0:9b334a45a8ff 513 if (phy_data & PHY_STS_DUPLEX) {
bogdanm 0:9b334a45a8ff 514 /* Full duplex is enabled. */
bogdanm 0:9b334a45a8ff 515 LPC_ETHERNET->MAC_CONFIG |= MAC_DUPLEX_MODE;
bogdanm 0:9b334a45a8ff 516 } else {
bogdanm 0:9b334a45a8ff 517 LPC_ETHERNET->MAC_CONFIG &= ~MAC_DUPLEX_MODE;
bogdanm 0:9b334a45a8ff 518 }
bogdanm 0:9b334a45a8ff 519
bogdanm 0:9b334a45a8ff 520 if(phy_data & PHY_STS_SPEED) {
bogdanm 0:9b334a45a8ff 521 LPC_ETHERNET->MAC_CONFIG &= ~SUPP_SPEED;
bogdanm 0:9b334a45a8ff 522 } else {
bogdanm 0:9b334a45a8ff 523 LPC_ETHERNET->MAC_CONFIG |= SUPP_SPEED;
bogdanm 0:9b334a45a8ff 524 }
bogdanm 0:9b334a45a8ff 525 break;
bogdanm 0:9b334a45a8ff 526 }
bogdanm 0:9b334a45a8ff 527 }
bogdanm 0:9b334a45a8ff 528