source: uKadecot/trunk/uip/target/if_rx62n/ether_phy.c@ 158

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

インクルードのパス指定をContikiに合わせ変更。
整数型の型名をContikiに合わせ変更。

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-chdr; charset=SHIFT_JIS
File size: 10.4 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 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: ether_phy.c 158 2016-02-20 13:43:32Z coas-nagasima $
38 */
39
40#include "ether_phy.h"
41#include <kernel.h>
42#include "net/ip/uip.h"
43#include <sil.h>
44
45#define PHY_CONTROL_REGISTER 0x00
46
47#define PHY_CONTROL_RESET 0x8000
48#define PHY_CONTROL_LOOPBACK 0x4000
49#define PHY_CONTROL_SPEED_SELECT 0x2000
50#define PHY_CONTROL_A_N_ENABLE 0x1000
51#define PHY_CONTROL_POWER_DOWN 0x0800
52#define PHY_CONTROL_ISOLATE 0x0400
53#define PHY_CONTROL_RESTART_A_N 0x0200
54#define PHY_CONTROL_DUPLEX_MODE 0x0100
55#define PHY_CONTROL_COLLISION_TEST 0x0080
56
57#define PHY_STATUS_REGISTER 0x01
58
59#define PHY_STATUS_100BASE_T4 0x8000
60#define PHY_STATUS_100BASE_TX_FULL_DUPLEX 0x4000
61#define PHY_STATUS_100BASE_TX_HALF_DUPLEX 0x2000
62#define PHY_STATUS_10BASE_T_FULL_DUPLEX 0x1000
63#define PHY_STATUS_10BASE_T_HALF_DUPLEX 0x0800
64#define PHY_STATUS_A_N_COMPLETE 0x0020
65#define PHY_STATUS_REMOTE_FAULT 0x0010
66#define PHY_STATUS_A_N_ABILITY 0x0008
67#define PHY_STATUS_LINK_STATUS 0x0004
68#define PHY_STATUS_JABBER_DETECT 0x0002
69#define PHY_STATUS_EXTENDED_CAPABILITY 0x0001
70
71#define PHY_AN_ADVERTISEMENT_REGISTER 0x04
72
73#define PHY_AN_AD_100BASE_T4 0x0200
74#define PHY_AN_AD_100BASE_TX_FULL_DUPLEX 0x0100
75#define PHY_AN_AD_100BASE_TX_HALF_DUPLEX 0x0080
76#define PHY_AN_AD_10BASE_T_FULL_DUPLEX 0x0040
77#define PHY_AN_AD_10BASE_T_HALF_DUPLEX 0x0020
78#define PHY_AN_AD_SELECTOR_FIELD 0x0001
79
80#define PHY_AN_STATUS_REGISTER 0x05
81
82#define PHY_AN_STATUS_100BASE_T4 0x0200
83#define PHY_AN_STATUS_100BASE_TX_FULL_DUPLEX 0x0100
84#define PHY_AN_STATUS_100BASE_TX_HALF_DUPLEX 0x0080
85#define PHY_AN_STATUS_10BASE_T_FULL_DUPLEX 0x0040
86#define PHY_AN_STATUS_10BASE_T_HALF_DUPLEX 0x0020
87
88static void phy_write_bit(bool_t bit);
89static void phy_release_bus();
90static bool_t phy_read_bit();
91static void phy_single_rel_bus();
92
93PHY_STATE_T phy_reset(PHY_STATE_T state, uint8_t phy_addr)
94{
95 switch(state){
96 case PHY_STATE_UNINIT:
97 /* PHYのリセット */
98 phy_write_reg(phy_addr, PHY_CONTROL_REGISTER, PHY_CONTROL_RESET);
99
100 /* 500ms待つ */
101 /* tslp_tsk(500); 不要? */
102 /* continue; */
103 case PHY_STATE_RESETING:
104 /* リセット完了の確認 */
105 if((phy_read_reg(phy_addr, PHY_CONTROL_REGISTER) & PHY_CONTROL_RESET) != 0)
106 return PHY_STATE_RESETING;
107
108 return PHY_STATE_RESET;
109 default:
110 return state;
111 }
112}
113
114PHY_STATE_T phy_initialize(PHY_STATE_T state, uint8_t phy_addr, PHY_MODE_T *mode)
115{
116#ifndef __RX
117 static int reset = 0;
118#endif
119 uint16_t status;
120 *mode = (PHY_MODE_T)0;
121
122 switch(state){
123 case PHY_STATE_RESET:
124#ifndef __RX
125 reset++;
126 if(reset < 2){
127#endif
128 /* リンク完了の確認 */
129 if(!phy_is_link(phy_addr))
130 return PHY_STATE_RESET;
131#ifndef __RX
132 }
133 reset = 0;
134#endif
135 /* オートネゴシエーションのお知らせを有効に設定 */
136 phy_write_reg(phy_addr, PHY_AN_ADVERTISEMENT_REGISTER,
137 PHY_AN_AD_100BASE_T4 | PHY_AN_AD_100BASE_TX_FULL_DUPLEX | PHY_AN_AD_100BASE_TX_HALF_DUPLEX
138 | PHY_AN_AD_10BASE_T_FULL_DUPLEX | PHY_AN_AD_10BASE_T_HALF_DUPLEX | PHY_AN_AD_SELECTOR_FIELD);
139
140 /* オートネゴシエーションを有効に設定 */
141 phy_write_reg(phy_addr, PHY_CONTROL_REGISTER, PHY_CONTROL_SPEED_SELECT | PHY_CONTROL_A_N_ENABLE);
142
143 /* continue; */
144 case PHY_STATE_LINKED:
145#ifndef __RX
146 reset++;
147 if(reset < 2){
148#endif
149 /* オートネゴシエーション完了の確認 */
150 if((phy_read_reg(phy_addr, PHY_STATUS_REGISTER) & PHY_STATUS_A_N_COMPLETE) == 0)
151 return PHY_STATE_LINKED;
152#ifndef __RX
153 }
154#endif
155 status = phy_read_reg(phy_addr, PHY_AN_STATUS_REGISTER);
156
157 if ((status & (PHY_AN_STATUS_100BASE_T4 | PHY_AN_STATUS_10BASE_T_FULL_DUPLEX | PHY_AN_STATUS_100BASE_TX_FULL_DUPLEX)) != 0)
158 *mode = (PHY_MODE_T)(((int)*mode) | 0x01);
159
160 if ((status & (PHY_AN_STATUS_100BASE_T4 | PHY_AN_STATUS_100BASE_TX_FULL_DUPLEX | PHY_AN_STATUS_100BASE_TX_HALF_DUPLEX)) != 0)
161 *mode = (PHY_MODE_T)(((int)*mode) | 0x02);
162
163 return PHY_STATE_NEGOTIATED;
164 }
165
166 return state;
167}
168
169bool_t phy_is_link(uint8_t phy_addr)
170{
171#ifdef __RX
172 /* リンクの確認 */
173 return (phy_read_reg(phy_addr, PHY_STATUS_REGISTER) & PHY_STATUS_LINK_STATUS) != 0;
174#else
175 return true;
176#endif
177}
178
179uint16_t phy_read_reg(uint8_t phy_addr, uint8_t reg_addr)
180{
181 uint16_t result = 0, bit;
182 int i;
183
184 /* PRE :32個の連続した1b */
185 for (i = 0; i < 32; i++)
186 phy_write_bit(true);
187
188 /* ST :フレームの先頭を示す01bのライト */
189 phy_write_bit(false);
190 phy_write_bit(true);
191
192 /* OP :アクセス種別を示すコードのライト */
193 phy_write_bit(true);
194 phy_write_bit(false);
195
196 /* PHYAD :PHY-LSIのアドレスが1番の場合、00001bをライト(MSB から順次ライト)。 */
197 phy_write_bit((phy_addr & 0x10) != 0);
198 phy_write_bit((phy_addr & 0x08) != 0);
199 phy_write_bit((phy_addr & 0x04) != 0);
200 phy_write_bit((phy_addr & 0x02) != 0);
201 phy_write_bit((phy_addr & 0x01) != 0);
202
203 /* REGAD :レジスタアドレスが1番の場合、00001bをライト(MSBから順次ライト)。 */
204 phy_write_bit((reg_addr & 0x10) != 0);
205 phy_write_bit((reg_addr & 0x08) != 0);
206 phy_write_bit((reg_addr & 0x04) != 0);
207 phy_write_bit((reg_addr & 0x02) != 0);
208 phy_write_bit((reg_addr & 0x01) != 0);
209
210 /* TA :MII/RMIIインタフェース上でデータの送信元を切り替える時間 */
211 /* 「バス解放」(Z0と表記)を行う */
212 phy_release_bus();
213
214 /* DATA :16ビットのデータ。MSBから順次リード */
215 for (bit = 0x8000; bit != 0; bit >>= 1) {
216 if(phy_read_bit())
217 result |= bit;
218 }
219
220 /* IDLE :次のMII管理フォーマット入力までの待機時間 */
221 /* すでにTA時にバス解放済みであり制御不要 */
222 phy_release_bus();
223
224 return result;
225}
226
227void phy_write_reg(uint8_t phy_addr, uint8_t reg_addr, uint16_t reg_data)
228{
229 int i;
230 uint16_t bit;
231
232 /* PRE :32個の連続した1b */
233 for (i = 0; i < 32; i++)
234 phy_write_bit(true);
235
236 /* ST :フレームの先頭を示す01bのライト */
237 phy_write_bit(false);
238 phy_write_bit(true);
239
240 /* OP :アクセス種別を示すコードのライト */
241 phy_write_bit(false);
242 phy_write_bit(true);
243
244 /* PHYAD :PHY-LSIのアドレスが1番の場合、00001bをライト(MSB から順次ライト)。 */
245 phy_write_bit((phy_addr & 0x10) != 0);
246 phy_write_bit((phy_addr & 0x08) != 0);
247 phy_write_bit((phy_addr & 0x04) != 0);
248 phy_write_bit((phy_addr & 0x02) != 0);
249 phy_write_bit((phy_addr & 0x01) != 0);
250
251 /* REGAD :レジスタアドレスが1番の場合、00001bをライト(MSBから順次ライト)。 */
252 phy_write_bit((reg_addr & 0x10) != 0);
253 phy_write_bit((reg_addr & 0x08) != 0);
254 phy_write_bit((reg_addr & 0x04) != 0);
255 phy_write_bit((reg_addr & 0x02) != 0);
256 phy_write_bit((reg_addr & 0x01) != 0);
257
258 /* TA :MII/RMIIインタフェース上でデータの送信元を切り替える時間 */
259 /* 10bをライト */
260 phy_write_bit(true);
261 phy_write_bit(false);
262
263 /* DATA :16ビットのデータ。MSBから順次ライト */
264 for (bit = 0x8000; bit != 0; bit >>= 1) {
265 phy_write_bit((reg_data & bit) != 0);
266 }
267
268 /* IDLE :次のMII管理フォーマット入力までの待機時間 */
269 /* 「単独バス解放」(Xと表記)を行う */
270 phy_single_rel_bus();
271}
272
273#define ETHERC_PIR_WAIT 4
274
275/*
276 * 1 ビットデータのライト
277 */
278static void phy_write_bit(bool_t bit)
279{
280 int i;
281 uint32_t data = bit ? ETHERC_PIR_MDO : 0;
282
283 /* PHY部インタフェースレジスタへのライト */
284 sil_wrw_mem(ETHERC_PIR, data | ETHERC_PIR_MMD | 0/*ETHERC_PIR_MDC*/);
285
286 for(i = ETHERC_PIR_WAIT; i > 0; i--);
287
288 /* PHY部インタフェースレジスタへのライト */
289 sil_wrw_mem(ETHERC_PIR, data | ETHERC_PIR_MMD | ETHERC_PIR_MDC);
290
291 for(i = 2 * ETHERC_PIR_WAIT; i > 0; i--);
292
293 /* PHY部インタフェースレジスタへのライト */
294 sil_wrw_mem(ETHERC_PIR, data | ETHERC_PIR_MMD | 0/*ETHERC_PIR_MDC*/);
295
296 for(i = ETHERC_PIR_WAIT; i > 0; i--);
297}
298
299/*
300 * バス解放
301 */
302static void phy_release_bus()
303{
304 int i;
305
306 /* PHY部インタフェースレジスタへのライト */
307 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
308
309 for(i = ETHERC_PIR_WAIT; i > 0; i--);
310
311 /* PHY部インタフェースレジスタへのライト */
312 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | ETHERC_PIR_MDC);
313
314 for(i = 2 * ETHERC_PIR_WAIT; i > 0; i--);
315
316 /* PHY部インタフェースレジスタへのライト */
317 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
318
319 for(i = ETHERC_PIR_WAIT; i > 0; i--);
320}
321
322/*
323 * 1 ビットデータのリード
324 */
325static bool_t phy_read_bit()
326{
327 bool_t bit;
328 int i;
329
330 for(i = ETHERC_PIR_WAIT; i > 0; i--);
331
332 /* PHY部インタフェースレジスタへのライト */
333 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | ETHERC_PIR_MDC);
334
335 for(i = ETHERC_PIR_WAIT; i > 0; i--);
336
337 /* PHY部インタフェースレジスタへのライト */
338 bit = (sil_rew_mem(ETHERC_PIR) & ETHERC_PIR_MDI) != 0;
339
340 for(i = 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
347 return bit;
348}
349
350/*
351 * 単独バス解放
352 */
353static void phy_single_rel_bus()
354{
355 int i;
356
357 for(i = ETHERC_PIR_WAIT; i > 0; i--);
358
359 /* PHY部インタフェースレジスタへのライト */
360 sil_wrw_mem(ETHERC_PIR, ETHERC_PIR_MMD | ETHERC_PIR_MDC);
361
362 for(i = 2 * ETHERC_PIR_WAIT; i > 0; i--);
363
364 /* PHY部インタフェースレジスタへのライト */
365 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
366
367 for(i = ETHERC_PIR_WAIT; i > 0; i--);
368}
Note: See TracBrowser for help on using the repository browser.