source: asp3_tinet_ecnl_rx/trunk/bnep_bridge/src/ether_phy.c@ 337

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

ASP3版ECNLを追加

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