OSDN Git Service

update libMiMic
[mimic/MiMicSDK.git] / lib / src / driver / ethernet / lpc4088 / EthDev_LPC4088.c
1 #include "NyLPC_config.h"\r
2 #if NyLPC_MCU==NyLPC_MCU_LPC4088\r
3 #include "NyLPC_os.h"\r
4 #include "copy_of_ethernet_api.h"\r
5 #include "NyLPC_IEthernetDevice.h"\r
6 #include "NyLPC_cEthernetMM.h"\r
7 \r
8 \r
9 \r
10 #define emacSHORT_DELAY_MS                 10\r
11 #ifndef configEMAC_INTERRUPT_PRIORITY\r
12     #define configEMAC_INTERRUPT_PRIORITY       5\r
13 #endif\r
14 ////////////////////////////////////////////////////////////////////////////////\r
15 // Ethernet Memory\r
16 ////////////////////////////////////////////////////////////////////////////////\r
17 \r
18 #define AHB_SRAM_BANK1_BASE  0x20004000UL\r
19 #define RX_DESC_BASE        (AHB_SRAM_BANK1_BASE         )\r
20 #define RX_STAT_BASE        (RX_DESC_BASE + NUM_RX_FRAG*(2*4))     /* 2 * uint32_t, see RX_DESC_TypeDef */\r
21 #define TX_DESC_BASE        (RX_STAT_BASE + NUM_RX_FRAG*(2*4))     /* 2 * uint32_t, see RX_STAT_TypeDef */\r
22 #define TX_STAT_BASE        (TX_DESC_BASE + NUM_TX_FRAG*(2*4))     /* 2 * uint32_t, see TX_DESC_TypeDef */\r
23 #define ETH_BUF_BASE            (TX_STAT_BASE + NUM_TX_FRAG*(1*4))     /* 1 * uint32_t, see TX_STAT_TypeDef */\r
24 \r
25 /**\r
26  * 消費メモリ量は、\r
27  * descriptor = NUM_RX_FRAG*16+NUM_TX_FRAG*12.\r
28  * EthnetBuf=ETH_FRAG_SIZE*NUM_RX_FRAG\r
29  */\r
30 \r
31 /* RX and TX descriptor and status definitions. */\r
32 #define RX_DESC_PACKET(i)   (*(unsigned int *)(RX_DESC_BASE   + 8*i))\r
33 #define RX_DESC_CTRL(i)     (*(unsigned int *)(RX_DESC_BASE+4 + 8*i))\r
34 #define RX_STAT_INFO(i)     (*(unsigned int *)(RX_STAT_BASE   + 8*i))\r
35 #define RX_STAT_HASHCRC(i)  (*(unsigned int *)(RX_STAT_BASE+4 + 8*i))\r
36 #define TX_DESC_PACKET(i)   (*(unsigned int *)(TX_DESC_BASE   + 8*i))\r
37 #define TX_DESC_CTRL(i)     (*(unsigned int *)(TX_DESC_BASE+4 + 8*i))\r
38 #define TX_STAT_INFO(i)     (*(unsigned int *)(TX_STAT_BASE   + 4*i))\r
39 #define ETH_BUF(i)          ( ETH_BUF_BASE + ETH_FRAG_SIZE*i )\r
40 #define ETH_TX_BUF_BASE ((void*)(ETH_BUF_BASE+ETH_FRAG_SIZE*NUM_RX_FRAG))\r
41 \r
42 \r
43 #define emacWAIT_FOR_LINK_TO_ESTABLISH_MS 500\r
44 \r
45 ////////////////////////////////////////////////////////////////////////////////\r
46 // Ethernet interdface functions\r
47 ////////////////////////////////////////////////////////////////////////////////\r
48 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param);\r
49 static void stop(void);\r
50 static void* getRxEthFrame(unsigned short* o_len_of_data);\r
51 static void nextRxEthFrame(void);\r
52 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size);\r
53 static void releaseTxBuf(void* i_buf);\r
54 static void sendTxEthFrame(void* i_buf,unsigned short i_size);\r
55 static void processTx(void);\r
56 \r
57 ////////////////////////////////////////////////////////////////////////////////\r
58 // Private\r
59 ////////////////////////////////////////////////////////////////////////////////\r
60 static void emacIsrHandler(unsigned long i_status);\r
61 static unsigned int clockselect(void);\r
62 static int ethernet_link(void);\r
63 static int phy_write(unsigned int PhyReg, unsigned short Data);\r
64 static int phy_read(unsigned int PhyReg);\r
65 static void prevTxDescriptor(void);\r
66 static void prevRxDescriptor(void);\r
67 static NyLPC_TUInt32 waitForTxEthFrameEmpty(void);\r
68 \r
69 /*-----------------------------------------------------------*/\r
70 \r
71 \r
72 const static struct TiEthernetDevice _interface_LAN8720=\r
73 {\r
74         "LAN8720",\r
75         start,\r
76         stop,\r
77         getRxEthFrame,\r
78         nextRxEthFrame,\r
79         allocTxBuf,\r
80         releaseTxBuf,\r
81         sendTxEthFrame,\r
82         processTx\r
83 };\r
84 const static struct TiEthernetDevice _interface_DP83848C=\r
85 {\r
86         "DP83848C",\r
87         start,\r
88         stop,\r
89         getRxEthFrame,\r
90         nextRxEthFrame,\r
91         allocTxBuf,\r
92         releaseTxBuf,\r
93         sendTxEthFrame,\r
94         processTx\r
95 };\r
96 \r
97 static void* _event_param;\r
98 static NyLPC_TiEthernetDevice_onEvent _event_handler;\r
99 static unsigned int phy_id;\r
100 \r
101 /*\r
102  * EthernetDeviceのファクトリー関数。インターフェイスを生成できればtrue\r
103  *\r
104  */\r
105 NyLPC_TBool EthDev_LPC4088_getInterface(\r
106         const struct TiEthernetDevice** o_dev)\r
107 {\r
108         int regv, tout;\r
109         unsigned int clock = clockselect();\r
110         \r
111         LPC_SC->PCONP |= 0x40000000; /* Power Up the EMAC controller. */\r
112         LPC_IOCON->P1_0 &= ~0x07; /* ENET I/O config */\r
113         LPC_IOCON->P1_0 |= 0x01; /* ENET_TXD0 */\r
114         LPC_IOCON->P1_1 &= ~0x07;\r
115         LPC_IOCON->P1_1 |= 0x01; /* ENET_TXD1 */\r
116         LPC_IOCON->P1_4 &= ~0x07;\r
117         LPC_IOCON->P1_4 |= 0x01; /* ENET_TXEN */\r
118         LPC_IOCON->P1_8 &= ~0x07;\r
119         LPC_IOCON->P1_8 |= 0x01; /* ENET_CRS */\r
120         LPC_IOCON->P1_9 &= ~0x07;\r
121         LPC_IOCON->P1_9 |= 0x01; /* ENET_RXD0 */\r
122         LPC_IOCON->P1_10 &= ~0x07;\r
123         LPC_IOCON->P1_10 |= 0x01; /* ENET_RXD1 */\r
124         LPC_IOCON->P1_14 &= ~0x07;\r
125         LPC_IOCON->P1_14 |= 0x01; /* ENET_RX_ER */\r
126         LPC_IOCON->P1_15 &= ~0x07;\r
127         LPC_IOCON->P1_15 |= 0x01; /* ENET_REF_CLK */\r
128         LPC_IOCON->P1_16 &= ~0x07; /* ENET/PHY I/O config */\r
129         LPC_IOCON->P1_16 |= 0x01; /* ENET_MDC */\r
130         LPC_IOCON->P1_17 &= ~0x07;\r
131         LPC_IOCON->P1_17 |= 0x01; /* ENET_MDIO */\r
132   \r
133         /* Reset all EMAC internal modules. */\r
134         LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;\r
135         LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;              \r
136 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */\r
137         \r
138         /* Initialize MAC control registers. */\r
139         LPC_EMAC->MAC1 = MAC1_PASS_ALL; \r
140         LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;\r
141         LPC_EMAC->MAXF = ETH_MAX_FLEN;\r
142         LPC_EMAC->CLRT = CLRT_DEF;\r
143         LPC_EMAC->IPGR = IPGR_DEF;\r
144         \r
145         /* Enable Reduced MII interface. */\r
146         LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; /* Set clock */\r
147         LPC_EMAC->MCFG |= MCFG_RES_MII; /* and reset */\r
148         LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM |CR_PASS_RX_FILT; /* Enable Reduced MII interface. */\r
149         \r
150 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */\r
151 \r
152         LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;\r
153         LPC_EMAC->MCMD = 0;\r
154         LPC_EMAC->SUPP = SUPP_RES_RMII; /* Reset Reduced MII Logic. */\r
155 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */\r
156         LPC_EMAC->SUPP = SUPP_SPEED;\r
157         \r
158         phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */\r
159         for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */\r
160                 regv = phy_read(PHY_REG_BMCR);\r
161                 if(regv < 0 || tout == 0) {\r
162                 return NyLPC_TBool_FALSE; /* Error */\r
163         }\r
164                 if(!(regv & PHY_BMCR_RESET)) {\r
165                 break; /* Reset complete. */\r
166         }\r
167         }\r
168 \r
169         phy_id = (phy_read(PHY_REG_IDR1) << 16);\r
170         phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);\r
171 \r
172         switch(phy_id){\r
173         case DP83848C_ID:\r
174                 *o_dev=&_interface_DP83848C;\r
175                 break;\r
176         case LAN8720_ID:\r
177                 *o_dev=&_interface_LAN8720;\r
178                 break;\r
179         default:\r
180                 return NyLPC_TBool_FALSE; /* Error */\r
181         }\r
182         LPC_EMAC->TxProduceIndex = 0;\r
183         LPC_EMAC->RxConsumeIndex = 0;   \r
184         return NyLPC_TBool_TRUE;\r
185 }\r
186 \r
187 \r
188 \r
189 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param)\r
190 {\r
191         int i;\r
192         //ISRw割り込み設定\r
193         NyLPC_cIsr_setEnetISR(emacIsrHandler);\r
194         _event_handler=i_handler;\r
195         _event_param=i_param;\r
196         /* Set the Ethernet MAC Address registers */\r
197         LPC_EMAC->SA0 = (((uint32_t)(i_eth_addr->addr[0])) << 8 ) | i_eth_addr->addr[1];\r
198         LPC_EMAC->SA1 = (((uint32_t)(i_eth_addr->addr[2])) << 8 ) | i_eth_addr->addr[3];\r
199         LPC_EMAC->SA2 = (((uint32_t)(i_eth_addr->addr[4])) << 8 ) | i_eth_addr->addr[5];\r
200 \r
201         //TXメモリマネージャの準備\r
202         NyLPC_cEthernetMM_initialize(ETH_TX_BUF_BASE);\r
203         /* Initialize Tx and Rx DMA Descriptors */\r
204         prevRxDescriptor();\r
205         prevTxDescriptor();\r
206         //wait for link up \r
207         for(i=0;i<5;i++){\r
208                 if(ethernet_link()!=0){\r
209                         break;\r
210                 }\r
211                 NyLPC_cThread_sleep(emacWAIT_FOR_LINK_TO_ESTABLISH_MS);\r
212         }\r
213 \r
214         //setup Link\r
215         ethernet_set_link(-1, 0);\r
216 \r
217         LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;\r
218         /* Receive Broadcast, Perfect Match Packets */\r
219 \r
220         //Ethernetの割込み開始設定\r
221         NyLPC_cIsr_enterCritical();\r
222         {\r
223                 LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE; /* Enable EMAC interrupts. */\r
224                 LPC_EMAC->IntClear = 0xFFFF; /* Reset all interrupts */\r
225           \r
226                 LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); /* Enable receive and transmit mode of MAC Ethernet core */\r
227                 LPC_EMAC->MAC1 |= MAC1_REC_EN;\r
228 \r
229         NVIC_SetPriority( ENET_IRQn, configEMAC_INTERRUPT_PRIORITY );\r
230         NVIC_EnableIRQ( ENET_IRQn );\r
231         }\r
232         NyLPC_cIsr_exitCritical();\r
233 \r
234         return NyLPC_TBool_TRUE;\r
235 }\r
236 \r
237 \r
238 static void stop(void)\r
239 {\r
240         NyLPC_cIsr_enterCritical();\r
241         {\r
242             LPC_EMAC->IntEnable &= ~(INT_RX_DONE | INT_TX_DONE);\r
243             LPC_EMAC->IntClear = 0xFFFF;\r
244             \r
245         NVIC_DisableIRQ( ENET_IRQn );\r
246         }\r
247         NyLPC_cIsr_exitCritical();\r
248         LPC_EMAC->Command &= ~( CR_RX_EN | CR_TX_EN );\r
249         LPC_EMAC->MAC1 &= ~MAC1_REC_EN;\r
250         //ISR割り込み解除\r
251         NyLPC_cIsr_setEnetISR(NULL);\r
252         //TXメモリマネージャの終了\r
253         NyLPC_cEthernetMM_finalize();\r
254 }\r
255 \r
256 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)\r
257 {\r
258         return NyLPC_cEthernetMM_alloc(i_hint,o_size);\r
259 }\r
260 static void releaseTxBuf(void* i_buf)\r
261 {\r
262         NyLPC_cEthernetMM_release(i_buf);\r
263 }\r
264 \r
265 \r
266 /**\r
267 */\r
268 static void processTx(void)\r
269 {\r
270         waitForTxEthFrameEmpty();\r
271 }\r
272 \r
273 \r
274 \r
275 /**\r
276  * Ethernetパケットを送信します。\r
277  * allocTxBufで得たバッファを指定すること。\r
278  * <p>関数仕様</p>\r
279  * この関数は、i_bufが\r
280  * </div>\r
281  */\r
282 static void sendTxEthFrame(void* i_buf,unsigned short i_size)\r
283 {\r
284         NyLPC_TUInt32   IndexNext,Index;\r
285         struct NyLPC_TTxBufferHeader* bh=NyLPC_TTxBufferHeader_getBufferHeaderAddr(i_buf);\r
286 \r
287         //サイズ0なら送信の必要なし\r
288         if(i_size == 0)\r
289         {\r
290                 return;\r
291         }\r
292         //送信デスクリプタの反映\r
293         IndexNext =waitForTxEthFrameEmpty();\r
294 \r
295         //送信対象のメモリブロックを送信中に設定。\r
296 //      b=(i_buf+1);\r
297         //送信中のメモリブロックなら無視\r
298         if(bh->is_lock){\r
299                 return;\r
300         }\r
301         //送信中にセット\r
302         bh->is_lock=NyLPC_TUInt8_TRUE;\r
303 \r
304         //送信データのセット\r
305         Index = LPC_EMAC->TxProduceIndex;\r
306         if (i_size > ETH_FRAG_SIZE){\r
307                 i_size = ETH_FRAG_SIZE;\r
308         }\r
309         //送信処理\r
310         TX_DESC_PACKET( Index ) = ( unsigned long )i_buf;\r
311         //See UM10360.pdf Table 181. Transmit descriptor control word\r
312         TX_DESC_CTRL( Index ) = ((i_size-1) | TCTRL_LAST | TCTRL_INT );\r
313         LPC_EMAC->TxProduceIndex = IndexNext;\r
314         return;\r
315 }\r
316 /**\r
317  * 送信デスクリプタを準備します。\r
318  */\r
319 static void prevTxDescriptor(void)\r
320 {\r
321         long x;\r
322         //デスクリプタの設定\r
323         for( x = 0; x < NUM_TX_FRAG; x++ )\r
324         {\r
325                 TX_DESC_PACKET( x ) = ( unsigned long ) NULL;\r
326                 TX_DESC_CTRL( x ) = 0;\r
327                 TX_STAT_INFO( x ) = 0;\r
328         }\r
329         /* Set LPC_EMAC Transmit Descriptor Registers. */\r
330         LPC_EMAC->TxDescriptor =TX_DESC_BASE;\r
331         LPC_EMAC->TxStatus = TX_STAT_BASE;\r
332         LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1;\r
333 }\r
334 static void prevRxDescriptor(void)\r
335 {\r
336         int x;\r
337         //デスクリプタの設定\r
338         for( x = 0; x < NUM_RX_FRAG; x++ )\r
339         {\r
340                 /* Allocate the next Ethernet buffer to this descriptor. */\r
341                 RX_DESC_PACKET(x) = ETH_BUF(x);\r
342                 RX_DESC_CTRL(x) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 );\r
343                 RX_STAT_INFO(x) = 0;\r
344                 RX_STAT_HASHCRC(x) = 0;\r
345         }\r
346 \r
347         /* Set LPC_EMAC Receive Descriptor Registers. */\r
348         LPC_EMAC->RxDescriptor = RX_DESC_BASE;\r
349         LPC_EMAC->RxStatus = RX_STAT_BASE;\r
350         LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1;\r
351 \r
352 }\r
353 \r
354 \r
355 /**\r
356  * 受信キューの先頭にあるRXフレームのポインタを返します。\r
357  * 関数は、受信キューのポインタを操作しません。続けて読み出したとしても、同じポインターを返します。\r
358  * 制限として、返却したポインタの内容は、一時的に書き換え可としてください。(この制限は将来削除します。)\r
359  * @return\r
360  * 成功した場合、受信データを格納したバッファポインターです。\r
361  * 次回nextRxEthFrameを呼び出すまで有効です。\r
362  */\r
363 static void* getRxEthFrame(unsigned short* o_len_of_data)\r
364 {\r
365         if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )\r
366         {\r
367                 //受信データを返却する。\r
368                 *o_len_of_data = (unsigned short)(( RX_STAT_INFO( LPC_EMAC->RxConsumeIndex ) & RINFO_SIZE ) - 3);\r
369                 return ( unsigned char * ) RX_DESC_PACKET( LPC_EMAC->RxConsumeIndex );\r
370         }\r
371         return NULL;\r
372 }\r
373 \r
374 \r
375 /**\r
376  * 受信キューを進行します。\r
377  */\r
378 static void nextRxEthFrame(void)\r
379 {\r
380         long lIndex;\r
381         if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )\r
382         {\r
383                 //キューすすめる。\r
384                 lIndex = LPC_EMAC->RxConsumeIndex;\r
385                 lIndex++;\r
386                 if( lIndex >= NUM_RX_FRAG )\r
387                 {\r
388                         lIndex = 0;\r
389                 }\r
390                 LPC_EMAC->RxConsumeIndex = lIndex;\r
391         }\r
392 }\r
393 /********************************************************************************\r
394  * Private functions\r
395  *******************************************************************************/\r
396 \r
397 \r
398 \r
399 /**\r
400  * 送信中のイーサフレームを処理する機会を与えて、送信キューが空くまで待ちます。\r
401  * LPC1769の場合は、非同期に更新したディスクリプタの内容から、送信メモリのフラグを更新します。\r
402  * @return\r
403  * 次に書き込むことが出来る送信キュー。\r
404  */\r
405 static NyLPC_TUInt32 waitForTxEthFrameEmpty(void)\r
406 {\r
407         NyLPC_TUInt32   IndexNext;\r
408         struct NyLPC_TTxBufferHeader *b;\r
409         void* p;\r
410         NyLPC_TUInt32 i;\r
411 \r
412         //送信キューの決定\r
413         IndexNext = (LPC_EMAC->TxProduceIndex + 1)%NUM_TX_FRAG;\r
414 \r
415         //送信キューフルが解除されるまで待ち\r
416         while(IndexNext == LPC_EMAC->TxConsumeIndex)\r
417         {\r
418                 //\r
419                 NyLPC_cThread_sleep(emacSHORT_DELAY_MS);\r
420         }\r
421 \r
422         //(TxProduceIndex+1)→TxConsumeIndexにあるデータのsentフラグを消去\r
423         for(i=IndexNext;i!=LPC_EMAC->TxConsumeIndex;i=(i+1)%NUM_TX_FRAG)\r
424         {\r
425                 p=(void*)TX_DESC_PACKET(i);\r
426                 if(p!=NULL){\r
427                         b=NyLPC_TTxBufferHeader_getBufferHeaderAddr(p);\r
428                         b->is_lock=NyLPC_TUInt8_FALSE;\r
429                         TX_DESC_PACKET(i)=0;\r
430                 }\r
431         }\r
432         p=(void*)TX_DESC_PACKET(i);\r
433         if(p!=NULL){\r
434                 b=NyLPC_TTxBufferHeader_getBufferHeaderAddr(p);\r
435                 b->is_lock=NyLPC_TUInt8_FALSE;\r
436                 TX_DESC_PACKET(i)=0;\r
437         }\r
438         return IndexNext;\r
439 }\r
440 \r
441 //--------------------------------------------------------------------------------\r
442 // ISR\r
443 //--------------------------------------------------------------------------------\r
444 \r
445 static void ethernet_set_link(int speed, int duplex) {\r
446     unsigned short phy_data;\r
447     int tout;\r
448     \r
449     if((speed < 0) || (speed > 1)) {\r
450         phy_data = PHY_AUTO_NEG;\r
451     } else {\r
452         phy_data = (((unsigned short) speed << 13) |\r
453                     ((unsigned short) duplex << 8));\r
454     }\r
455     \r
456     phy_write(PHY_REG_BMCR, phy_data);\r
457     \r
458     for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */\r
459     \r
460     switch(phy_id) {\r
461         case DP83848C_ID:\r
462             phy_data = phy_read(PHY_REG_STS);\r
463             \r
464             if(phy_data & PHY_STS_DUPLEX) {\r
465                 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;\r
466                 LPC_EMAC->Command |= CR_FULL_DUP;\r
467                 LPC_EMAC->IPGT = IPGT_FULL_DUP;\r
468             } else {\r
469             LPC_EMAC->MAC2 &= ~MAC2_FULL_DUP;\r
470                 LPC_EMAC->Command &= ~CR_FULL_DUP;\r
471                 LPC_EMAC->IPGT = IPGT_HALF_DUP;\r
472             }\r
473             \r
474             if(phy_data & PHY_STS_SPEED) {\r
475                 LPC_EMAC->SUPP &= ~SUPP_SPEED;\r
476             } else {\r
477                 LPC_EMAC->SUPP |= SUPP_SPEED;\r
478             }\r
479             break;\r
480         \r
481         case LAN8720_ID:\r
482             phy_data = phy_read(PHY_REG_SCSR);\r
483             \r
484             if (phy_data & PHY_SCSR_DUPLEX) {\r
485                 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;\r
486                 LPC_EMAC->Command |= CR_FULL_DUP;\r
487                 LPC_EMAC->IPGT = IPGT_FULL_DUP;\r
488             } else {\r
489                 LPC_EMAC->Command &= ~CR_FULL_DUP;\r
490                 LPC_EMAC->IPGT = IPGT_HALF_DUP;\r
491             }\r
492             \r
493             if(phy_data & PHY_SCSR_100MBIT) {\r
494                 LPC_EMAC->SUPP |= SUPP_SPEED;\r
495             } else {\r
496                 LPC_EMAC->SUPP &= ~SUPP_SPEED;\r
497             }\r
498             \r
499             break;\r
500     }\r
501 }\r
502 \r
503 static int phy_write(unsigned int PhyReg, unsigned short Data) {\r
504     unsigned int timeOut;\r
505 \r
506     LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;\r
507     LPC_EMAC->MWTD = Data;\r
508 \r
509     for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) { /* Wait until operation completed */\r
510         if((LPC_EMAC->MIND & MIND_BUSY) == 0) {\r
511             return 0;\r
512         }\r
513     }\r
514 \r
515     return -1;\r
516 }\r
517 \r
518 \r
519 static int phy_read(unsigned int PhyReg) {\r
520     unsigned int timeOut;\r
521 \r
522     LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;\r
523     LPC_EMAC->MCMD = MCMD_READ;\r
524 \r
525     for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */\r
526         if((LPC_EMAC->MIND & MIND_BUSY) == 0) {\r
527             LPC_EMAC->MCMD = 0;\r
528             return LPC_EMAC->MRDD; /* Return a 16-bit value. */\r
529         }\r
530     }\r
531 \r
532     return -1;\r
533 }\r
534 \r
535 \r
536 //extern unsigned int SystemFrequency;\r
537 static unsigned int clockselect(void)\r
538 {\r
539   if(SystemCoreClock < 10000000) {\r
540     return 1;\r
541   } else if(SystemCoreClock < 15000000) {\r
542     return 2;\r
543   } else if(SystemCoreClock < 20000000) {\r
544     return 3;\r
545   } else if(SystemCoreClock < 25000000) {\r
546     return 4;\r
547   } else if(SystemCoreClock < 35000000) {\r
548     return 5;\r
549   } else if(SystemCoreClock < 50000000) {\r
550     return 6;\r
551   } else if(SystemCoreClock < 70000000) {\r
552     return 7;\r
553   } else if(SystemCoreClock < 80000000) {\r
554     return 8;\r
555   } else if(SystemCoreClock < 90000000) {\r
556     return 9;\r
557   } else if(SystemCoreClock < 100000000) {\r
558     return 10;\r
559   } else if(SystemCoreClock < 120000000) {\r
560     return 11;\r
561   } else if(SystemCoreClock < 130000000) {\r
562     return 12;\r
563   } else if(SystemCoreClock < 140000000) {\r
564     return 13;\r
565   } else if(SystemCoreClock < 150000000) {\r
566     return 15;\r
567   } else if(SystemCoreClock < 160000000) {\r
568     return 16;\r
569   } else {\r
570     return 0;\r
571   }\r
572 }\r
573 \r
574 static int ethernet_link(void)\r
575 {\r
576 \r
577     if (phy_id == DP83848C_ID) {\r
578       return (phy_read(PHY_REG_STS) & PHY_STS_LINK);\r
579     }\r
580     else { // LAN8720_ID\r
581       return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);\r
582     }\r
583 }\r
584 //--------------------------------------------------------------------------------\r
585 // ISR\r
586 //--------------------------------------------------------------------------------\r
587 \r
588 \r
589 /**\r
590  * EMACからのハンドラ\r
591  */\r
592 static void emacIsrHandler(unsigned long i_status)\r
593 {\r
594         if( i_status & INT_RX_DONE )\r
595         {\r
596                 _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_RX);\r
597         }\r
598         if( i_status & INT_TX_DONE )\r
599         {\r
600                 _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_TX);\r
601         }\r
602 }\r
603 \r
604 #endif\r
605 \r
606 \r
607 \r