Johannes Stratmann / mbed-dev

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

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