source: azure_iot_hub/trunk/asp3_dcre/tinet/netdev/if_rx62n/ether_phy.c@ 388

Last change on this file since 388 was 388, checked in by coas-nagasima, 5 years ago

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 11.9 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2009 by Dep. of Computer Science and Engineering
5 * Tomakomai National College of Technology, JAPAN
6 * Copyright (C) 2014-2017 by Cores Co., Ltd. Japan
7 *
8 * 上記著作権者
9は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
10 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11 * 変・再é…
12å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
13 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15 * スコード中に含まれていること.
16 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17 * 用できる形で再é…
18å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
19å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
20 * 者
21マニュアルなど)に,上記の著作権表示,この利用条件および下記
22 * の無保証規定を掲載すること.
23 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
24 * 用できない形で再é…
25å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
26 * と.
27 * (a) 再é…
28å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
29マニュアルなど)に,上記の著
30 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
31 * (b) 再é…
32å¸ƒã®å½¢æ…
33‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
34 * 報告すること.
35 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
36 * 害からも,上記著作権者
37およびTOPPERSプロジェクトをå…
38è²¬ã™ã‚‹ã“と.
39 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
40 * 由に基づく請求からも,上記著作権者
41およびTOPPERSプロジェクトを
42 * å…
43è²¬ã™ã‚‹ã“と.
44 *
45 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
46お
47 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
48 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
49 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
50 * の責任を負わない.
51 *
52 * @(#) $Id: ether_phy.c 388 2019-05-22 11:25:18Z coas-nagasima $
53 */
54
55#include "ether_phy.h"
56#include <kernel.h>
57#include <sil.h>
58
59#define PHY_CONTROL_REGISTER 0x00
60
61#define PHY_CONTROL_RESET 0x8000
62#define PHY_CONTROL_LOOPBACK 0x4000
63#define PHY_CONTROL_SPEED_SELECT 0x2000
64#define PHY_CONTROL_A_N_ENABLE 0x1000
65#define PHY_CONTROL_POWER_DOWN 0x0800
66#define PHY_CONTROL_ISOLATE 0x0400
67#define PHY_CONTROL_RESTART_A_N 0x0200
68#define PHY_CONTROL_DUPLEX_MODE 0x0100
69#define PHY_CONTROL_COLLISION_TEST 0x0080
70
71#define PHY_STATUS_REGISTER 0x01
72
73#define PHY_STATUS_100BASE_T4 0x8000
74#define PHY_STATUS_100BASE_TX_FULL_DUPLEX 0x4000
75#define PHY_STATUS_100BASE_TX_HALF_DUPLEX 0x2000
76#define PHY_STATUS_10BASE_T_FULL_DUPLEX 0x1000
77#define PHY_STATUS_10BASE_T_HALF_DUPLEX 0x0800
78#define PHY_STATUS_A_N_COMPLETE 0x0020
79#define PHY_STATUS_REMOTE_FAULT 0x0010
80#define PHY_STATUS_A_N_ABILITY 0x0008
81#define PHY_STATUS_LINK_STATUS 0x0004
82#define PHY_STATUS_JABBER_DETECT 0x0002
83#define PHY_STATUS_EXTENDED_CAPABILITY 0x0001
84
85#define PHY_AN_ADVERTISEMENT_REGISTER 0x04
86
87#define PHY_AN_AD_100BASE_T4 0x0200
88#define PHY_AN_AD_100BASE_TX_FULL_DUPLEX 0x0100
89#define PHY_AN_AD_100BASE_TX_HALF_DUPLEX 0x0080
90#define PHY_AN_AD_10BASE_T_FULL_DUPLEX 0x0040
91#define PHY_AN_AD_10BASE_T_HALF_DUPLEX 0x0020
92#define PHY_AN_AD_SELECTOR_FIELD 0x0001
93
94#define PHY_AN_STATUS_REGISTER 0x05
95
96#define PHY_AN_STATUS_100BASE_T4 0x0200
97#define PHY_AN_STATUS_100BASE_TX_FULL_DUPLEX 0x0100
98#define PHY_AN_STATUS_100BASE_TX_HALF_DUPLEX 0x0080
99#define PHY_AN_STATUS_10BASE_T_FULL_DUPLEX 0x0040
100#define PHY_AN_STATUS_10BASE_T_HALF_DUPLEX 0x0020
101
102static void phy_write_bit(bool_t bit);
103static void phy_release_bus();
104static bool_t phy_read_bit();
105static void phy_single_rel_bus();
106
107PHY_STATE_T phy_reset(PHY_STATE_T state, uint8_t phy_addr)
108{
109 switch(state){
110 case PHY_STATE_UNINIT:
111 /* PHYのリセット */
112 phy_write_reg(phy_addr, PHY_CONTROL_REGISTER, PHY_CONTROL_RESET);
113
114 /* 500ms待
115つ */
116 dly_tsk(500 * 1000);
117 /* continue; */
118 case PHY_STATE_RESETING:
119 /* リセット完了の確認 */
120 if((phy_read_reg(phy_addr, PHY_CONTROL_REGISTER) & PHY_CONTROL_RESET) != 0)
121 return PHY_STATE_RESETING;
122
123 return PHY_STATE_RESET;
124 default:
125 return state;
126 }
127}
128
129PHY_STATE_T phy_initialize(PHY_STATE_T state, uint8_t phy_addr, PHY_MODE_T *mode)
130{
131#if defined(_MSC_VER) || defined(__c2__)
132 static int reset = 0;
133#endif
134 uint16_t status;
135 *mode = (PHY_MODE_T)0;
136
137 switch(state){
138 case PHY_STATE_RESET:
139 /* オートネゴシエーションのお知らせを有効に設定 */
140 phy_write_reg(phy_addr, PHY_AN_ADVERTISEMENT_REGISTER,
141 PHY_AN_AD_100BASE_T4 | PHY_AN_AD_100BASE_TX_FULL_DUPLEX | PHY_AN_AD_100BASE_TX_HALF_DUPLEX
142 | PHY_AN_AD_10BASE_T_FULL_DUPLEX | PHY_AN_AD_10BASE_T_HALF_DUPLEX | PHY_AN_AD_SELECTOR_FIELD);
143
144 /* オートネゴシエーションを有効に設定 */
145 phy_write_reg(phy_addr, PHY_CONTROL_REGISTER, PHY_CONTROL_SPEED_SELECT | PHY_CONTROL_A_N_ENABLE);
146 /* continue; */
147 case PHY_STATE_LINKE_WAIT:
148#if defined(_MSC_VER) || defined(__c2__)
149 reset++;
150 if(reset < 2){
151#endif
152 /* リンク完了の確認 */
153 if(!phy_is_link(phy_addr))
154 return PHY_STATE_LINKE_WAIT;
155#if defined(_MSC_VER) || defined(__c2__)
156 }
157 reset = 0;
158#endif
159 /* continue; */
160 case PHY_STATE_LINKED:
161#if defined(_MSC_VER) || defined(__c2__)
162 reset++;
163 if(reset < 2){
164#endif
165 /* オートネゴシエーション完了の確認 */
166 if((phy_read_reg(phy_addr, PHY_STATUS_REGISTER) & PHY_STATUS_A_N_COMPLETE) == 0)
167 return PHY_STATE_LINKED;
168#if defined(_MSC_VER) || defined(__c2__)
169 }
170#endif
171 status = phy_read_reg(phy_addr, PHY_AN_STATUS_REGISTER);
172
173 if ((status & (PHY_AN_STATUS_100BASE_T4 | PHY_AN_STATUS_10BASE_T_FULL_DUPLEX | PHY_AN_STATUS_100BASE_TX_FULL_DUPLEX)) != 0)
174 *mode = (PHY_MODE_T)(((int)*mode) | 0x01);
175
176 if ((status & (PHY_AN_STATUS_100BASE_T4 | PHY_AN_STATUS_100BASE_TX_FULL_DUPLEX | PHY_AN_STATUS_100BASE_TX_HALF_DUPLEX)) != 0)
177 *mode = (PHY_MODE_T)(((int)*mode) | 0x02);
178
179 return PHY_STATE_NEGOTIATED;
180 }
181
182 return state;
183}
184
185bool_t phy_is_link(uint8_t phy_addr)
186{
187#if !defined(_MSC_VER) && !defined(__c2__)
188 /* リンクの確認 */
189 return (phy_read_reg(phy_addr, PHY_STATUS_REGISTER) & PHY_STATUS_LINK_STATUS) != 0;
190#else
191 return true;
192#endif
193}
194
195uint16_t phy_read_reg(uint8_t phy_addr, uint8_t reg_addr)
196{
197 uint16_t result = 0, bit;
198 int i;
199
200 /* PRE :32個の連続した1b */
201 for (i = 0; i < 32; i++)
202 phy_write_bit(true);
203
204 /* ST :フレームのå…
205ˆé ­ã‚’示す01bのライト */
206 phy_write_bit(false);
207 phy_write_bit(true);
208
209 /* OP :アクセス種別を示すコードのライト */
210 phy_write_bit(true);
211 phy_write_bit(false);
212
213 /* PHYAD :PHY-LSIのアドレスが1番の場合、00001bをライト(MSB から順次ライト)。 */
214 phy_write_bit((phy_addr & 0x10) != 0);
215 phy_write_bit((phy_addr & 0x08) != 0);
216 phy_write_bit((phy_addr & 0x04) != 0);
217 phy_write_bit((phy_addr & 0x02) != 0);
218 phy_write_bit((phy_addr & 0x01) != 0);
219
220 /* REGAD :レジスタアドレスが1番の場合、00001bをライト(MSBから順次ライト)。 */
221 phy_write_bit((reg_addr & 0x10) != 0);
222 phy_write_bit((reg_addr & 0x08) != 0);
223 phy_write_bit((reg_addr & 0x04) != 0);
224 phy_write_bit((reg_addr & 0x02) != 0);
225 phy_write_bit((reg_addr & 0x01) != 0);
226
227 /* TA :MII/RMIIインタフェース上でデータの送信å…
228ƒã‚’切り替える時間 */
229 /* 「バス解放」(Z0と表記)を行う */
230 phy_release_bus();
231
232 /* DATA :16ビットのデータ。MSBから順次リード */
233 for (bit = 0x8000; bit != 0; bit >>= 1) {
234 if(phy_read_bit())
235 result |= bit;
236 }
237
238 /* IDLE :次のMII管理フォーマットå…
239¥åŠ›ã¾ã§ã®å¾…
240機時間 */
241 /* すでにTA時にバス解放済みであり制御不要 */
242 phy_release_bus();
243
244 return result;
245}
246
247void phy_write_reg(uint8_t phy_addr, uint8_t reg_addr, uint16_t reg_data)
248{
249 int i;
250 uint16_t bit;
251
252 /* PRE :32個の連続した1b */
253 for (i = 0; i < 32; i++)
254 phy_write_bit(true);
255
256 /* ST :フレームのå…
257ˆé ­ã‚’示す01bのライト */
258 phy_write_bit(false);
259 phy_write_bit(true);
260
261 /* OP :アクセス種別を示すコードのライト */
262 phy_write_bit(false);
263 phy_write_bit(true);
264
265 /* PHYAD :PHY-LSIのアドレスが1番の場合、00001bをライト(MSB から順次ライト)。 */
266 phy_write_bit((phy_addr & 0x10) != 0);
267 phy_write_bit((phy_addr & 0x08) != 0);
268 phy_write_bit((phy_addr & 0x04) != 0);
269 phy_write_bit((phy_addr & 0x02) != 0);
270 phy_write_bit((phy_addr & 0x01) != 0);
271
272 /* REGAD :レジスタアドレスが1番の場合、00001bをライト(MSBから順次ライト)。 */
273 phy_write_bit((reg_addr & 0x10) != 0);
274 phy_write_bit((reg_addr & 0x08) != 0);
275 phy_write_bit((reg_addr & 0x04) != 0);
276 phy_write_bit((reg_addr & 0x02) != 0);
277 phy_write_bit((reg_addr & 0x01) != 0);
278
279 /* TA :MII/RMIIインタフェース上でデータの送信å…
280ƒã‚’切り替える時間 */
281 /* 10bをライト */
282 phy_write_bit(true);
283 phy_write_bit(false);
284
285 /* DATA :16ビットのデータ。MSBから順次ライト */
286 for (bit = 0x8000; bit != 0; bit >>= 1) {
287 phy_write_bit((reg_data & bit) != 0);
288 }
289
290 /* IDLE :次のMII管理フォーマットå…
291¥åŠ›ã¾ã§ã®å¾…
292機時間 */
293 /* 「単独バス解放」(Xと表記)を行う */
294 phy_single_rel_bus();
295}
296
297#define ETHERC_PIR_WAIT 4
298
299/*
300 * 1 ビットデータのライト
301 */
302static void phy_write_bit(bool_t bit)
303{
304 int i;
305 uint32_t data = bit ? ETHERC_PIR_MDO : 0;
306
307 /* PHY部インタフェースレジスタへのライト */
308 sil_wrw_mem(ETHERC_PIR, data | ETHERC_PIR_MMD | 0/*ETHERC_PIR_MDC*/);
309
310 for(i = ETHERC_PIR_WAIT; i > 0; i--);
311
312 /* PHY部インタフェースレジスタへのライト */
313 sil_wrw_mem(ETHERC_PIR, data | ETHERC_PIR_MMD | ETHERC_PIR_MDC);
314
315 for(i = 2 * ETHERC_PIR_WAIT; i > 0; i--);
316
317 /* PHY部インタフェースレジスタへのライト */
318 sil_wrw_mem(ETHERC_PIR, data | ETHERC_PIR_MMD | 0/*ETHERC_PIR_MDC*/);
319
320 for(i = ETHERC_PIR_WAIT; i > 0; i--);
321}
322
323/*
324 * バス解放
325 */
326static void phy_release_bus()
327{
328 int i;
329
330 /* PHY部インタフェースレジスタへのライト */
331 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
332
333 for(i = ETHERC_PIR_WAIT; i > 0; i--);
334
335 /* PHY部インタフェースレジスタへのライト */
336 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | ETHERC_PIR_MDC);
337
338 for(i = 2 * ETHERC_PIR_WAIT; i > 0; i--);
339
340 /* PHY部インタフェースレジスタへのライト */
341 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
342
343 for(i = ETHERC_PIR_WAIT; i > 0; i--);
344}
345
346/*
347 * 1 ビットデータのリード
348 */
349static bool_t phy_read_bit()
350{
351 bool_t bit;
352 int i;
353
354 for(i = ETHERC_PIR_WAIT; i > 0; i--);
355
356 /* PHY部インタフェースレジスタへのライト */
357 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | ETHERC_PIR_MDC);
358
359 for(i = ETHERC_PIR_WAIT; i > 0; i--);
360
361 /* PHY部インタフェースレジスタへのライト */
362 bit = (sil_rew_mem(ETHERC_PIR) & ETHERC_PIR_MDI) != 0;
363
364 for(i = ETHERC_PIR_WAIT; i > 0; i--);
365
366 /* PHY部インタフェースレジスタへのライト */
367 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
368
369 for(i = ETHERC_PIR_WAIT; i > 0; i--);
370
371 return bit;
372}
373
374/*
375 * 単独バス解放
376 */
377static void phy_single_rel_bus()
378{
379 int i;
380
381 for(i = ETHERC_PIR_WAIT; i > 0; i--);
382
383 /* PHY部インタフェースレジスタへのライト */
384 sil_wrw_mem(ETHERC_PIR, ETHERC_PIR_MMD | ETHERC_PIR_MDC);
385
386 for(i = 2 * ETHERC_PIR_WAIT; i > 0; i--);
387
388 /* PHY部インタフェースレジスタへのライト */
389 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
390
391 for(i = ETHERC_PIR_WAIT; i > 0; i--);
392}
Note: See TracBrowser for help on using the repository browser.