]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC23XX/ethernet_api.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / hal / TARGET_NXP / TARGET_LPC23XX / ethernet_api.c
1 /* mbed Microcontroller Library
2  * Copyright (c) 2006-2013 ARM Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <string.h>
17
18 #include "ethernet_api.h"
19 #include "cmsis.h"
20 #include "mbed_interface.h"
21 #include "toolchain.h"
22 #include "mbed_error.h"
23
24 #define NEW_LOGIC       0
25 #define NEW_ETH_BUFFER  0
26
27 #if NEW_ETH_BUFFER
28
29 #define NUM_RX_FRAG         4           // Number of Rx Fragments (== packets)
30 #define NUM_TX_FRAG         3           // Number of Tx Fragments (== packets)
31
32 #define ETH_MAX_FLEN        1536         // Maximum Ethernet Frame Size
33 #define ETH_FRAG_SIZE       ETH_MAX_FLEN // Packet Fragment size (same as packet length)
34
35 #else
36
37 // Memfree calculation:
38 // (16 * 1024) - ((2 * 4 * NUM_RX) + (2 * 4 * NUM_RX) + (0x300 * NUM_RX) +
39 //                (2 * 4 * NUM_TX) + (1 * 4 * NUM_TX) + (0x300 * NUM_TX)) = 8556
40 /* EMAC Memory Buffer configuration for 16K Ethernet RAM. */
41 #define NUM_RX_FRAG         4           /* Num.of RX Fragments 4*1536= 6.0kB */
42 #define NUM_TX_FRAG         3           /* Num.of TX Fragments 3*1536= 4.6kB */
43 //#define ETH_FRAG_SIZE       1536        /* Packet Fragment size 1536 Bytes   */
44
45 //#define ETH_MAX_FLEN        1536        /* Max. Ethernet Frame Size          */
46 #define ETH_FRAG_SIZE       0x300       /* Packet Fragment size 1536/2 Bytes   */
47 #define ETH_MAX_FLEN        0x300       /* Max. Ethernet Frame Size          */
48
49 const int ethernet_MTU_SIZE  = 0x300;
50
51 #endif
52
53 #define ETHERNET_ADDR_SIZE 6
54
55 PACKED struct RX_DESC_TypeDef {                        /* RX Descriptor struct              */
56    unsigned int Packet;
57    unsigned int Ctrl;
58 };
59 typedef struct RX_DESC_TypeDef RX_DESC_TypeDef;
60
61 PACKED struct RX_STAT_TypeDef {                        /* RX Status struct                  */
62    unsigned int Info;
63    unsigned int HashCRC;
64 };
65 typedef struct RX_STAT_TypeDef RX_STAT_TypeDef;
66
67 PACKED struct TX_DESC_TypeDef {                        /* TX Descriptor struct              */
68    unsigned int Packet;
69    unsigned int Ctrl;
70 };
71 typedef struct TX_DESC_TypeDef TX_DESC_TypeDef;
72
73 PACKED struct TX_STAT_TypeDef {                        /* TX Status struct                  */
74    unsigned int Info;
75 };
76 typedef struct TX_STAT_TypeDef TX_STAT_TypeDef;
77
78 /* MAC Configuration Register 1 */
79 #define MAC1_REC_EN         0x00000001  /* Receive Enable                    */
80 #define MAC1_PASS_ALL       0x00000002  /* Pass All Receive Frames           */
81 #define MAC1_RX_FLOWC       0x00000004  /* RX Flow Control                   */
82 #define MAC1_TX_FLOWC       0x00000008  /* TX Flow Control                   */
83 #define MAC1_LOOPB          0x00000010  /* Loop Back Mode                    */
84 #define MAC1_RES_TX         0x00000100  /* Reset TX Logic                    */
85 #define MAC1_RES_MCS_TX     0x00000200  /* Reset MAC TX Control Sublayer     */
86 #define MAC1_RES_RX         0x00000400  /* Reset RX Logic                    */
87 #define MAC1_RES_MCS_RX     0x00000800  /* Reset MAC RX Control Sublayer     */
88 #define MAC1_SIM_RES        0x00004000  /* Simulation Reset                  */
89 #define MAC1_SOFT_RES       0x00008000  /* Soft Reset MAC                    */
90
91 /* MAC Configuration Register 2 */
92 #define MAC2_FULL_DUP       0x00000001  /* Full Duplex Mode                  */
93 #define MAC2_FRM_LEN_CHK    0x00000002  /* Frame Length Checking             */
94 #define MAC2_HUGE_FRM_EN    0x00000004  /* Huge Frame Enable                 */
95 #define MAC2_DLY_CRC        0x00000008  /* Delayed CRC Mode                  */
96 #define MAC2_CRC_EN         0x00000010  /* Append CRC to every Frame         */
97 #define MAC2_PAD_EN         0x00000020  /* Pad all Short Frames              */
98 #define MAC2_VLAN_PAD_EN    0x00000040  /* VLAN Pad Enable                   */
99 #define MAC2_ADET_PAD_EN    0x00000080  /* Auto Detect Pad Enable            */
100 #define MAC2_PPREAM_ENF     0x00000100  /* Pure Preamble Enforcement         */
101 #define MAC2_LPREAM_ENF     0x00000200  /* Long Preamble Enforcement         */
102 #define MAC2_NO_BACKOFF     0x00001000  /* No Backoff Algorithm              */
103 #define MAC2_BACK_PRESSURE  0x00002000  /* Backoff Presurre / No Backoff     */
104 #define MAC2_EXCESS_DEF     0x00004000  /* Excess Defer                      */
105
106 /* Back-to-Back Inter-Packet-Gap Register */
107 #define IPGT_FULL_DUP       0x00000015  /* Recommended value for Full Duplex */
108 #define IPGT_HALF_DUP       0x00000012  /* Recommended value for Half Duplex */
109
110 /* Non Back-to-Back Inter-Packet-Gap Register */
111 #define IPGR_DEF            0x00000012  /* Recommended value                 */
112
113 /* Collision Window/Retry Register */
114 #define CLRT_DEF            0x0000370F  /* Default value                     */
115
116 /* PHY Support Register */
117 #define SUPP_SPEED          0x00000100  /* Reduced MII Logic Current Speed   */
118 //#define SUPP_RES_RMII       0x00000800  /* Reset Reduced MII Logic           */
119 #define SUPP_RES_RMII       0x00000000  /* Reset Reduced MII Logic           */
120
121 /* Test Register */
122 #define TEST_SHCUT_PQUANTA  0x00000001  /* Shortcut Pause Quanta             */
123 #define TEST_TST_PAUSE      0x00000002  /* Test Pause                        */
124 #define TEST_TST_BACKP      0x00000004  /* Test Back Pressure                */
125
126 /* MII Management Configuration Register */
127 #define MCFG_SCAN_INC       0x00000001  /* Scan Increment PHY Address        */
128 #define MCFG_SUPP_PREAM     0x00000002  /* Suppress Preamble                 */
129 #define MCFG_CLK_SEL        0x0000003C  /* Clock Select Mask                 */
130 #define MCFG_RES_MII        0x00008000  /* Reset MII Management Hardware     */
131
132 /* MII Management Command Register */
133 #define MCMD_READ           0x00000001  /* MII Read                          */
134 #define MCMD_SCAN           0x00000002  /* MII Scan continuously             */
135
136 #define MII_WR_TOUT         0x00050000  /* MII Write timeout count           */
137 #define MII_RD_TOUT         0x00050000  /* MII Read timeout count            */
138
139 /* MII Management Address Register */
140 #define MADR_REG_ADR        0x0000001F  /* MII Register Address Mask         */
141 #define MADR_PHY_ADR        0x00001F00  /* PHY Address Mask                  */
142
143 /* MII Management Indicators Register */
144 #define MIND_BUSY           0x00000001  /* MII is Busy                       */
145 #define MIND_SCAN           0x00000002  /* MII Scanning in Progress          */
146 #define MIND_NOT_VAL        0x00000004  /* MII Read Data not valid           */
147 #define MIND_MII_LINK_FAIL  0x00000008  /* MII Link Failed                   */
148
149 /* Command Register */
150 #define CR_RX_EN            0x00000001  /* Enable Receive                    */
151 #define CR_TX_EN            0x00000002  /* Enable Transmit                   */
152 #define CR_REG_RES          0x00000008  /* Reset Host Registers              */
153 #define CR_TX_RES           0x00000010  /* Reset Transmit Datapath           */
154 #define CR_RX_RES           0x00000020  /* Reset Receive Datapath            */
155 #define CR_PASS_RUNT_FRM    0x00000040  /* Pass Runt Frames                  */
156 #define CR_PASS_RX_FILT     0x00000080  /* Pass RX Filter                    */
157 #define CR_TX_FLOW_CTRL     0x00000100  /* TX Flow Control                   */
158 #define CR_RMII             0x00000200  /* Reduced MII Interface             */
159 #define CR_FULL_DUP         0x00000400  /* Full Duplex                       */
160
161 /* Status Register */
162 #define SR_RX_EN            0x00000001  /* Enable Receive                    */
163 #define SR_TX_EN            0x00000002  /* Enable Transmit                   */
164
165 /* Transmit Status Vector 0 Register */
166 #define TSV0_CRC_ERR        0x00000001  /* CRC error                         */
167 #define TSV0_LEN_CHKERR     0x00000002  /* Length Check Error                */
168 #define TSV0_LEN_OUTRNG     0x00000004  /* Length Out of Range               */
169 #define TSV0_DONE           0x00000008  /* Tramsmission Completed            */
170 #define TSV0_MCAST          0x00000010  /* Multicast Destination             */
171 #define TSV0_BCAST          0x00000020  /* Broadcast Destination             */
172 #define TSV0_PKT_DEFER      0x00000040  /* Packet Deferred                   */
173 #define TSV0_EXC_DEFER      0x00000080  /* Excessive Packet Deferral         */
174 #define TSV0_EXC_COLL       0x00000100  /* Excessive Collision               */
175 #define TSV0_LATE_COLL      0x00000200  /* Late Collision Occured            */
176 #define TSV0_GIANT          0x00000400  /* Giant Frame                       */
177 #define TSV0_UNDERRUN       0x00000800  /* Buffer Underrun                   */
178 #define TSV0_BYTES          0x0FFFF000  /* Total Bytes Transferred           */
179 #define TSV0_CTRL_FRAME     0x10000000  /* Control Frame                     */
180 #define TSV0_PAUSE          0x20000000  /* Pause Frame                       */
181 #define TSV0_BACK_PRESS     0x40000000  /* Backpressure Method Applied       */
182 #define TSV0_VLAN           0x80000000  /* VLAN Frame                        */
183
184 /* Transmit Status Vector 1 Register */
185 #define TSV1_BYTE_CNT       0x0000FFFF  /* Transmit Byte Count               */
186 #define TSV1_COLL_CNT       0x000F0000  /* Transmit Collision Count          */
187
188 /* Receive Status Vector Register */
189 #define RSV_BYTE_CNT        0x0000FFFF  /* Receive Byte Count                */
190 #define RSV_PKT_IGNORED     0x00010000  /* Packet Previously Ignored         */
191 #define RSV_RXDV_SEEN       0x00020000  /* RXDV Event Previously Seen        */
192 #define RSV_CARR_SEEN       0x00040000  /* Carrier Event Previously Seen     */
193 #define RSV_REC_CODEV       0x00080000  /* Receive Code Violation            */
194 #define RSV_CRC_ERR         0x00100000  /* CRC Error                         */
195 #define RSV_LEN_CHKERR      0x00200000  /* Length Check Error                */
196 #define RSV_LEN_OUTRNG      0x00400000  /* Length Out of Range               */
197 #define RSV_REC_OK          0x00800000  /* Frame Received OK                 */
198 #define RSV_MCAST           0x01000000  /* Multicast Frame                   */
199 #define RSV_BCAST           0x02000000  /* Broadcast Frame                   */
200 #define RSV_DRIB_NIBB       0x04000000  /* Dribble Nibble                    */
201 #define RSV_CTRL_FRAME      0x08000000  /* Control Frame                     */
202 #define RSV_PAUSE           0x10000000  /* Pause Frame                       */
203 #define RSV_UNSUPP_OPC      0x20000000  /* Unsupported Opcode                */
204 #define RSV_VLAN            0x40000000  /* VLAN Frame                        */
205
206 /* Flow Control Counter Register */
207 #define FCC_MIRR_CNT        0x0000FFFF  /* Mirror Counter                    */
208 #define FCC_PAUSE_TIM       0xFFFF0000  /* Pause Timer                       */
209
210 /* Flow Control Status Register */
211 #define FCS_MIRR_CNT        0x0000FFFF  /* Mirror Counter Current            */
212
213 /* Receive Filter Control Register */
214 #define RFC_UCAST_EN        0x00000001  /* Accept Unicast Frames Enable      */
215 #define RFC_BCAST_EN        0x00000002  /* Accept Broadcast Frames Enable    */
216 #define RFC_MCAST_EN        0x00000004  /* Accept Multicast Frames Enable    */
217 #define RFC_UCAST_HASH_EN   0x00000008  /* Accept Unicast Hash Filter Frames */
218 #define RFC_MCAST_HASH_EN   0x00000010  /* Accept Multicast Hash Filter Fram.*/
219 #define RFC_PERFECT_EN      0x00000020  /* Accept Perfect Match Enable       */
220 #define RFC_MAGP_WOL_EN     0x00001000  /* Magic Packet Filter WoL Enable    */
221 #define RFC_PFILT_WOL_EN    0x00002000  /* Perfect Filter WoL Enable         */
222
223 /* Receive Filter WoL Status/Clear Registers */
224 #define WOL_UCAST           0x00000001  /* Unicast Frame caused WoL          */
225 #define WOL_BCAST           0x00000002  /* Broadcast Frame caused WoL        */
226 #define WOL_MCAST           0x00000004  /* Multicast Frame caused WoL        */
227 #define WOL_UCAST_HASH      0x00000008  /* Unicast Hash Filter Frame WoL     */
228 #define WOL_MCAST_HASH      0x00000010  /* Multicast Hash Filter Frame WoL   */
229 #define WOL_PERFECT         0x00000020  /* Perfect Filter WoL                */
230 #define WOL_RX_FILTER       0x00000080  /* RX Filter caused WoL              */
231 #define WOL_MAG_PACKET      0x00000100  /* Magic Packet Filter caused WoL    */
232
233 /* Interrupt Status/Enable/Clear/Set Registers */
234 #define INT_RX_OVERRUN      0x00000001  /* Overrun Error in RX Queue         */
235 #define INT_RX_ERR          0x00000002  /* Receive Error                     */
236 #define INT_RX_FIN          0x00000004  /* RX Finished Process Descriptors   */
237 #define INT_RX_DONE         0x00000008  /* Receive Done                      */
238 #define INT_TX_UNDERRUN     0x00000010  /* Transmit Underrun                 */
239 #define INT_TX_ERR          0x00000020  /* Transmit Error                    */
240 #define INT_TX_FIN          0x00000040  /* TX Finished Process Descriptors   */
241 #define INT_TX_DONE         0x00000080  /* Transmit Done                     */
242 #define INT_SOFT_INT        0x00001000  /* Software Triggered Interrupt      */
243 #define INT_WAKEUP          0x00002000  /* Wakeup Event Interrupt            */
244
245 /* Power Down Register */
246 #define PD_POWER_DOWN       0x80000000  /* Power Down MAC                    */
247
248 /* RX Descriptor Control Word */
249 #define RCTRL_SIZE          0x000007FF  /* Buffer size mask                  */
250 #define RCTRL_INT           0x80000000  /* Generate RxDone Interrupt         */
251
252 /* RX Status Hash CRC Word */
253 #define RHASH_SA            0x000001FF  /* Hash CRC for Source Address       */
254 #define RHASH_DA            0x001FF000  /* Hash CRC for Destination Address  */
255
256 /* RX Status Information Word */
257 #define RINFO_SIZE          0x000007FF  /* Data size in bytes                */
258 #define RINFO_CTRL_FRAME    0x00040000  /* Control Frame                     */
259 #define RINFO_VLAN          0x00080000  /* VLAN Frame                        */
260 #define RINFO_FAIL_FILT     0x00100000  /* RX Filter Failed                  */
261 #define RINFO_MCAST         0x00200000  /* Multicast Frame                   */
262 #define RINFO_BCAST         0x00400000  /* Broadcast Frame                   */
263 #define RINFO_CRC_ERR       0x00800000  /* CRC Error in Frame                */
264 #define RINFO_SYM_ERR       0x01000000  /* Symbol Error from PHY             */
265 #define RINFO_LEN_ERR       0x02000000  /* Length Error                      */
266 #define RINFO_RANGE_ERR     0x04000000  /* Range Error (exceeded max. size)  */
267 #define RINFO_ALIGN_ERR     0x08000000  /* Alignment Error                   */
268 #define RINFO_OVERRUN       0x10000000  /* Receive overrun                   */
269 #define RINFO_NO_DESCR      0x20000000  /* No new Descriptor available       */
270 #define RINFO_LAST_FLAG     0x40000000  /* Last Fragment in Frame            */
271 #define RINFO_ERR           0x80000000  /* Error Occured (OR of all errors)  */
272
273 //#define RINFO_ERR_MASK     (RINFO_FAIL_FILT | RINFO_CRC_ERR   | RINFO_SYM_ERR | RINFO_LEN_ERR   | RINFO_ALIGN_ERR | RINFO_OVERRUN)
274 #define RINFO_ERR_MASK     (RINFO_FAIL_FILT | RINFO_SYM_ERR | \
275                             RINFO_LEN_ERR   | RINFO_ALIGN_ERR | RINFO_OVERRUN)
276
277
278 /* TX Descriptor Control Word */
279 #define TCTRL_SIZE          0x000007FF  /* Size of data buffer in bytes      */
280 #define TCTRL_OVERRIDE      0x04000000  /* Override Default MAC Registers    */
281 #define TCTRL_HUGE          0x08000000  /* Enable Huge Frame                 */
282 #define TCTRL_PAD           0x10000000  /* Pad short Frames to 64 bytes      */
283 #define TCTRL_CRC           0x20000000  /* Append a hardware CRC to Frame    */
284 #define TCTRL_LAST          0x40000000  /* Last Descriptor for TX Frame      */
285 #define TCTRL_INT           0x80000000  /* Generate TxDone Interrupt         */
286
287 /* TX Status Information Word */
288 #define TINFO_COL_CNT       0x01E00000  /* Collision Count                   */
289 #define TINFO_DEFER         0x02000000  /* Packet Deferred (not an error)    */
290 #define TINFO_EXCESS_DEF    0x04000000  /* Excessive Deferral                */
291 #define TINFO_EXCESS_COL    0x08000000  /* Excessive Collision               */
292 #define TINFO_LATE_COL      0x10000000  /* Late Collision Occured            */
293 #define TINFO_UNDERRUN      0x20000000  /* Transmit Underrun                 */
294 #define TINFO_NO_DESCR      0x40000000  /* No new Descriptor available       */
295 #define TINFO_ERR           0x80000000  /* Error Occured (OR of all errors)  */
296
297 /* ENET Device Revision ID */
298 #define OLD_EMAC_MODULE_ID  0x39022000  /* Rev. ID for first rev '-'         */
299
300 /* DP83848C PHY Registers */
301 #define PHY_REG_BMCR        0x00        /* Basic Mode Control Register       */
302 #define PHY_REG_BMSR        0x01        /* Basic Mode Status Register        */
303 #define PHY_REG_IDR1        0x02        /* PHY Identifier 1                  */
304 #define PHY_REG_IDR2        0x03        /* PHY Identifier 2                  */
305 #define PHY_REG_ANAR        0x04        /* Auto-Negotiation Advertisement    */
306 #define PHY_REG_ANLPAR      0x05        /* Auto-Neg. Link Partner Abitily    */
307 #define PHY_REG_ANER        0x06        /* Auto-Neg. Expansion Register      */
308 #define PHY_REG_ANNPTR      0x07        /* Auto-Neg. Next Page TX            */
309
310 /* PHY Extended Registers */
311 #define PHY_REG_STS         0x10        /* Status Register                   */
312 #define PHY_REG_MICR        0x11        /* MII Interrupt Control Register    */
313 #define PHY_REG_MISR        0x12        /* MII Interrupt Status Register     */
314 #define PHY_REG_FCSCR       0x14        /* False Carrier Sense Counter       */
315 #define PHY_REG_RECR        0x15        /* Receive Error Counter             */
316 #define PHY_REG_PCSR        0x16        /* PCS Sublayer Config. and Status   */
317 #define PHY_REG_RBR         0x17        /* RMII and Bypass Register          */
318 #define PHY_REG_LEDCR       0x18        /* LED Direct Control Register       */
319 #define PHY_REG_PHYCR       0x19        /* PHY Control Register              */
320 #define PHY_REG_10BTSCR     0x1A        /* 10Base-T Status/Control Register  */
321 #define PHY_REG_CDCTRL1     0x1B        /* CD Test Control and BIST Extens.  */
322 #define PHY_REG_EDCR        0x1D        /* Energy Detect Control Register    */
323
324 #define PHY_REG_SCSR        0x1F        /* PHY Special Control/Status Register */
325
326 #define PHY_FULLD_100M      0x2100      /* Full Duplex 100Mbit               */
327 #define PHY_HALFD_100M      0x2000      /* Half Duplex 100Mbit               */
328 #define PHY_FULLD_10M       0x0100      /* Full Duplex 10Mbit                */
329 #define PHY_HALFD_10M       0x0000      /* Half Duplex 10MBit                */
330 #define PHY_AUTO_NEG        0x3000      /* Select Auto Negotiation           */
331
332 #define DP83848C_DEF_ADR    0x0100      /* Default PHY device address        */
333 #define DP83848C_ID         0x20005C90  /* PHY Identifier - DP83848C         */
334
335 #define LAN8720_ID          0x0007C0F0  /* PHY Identifier - LAN8720          */
336
337 #define PHY_STS_LINK        0x0001      /* PHY Status Link Mask              */
338 #define PHY_STS_SPEED       0x0002      /* PHY Status Speed Mask             */
339 #define PHY_STS_DUPLEX      0x0004      /* PHY Status Duplex Mask            */
340
341 #define PHY_BMCR_RESET      0x8000      /* PHY Reset                         */
342
343 #define PHY_BMSR_LINK       0x0004      /* PHY BMSR Link valid               */
344
345 #define PHY_SCSR_100MBIT    0x0008      /* Speed: 1=100 MBit, 0=10Mbit       */
346 #define PHY_SCSR_DUPLEX     0x0010      /* PHY Duplex Mask                   */
347
348
349 static int phy_read(unsigned int PhyReg);
350 static int phy_write(unsigned int PhyReg, unsigned short Data);
351
352 static void txdscr_init(void);
353 static void rxdscr_init(void);
354
355 #if defined (__ICCARM__)
356 #   define AHBSRAM1
357 #elif defined(TOOLCHAIN_GCC_CR)
358 #   define AHBSRAM1 __attribute__((section(".data.$RamPeriph32")))
359 #else
360 #   define AHBSRAM1     __attribute__((section("AHBSRAM1"),aligned))
361 #endif
362
363 AHBSRAM1 volatile uint8_t rxbuf[NUM_RX_FRAG][ETH_FRAG_SIZE];
364 AHBSRAM1 volatile uint8_t txbuf[NUM_TX_FRAG][ETH_FRAG_SIZE];
365 AHBSRAM1 volatile RX_DESC_TypeDef rxdesc[NUM_RX_FRAG];
366 AHBSRAM1 volatile RX_STAT_TypeDef rxstat[NUM_RX_FRAG];
367 AHBSRAM1 volatile TX_DESC_TypeDef txdesc[NUM_TX_FRAG];
368 AHBSRAM1 volatile TX_STAT_TypeDef txstat[NUM_TX_FRAG];
369
370
371 #if NEW_LOGIC
372 static int rx_consume_offset = -1;
373 static int tx_produce_offset = -1;
374 #else
375 static int send_doff =  0;
376 static int send_idx  = -1;
377 static int send_size =  0;
378
379 static int receive_soff =  0;
380 static int receive_idx  = -1;
381 #endif
382
383 static uint32_t phy_id = 0;
384
385 static inline int rinc(int idx, int mod) {
386   ++idx;
387   idx %= mod;
388   return idx;
389 }
390
391 //extern unsigned int SystemFrequency;
392 static inline unsigned int clockselect() {
393   if(SystemCoreClock < 10000000) {
394     return 1;
395   } else if(SystemCoreClock <  15000000) {
396     return 2;
397   } else if(SystemCoreClock <  20000000) {
398     return 3;
399   } else if(SystemCoreClock <  25000000) {
400     return 4;
401   } else if(SystemCoreClock <  35000000) {
402     return 5;
403   } else if(SystemCoreClock <  50000000) {
404     return 6;
405   } else if(SystemCoreClock <  70000000) {
406     return 7;
407   } else if(SystemCoreClock <  80000000) {
408     return 8;
409   } else if(SystemCoreClock <  90000000) {
410     return 9;
411   } else if(SystemCoreClock < 100000000) {
412     return 10;
413   } else if(SystemCoreClock < 120000000) {
414     return 11;
415   } else if(SystemCoreClock < 130000000) {
416     return 12;
417   } else if(SystemCoreClock < 140000000) {
418     return 13;
419   } else if(SystemCoreClock < 150000000) {
420     return 15;
421   } else if(SystemCoreClock < 160000000) {
422     return 16;
423   } else {
424     return 0;
425   }
426 }
427
428 #ifndef min
429 #define min(x, y) (((x)<(y))?(x):(y))
430 #endif
431
432 /*----------------------------------------------------------------------------
433   Ethernet Device initialize
434  *----------------------------------------------------------------------------*/
435 int ethernet_init() {
436   int regv, tout;
437   char mac[ETHERNET_ADDR_SIZE];
438   unsigned int clock = clockselect();
439   
440   LPC_SC->PCONP |= 0x40000000;                       /* Power Up the EMAC controller. */
441   
442   LPC_PINCON->PINSEL2 = 0x50150105;                  /* Enable P1 Ethernet Pins. */
443   LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005;
444   
445    /* Reset all EMAC internal modules. */
446   LPC_EMAC->MAC1    = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX |
447                       MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
448   LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
449
450   for(tout = 100; tout; tout--) __NOP();             /* A short delay after reset. */
451
452   LPC_EMAC->MAC1 = MAC1_PASS_ALL;                    /* Initialize MAC control registers. */
453   LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
454   LPC_EMAC->MAXF = ETH_MAX_FLEN;
455   LPC_EMAC->CLRT = CLRT_DEF;
456   LPC_EMAC->IPGR = IPGR_DEF;
457
458   LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM;    /* Enable Reduced MII interface. */
459
460   LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;    /* Set clock */
461   LPC_EMAC->MCFG |= MCFG_RES_MII;                    /* and reset */
462
463   for(tout = 100; tout; tout--) __NOP();             /* A short delay */
464
465   LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;
466   LPC_EMAC->MCMD = 0;
467
468   LPC_EMAC->SUPP = SUPP_RES_RMII;                    /* Reset Reduced MII Logic. */
469
470   for (tout = 100; tout; tout--) __NOP();            /* A short delay */
471
472   LPC_EMAC->SUPP = 0;
473
474   phy_write(PHY_REG_BMCR, PHY_BMCR_RESET);           /* perform PHY reset */
475   for(tout = 0x20000; ; tout--) {                    /* Wait for hardware reset to end. */
476     regv = phy_read(PHY_REG_BMCR);
477     if(regv < 0 || tout == 0) {
478        return -1;                                    /* Error */
479     }
480     if(!(regv & PHY_BMCR_RESET)) {
481        break;                                        /* Reset complete. */
482     }
483   }
484
485   phy_id =  (phy_read(PHY_REG_IDR1) << 16);
486   phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);
487
488   if (phy_id != DP83848C_ID && phy_id != LAN8720_ID) {
489       error("Unknown Ethernet PHY (%x)", (unsigned int)phy_id);
490   }
491
492   ethernet_set_link(-1, 0);
493
494   /* Set the Ethernet MAC Address registers */
495   ethernet_address(mac);
496   LPC_EMAC->SA0 = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4];
497   LPC_EMAC->SA1 = ((uint32_t)mac[3] << 8) | (uint32_t)mac[2];
498   LPC_EMAC->SA2 = ((uint32_t)mac[1] << 8) | (uint32_t)mac[0];
499
500   txdscr_init();                                      /* initialize DMA TX Descriptor */
501   rxdscr_init();                                      /* initialize DMA RX Descriptor */
502
503   LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
504                                                       /* Receive Broadcast, Perfect Match Packets */
505
506   LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE;    /* Enable EMAC interrupts. */
507   LPC_EMAC->IntClear  = 0xFFFF;                       /* Reset all interrupts */
508
509
510   LPC_EMAC->Command  |= (CR_RX_EN | CR_TX_EN);        /* Enable receive and transmit mode of MAC Ethernet core */
511   LPC_EMAC->MAC1     |= MAC1_REC_EN;
512
513 #if NEW_LOGIC
514   rx_consume_offset = -1;
515   tx_produce_offset = -1;
516 #else
517   send_doff =  0;
518   send_idx  = -1;
519   send_size =  0;
520
521   receive_soff =  0;
522   receive_idx  = -1;
523 #endif
524
525   return 0;
526 }
527
528 /*----------------------------------------------------------------------------
529   Ethernet Device Uninitialize
530  *----------------------------------------------------------------------------*/
531 void ethernet_free() {
532   LPC_EMAC->IntEnable &= ~(INT_RX_DONE | INT_TX_DONE);
533   LPC_EMAC->IntClear   =  0xFFFF;
534   
535   LPC_SC->PCONP   &= ~0x40000000;       /* Power down the EMAC controller. */
536   
537   LPC_PINCON->PINSEL2 &= ~0x50150105;   /* Disable P1 ethernet pins. */
538   LPC_PINCON->PINSEL3  = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000000;
539 }
540
541 // if(TxProduceIndex == TxConsumeIndex) buffer array is empty
542 // if(TxProduceIndex == TxConsumeIndex - 1) buffer is full, should not fill
543 // TxProduceIndex - The buffer that will/is being fileld by driver, s/w increment
544 // TxConsumeIndex - The buffer that will/is beign sent by hardware
545
546 int ethernet_write(const char *data, int slen) {
547
548 #if NEW_LOGIC
549
550    if(tx_produce_offset < 0) { // mark as active if not already
551      tx_produce_offset = 0;
552    }
553
554    int index = LPC_EMAC->TxProduceIndex;
555
556    int remaining = ETH_MAX_FLEN - tx_produce_offset - 4; // bytes written plus checksum
557    int requested = slen;
558    int ncopy = min(remaining, requested);
559
560    void *pdst = (void *)(txdesc[index].Packet + tx_produce_offset);
561    void *psrc = (void *)(data);
562
563    if(ncopy > 0 ){
564      if(data != NULL) {
565        memcpy(pdst, psrc, ncopy);
566      } else {
567        memset(pdst, 0, ncopy);
568      }
569    }
570
571    tx_produce_offset += ncopy;
572
573    return ncopy;
574
575 #else
576     void       *pdst, *psrc;
577     const int   dlen = ETH_FRAG_SIZE;
578     int         copy = 0;
579     int         soff = 0;
580
581     if(send_idx == -1) {
582         send_idx = LPC_EMAC->TxProduceIndex;
583     }
584
585     if(slen + send_doff > ethernet_MTU_SIZE) {
586        return -1;
587     }
588
589     do {
590         copy = min(slen - soff, dlen - send_doff);
591         pdst = (void *)(txdesc[send_idx].Packet + send_doff);
592         psrc = (void *)(data + soff);
593         if(send_doff + copy > ETH_FRAG_SIZE) {
594             txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT);
595             send_idx = rinc(send_idx, NUM_TX_FRAG);
596             send_doff = 0;
597         }
598
599         if(data != NULL) {
600             memcpy(pdst, psrc, copy);
601         } else {
602             memset(pdst, 0, copy);
603         }
604
605         soff += copy;
606         send_doff += copy;
607         send_size += copy;
608     } while(soff != slen);
609
610     return soff;
611 #endif
612 }
613
614 int ethernet_send() {
615
616 #if NEW_LOGIC
617   if(tx_produce_offset < 0) { // no buffer active
618     return -1;
619   }
620
621   // ensure there is a link
622   if(!ethernet_link()) {
623     return -2;
624   }
625
626   // we have been writing in to a buffer, so finalise it
627   int size = tx_produce_offset;
628   int index = LPC_EMAC->TxProduceIndex;
629   txdesc[index].Ctrl = (tx_produce_offset-1) | (TCTRL_INT | TCTRL_LAST);
630
631   // Increment ProduceIndex to allow it to be sent
632   // We can only do this if the next slot is free
633   int next = rinc(index, NUM_TX_FRAG);
634   while(next == LPC_EMAC->TxConsumeIndex) {
635     for(int i=0; i<1000; i++) { __NOP(); }
636   }
637
638   LPC_EMAC->TxProduceIndex = next;
639   tx_produce_offset = -1;
640   return size;
641
642 #else
643     int s = send_size;
644     txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT | TCTRL_LAST);
645     send_idx  = rinc(send_idx, NUM_TX_FRAG);
646     LPC_EMAC->TxProduceIndex = send_idx;
647     send_doff =  0;
648     send_idx  = -1;
649     send_size =  0;
650     return s;
651 #endif
652 }
653
654 // RxConsmeIndex - The index of buffer the driver will/is reading from. Driver should inc once read
655 // RxProduceIndex - The index of buffer that will/is being filled by MAC. H/w will inc once rxd
656 //
657 // if(RxConsumeIndex == RxProduceIndex) buffer array is empty
658 // if(RxConsumeIndex == RxProduceIndex + 1) buffer array is full
659
660 // Recevies an arrived ethernet packet.
661 // Receiving an ethernet packet will drop the last received ethernet packet
662 // and make a new ethernet packet ready to read.
663 // Returns size of packet, else 0 if nothing to receive
664
665 // We read from RxConsumeIndex from position rx_consume_offset
666 // if rx_consume_offset < 0, then we have not recieved the RxConsumeIndex packet for reading
667 // rx_consume_offset = -1 // no frame
668 // rx_consume_offset = 0  // start of frame
669 // Assumption: A fragment should alway be a whole frame
670
671 int ethernet_receive() {
672 #if NEW_LOGIC
673
674   // if we are currently reading a valid RxConsume buffer, increment to the next one
675   if(rx_consume_offset >= 0) {
676     LPC_EMAC->RxConsumeIndex = rinc(LPC_EMAC->RxConsumeIndex, NUM_RX_FRAG);
677   }
678
679   // if the buffer is empty, mark it as no valid buffer
680   if(LPC_EMAC->RxConsumeIndex == LPC_EMAC->RxProduceIndex) {
681     rx_consume_offset = -1;
682     return 0;
683   }
684
685   uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info;
686   rx_consume_offset = 0;
687
688   // check if it is not marked as last or for errors
689   if(!(info & RINFO_LAST_FLAG) || (info & RINFO_ERR_MASK)) {
690     return -1;
691   }
692
693   int size = (info & RINFO_SIZE) + 1;
694   return size - 4; // don't include checksum bytes
695
696 #else
697     if(receive_idx == -1) {
698       receive_idx = LPC_EMAC->RxConsumeIndex;
699     } else {
700         while(!(rxstat[receive_idx].Info & RINFO_LAST_FLAG) && ((uint32_t)receive_idx != LPC_EMAC->RxProduceIndex)) {
701             receive_idx  = rinc(receive_idx, NUM_RX_FRAG);
702         }
703         unsigned int info =   rxstat[receive_idx].Info;
704         int slen =  (info & RINFO_SIZE) + 1;
705
706         if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) {
707             /* Invalid frame, ignore it and free buffer. */
708             receive_idx = rinc(receive_idx, NUM_RX_FRAG);
709         }
710         receive_idx = rinc(receive_idx, NUM_RX_FRAG);
711         receive_soff = 0;
712         
713         LPC_EMAC->RxConsumeIndex = receive_idx;
714     }
715     
716     if((uint32_t)receive_idx == LPC_EMAC->RxProduceIndex) {
717         receive_idx = -1;
718         return 0;
719     }
720     
721     return (rxstat[receive_idx].Info & RINFO_SIZE) - 3;
722 #endif
723 }
724
725 // Read from an recevied ethernet packet.
726 // After receive returnd a number bigger than 0 it is
727 // possible to read bytes from this packet.
728 // Read will write up to size bytes into data.
729 // It is possible to use read multible times.
730 // Each time read will start reading after the last read byte before.
731
732 int ethernet_read(char *data, int dlen) {
733 #if NEW_LOGIC
734   // Check we have a valid buffer to read
735   if(rx_consume_offset < 0) {
736     return 0;
737   }
738
739   // Assume 1 fragment block
740   uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info;
741   int size = (info & RINFO_SIZE) + 1 - 4; // exclude checksum
742
743   int remaining = size - rx_consume_offset;
744   int requested = dlen;
745   int ncopy = min(remaining, requested);
746
747   void *psrc = (void *)(rxdesc[LPC_EMAC->RxConsumeIndex].Packet + rx_consume_offset);
748   void *pdst = (void *)(data);
749
750   if(data != NULL && ncopy > 0) {
751     memcpy(pdst, psrc, ncopy);
752   }
753
754   rx_consume_offset += ncopy;
755
756   return ncopy;
757 #else
758     int          slen;
759     int          copy   = 0;
760     unsigned int more;
761     unsigned int info;
762     void        *pdst, *psrc;
763     int          doff = 0;
764     
765     if((uint32_t)receive_idx == LPC_EMAC->RxProduceIndex || receive_idx == -1) {
766         return 0;
767     }
768     
769     do {
770         info =   rxstat[receive_idx].Info;
771         more = !(info & RINFO_LAST_FLAG);
772         slen =  (info & RINFO_SIZE) + 1;
773         
774         if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) {
775             /* Invalid frame, ignore it and free buffer. */
776             receive_idx = rinc(receive_idx, NUM_RX_FRAG);
777         } else {
778             
779             copy = min(slen - receive_soff, dlen - doff);
780             psrc = (void *)(rxdesc[receive_idx].Packet + receive_soff);
781             pdst = (void *)(data + doff);
782             
783             if(data != NULL) {
784                 /* check if Buffer available */
785                 memcpy(pdst, psrc, copy);
786             }
787             
788             receive_soff += copy;
789             doff += copy;
790             
791             if((more && (receive_soff == slen))) {
792                 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
793                 receive_soff = 0;
794             }
795         }
796     } while(more && !(doff == dlen) && !receive_soff);
797     
798     return doff;
799 #endif
800 }
801
802 int ethernet_link(void) {
803     if (phy_id == DP83848C_ID) {
804       return (phy_read(PHY_REG_STS) & PHY_STS_LINK);
805     }
806     else { // LAN8720_ID
807       return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);
808     }
809 }
810
811 static int phy_write(unsigned int PhyReg, unsigned short Data) {
812     unsigned int timeOut;
813     
814     LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
815     LPC_EMAC->MWTD = Data;
816     
817     for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) {     /* Wait until operation completed */
818         if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
819             return 0;
820         }
821     }
822     
823     return -1;
824 }
825
826 static int phy_read(unsigned int PhyReg) {
827     unsigned int timeOut;
828     
829     LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
830     LPC_EMAC->MCMD = MCMD_READ;
831     
832     for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) {     /* Wait until operation completed */
833         if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
834             LPC_EMAC->MCMD = 0;
835             return LPC_EMAC->MRDD;                           /* Return a 16-bit value. */
836         }
837     }
838     
839     return -1;
840 }
841
842
843 static void txdscr_init() {
844     int i;
845     
846     for(i = 0; i < NUM_TX_FRAG; i++) {
847         txdesc[i].Packet = (uint32_t)&txbuf[i];
848         txdesc[i].Ctrl   = 0;
849         txstat[i].Info   = 0;
850     }
851     
852     LPC_EMAC->TxDescriptor       = (uint32_t)txdesc;         /* Set EMAC Transmit Descriptor Registers. */
853     LPC_EMAC->TxStatus           = (uint32_t)txstat;
854     LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
855     
856     LPC_EMAC->TxProduceIndex  = 0;                           /* Tx Descriptors Point to 0 */
857 }
858
859 static void rxdscr_init() {
860     int i;
861     
862     for(i = 0; i < NUM_RX_FRAG; i++) {
863         rxdesc[i].Packet  = (uint32_t)&rxbuf[i];
864         rxdesc[i].Ctrl    = RCTRL_INT | (ETH_FRAG_SIZE-1);
865         rxstat[i].Info    = 0;
866         rxstat[i].HashCRC = 0;
867     }
868     
869     LPC_EMAC->RxDescriptor       = (uint32_t)rxdesc;        /* Set EMAC Receive Descriptor Registers. */
870     LPC_EMAC->RxStatus           = (uint32_t)rxstat;
871     LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1;
872     
873     LPC_EMAC->RxConsumeIndex  = 0;                          /* Rx Descriptors Point to 0 */
874 }
875
876 void ethernet_address(char *mac) {
877     mbed_mac_address(mac);
878 }
879
880 void ethernet_set_link(int speed, int duplex) {
881     unsigned short phy_data;
882     int tout;
883     
884     if((speed < 0) || (speed > 1)) {
885         phy_data = PHY_AUTO_NEG;
886     } else {
887         phy_data = (((unsigned short) speed << 13) |
888                     ((unsigned short) duplex << 8));
889     }
890     
891     phy_write(PHY_REG_BMCR, phy_data);
892     
893     for(tout = 100; tout; tout--) { __NOP(); }     /* A short delay */
894     
895     switch(phy_id) {
896         case DP83848C_ID:
897             phy_data = phy_read(PHY_REG_STS);
898             
899             if(phy_data & PHY_STS_DUPLEX) {
900                 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
901                 LPC_EMAC->Command |= CR_FULL_DUP;
902                 LPC_EMAC->IPGT = IPGT_FULL_DUP;
903             } else {
904             LPC_EMAC->MAC2 &= ~MAC2_FULL_DUP;
905                 LPC_EMAC->Command &= ~CR_FULL_DUP;
906                 LPC_EMAC->IPGT = IPGT_HALF_DUP;
907             }
908             
909             if(phy_data & PHY_STS_SPEED) {
910                 LPC_EMAC->SUPP &= ~SUPP_SPEED;
911             } else {
912                 LPC_EMAC->SUPP |= SUPP_SPEED;
913             }
914             break;
915         
916         case LAN8720_ID:
917             phy_data = phy_read(PHY_REG_SCSR);
918             
919             if (phy_data & PHY_SCSR_DUPLEX) {
920                 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
921                 LPC_EMAC->Command |= CR_FULL_DUP;
922                 LPC_EMAC->IPGT = IPGT_FULL_DUP;
923             } else {
924                 LPC_EMAC->Command &= ~CR_FULL_DUP;
925                 LPC_EMAC->IPGT = IPGT_HALF_DUP;
926             }
927             
928             if(phy_data & PHY_SCSR_100MBIT) {
929                 LPC_EMAC->SUPP |= SUPP_SPEED;
930             } else {
931                 LPC_EMAC->SUPP &= ~SUPP_SPEED;
932             }
933             break;
934     }
935 }