source: rubycfg_asp/trunk/asp_dcre/tinet/netdev/if_rx62n/ether_phy.c@ 315

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

SVNプロパティを設定

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc; charset=UTF-8
File size: 11.2 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 315 2017-07-23 05:29:40Z coas-nagasima $
38 */
39
40#include "ether_phy.h"
41#include <kernel.h>
42#include <tinet_config.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
93void phy_reset(uint8_t phy_addr)
94{
95#ifndef _MSC_VER
96 /* PHYのリセット */
97 phy_write_reg(phy_addr, PHY_CONTROL_REGISTER, PHY_CONTROL_RESET);
98
99 /* 500ms待つ */
100 /* tslp_tsk(500); 不要? */
101
102 /* リセット完了の確認 */
103 while((phy_read_reg(phy_addr, PHY_CONTROL_REGISTER) & PHY_CONTROL_RESET) != 0)
104 tslp_tsk(1);
105#endif
106}
107
108enum phy_mode_t phy_initialize(uint8_t phy_addr)
109{
110 uint_t result = 0;
111 uint16_t status;
112#ifndef _MSC_VER
113 /* リンク完了の確認 */
114 while((phy_read_reg(phy_addr, PHY_STATUS_REGISTER) & PHY_STATUS_LINK_STATUS) == 0)
115 tslp_tsk(1);
116
117 /* オートネゴシエーションのお知らせを有効に設定 */
118 phy_write_reg(phy_addr, PHY_AN_ADVERTISEMENT_REGISTER,
119 PHY_AN_AD_100BASE_T4 | PHY_AN_AD_100BASE_TX_FULL_DUPLEX | PHY_AN_AD_100BASE_TX_HALF_DUPLEX
120 | PHY_AN_AD_10BASE_T_FULL_DUPLEX | PHY_AN_AD_10BASE_T_HALF_DUPLEX | PHY_AN_AD_SELECTOR_FIELD);
121
122 /* オートネゴシエーションを有効に設定 */
123 phy_write_reg(phy_addr, PHY_CONTROL_REGISTER, PHY_CONTROL_SPEED_SELECT | PHY_CONTROL_A_N_ENABLE);
124
125 /* オートネゴシエーション完了の確認 */
126 while((phy_read_reg(phy_addr, PHY_STATUS_REGISTER) & PHY_STATUS_A_N_COMPLETE) == 0)
127 tslp_tsk(1);
128
129 status = phy_read_reg(phy_addr, PHY_AN_STATUS_REGISTER);
130
131 if ((status & (PHY_AN_STATUS_10BASE_T_FULL_DUPLEX | PHY_AN_STATUS_100BASE_TX_FULL_DUPLEX)) != 0)
132 result |= 0x01;
133
134 if ((status & (PHY_AN_STATUS_100BASE_TX_FULL_DUPLEX | PHY_AN_STATUS_100BASE_TX_HALF_DUPLEX)) != 0)
135 result |= 0x02;
136#endif
137 return (enum phy_mode_t)result;
138}
139
140bool_t phy_is_link(uint8_t phy_addr)
141{
142#ifndef _MSC_VER
143 /* リンクの確認 */
144 return (phy_read_reg(phy_addr, PHY_STATUS_REGISTER) & PHY_STATUS_LINK_STATUS) == 0;
145#else
146 return true;
147#endif
148}
149
150uint16_t phy_read_reg(uint8_t phy_addr, uint8_t reg_addr)
151{
152 uint16_t result = 0, bit;
153 int i;
154
155 /* PRE :32個の連続した1b */
156 for (i = 0; i < 32; i++)
157 phy_write_bit(true);
158
159 /* ST :フレームの先頭を示す01bのライト */
160 phy_write_bit(false);
161 phy_write_bit(true);
162
163 /* OP :アクセス種別を示すコードのライト */
164 phy_write_bit(true);
165 phy_write_bit(false);
166
167 /* PHYAD :PHY-LSIのアドレスが1番の場合、00001bをライト(MSB から順次ライト)。 */
168 phy_write_bit((phy_addr & 0x10) != 0);
169 phy_write_bit((phy_addr & 0x08) != 0);
170 phy_write_bit((phy_addr & 0x04) != 0);
171 phy_write_bit((phy_addr & 0x02) != 0);
172 phy_write_bit((phy_addr & 0x01) != 0);
173
174 /* REGAD :レジスタアドレスが1番の場合、00001bをライト(MSBから順次ライト)。 */
175 phy_write_bit((reg_addr & 0x10) != 0);
176 phy_write_bit((reg_addr & 0x08) != 0);
177 phy_write_bit((reg_addr & 0x04) != 0);
178 phy_write_bit((reg_addr & 0x02) != 0);
179 phy_write_bit((reg_addr & 0x01) != 0);
180
181 /* TA :MII/RMIIインタフェース上でデータの送信元を切り替える時間 */
182 /* 「バス解放」(Z0と表記)を行う */
183 phy_release_bus();
184
185 /* DATA :16ビットのデータ。MSBから順次リード */
186 for (bit = 0x8000; bit != 0; bit >>= 1) {
187 if(phy_read_bit())
188 result |= bit;
189 }
190
191 /* IDLE :次のMII管理フォーマット入力までの待機時間 */
192 /* すでにTA時にバス解放済みであり制御不要 */
193 phy_release_bus();
194
195 return result;
196}
197
198void phy_write_reg(uint8_t phy_addr, uint8_t reg_addr, uint16_t reg_data)
199{
200 int i;
201 uint16_t bit;
202
203 /* PRE :32個の連続した1b */
204 for (i = 0; i < 32; i++)
205 phy_write_bit(true);
206
207 /* ST :フレームの先頭を示す01bのライト */
208 phy_write_bit(false);
209 phy_write_bit(true);
210
211 /* OP :アクセス種別を示すコードのライト */
212 phy_write_bit(false);
213 phy_write_bit(true);
214
215 /* PHYAD :PHY-LSIのアドレスが1番の場合、00001bをライト(MSB から順次ライト)。 */
216 phy_write_bit((phy_addr & 0x10) != 0);
217 phy_write_bit((phy_addr & 0x08) != 0);
218 phy_write_bit((phy_addr & 0x04) != 0);
219 phy_write_bit((phy_addr & 0x02) != 0);
220 phy_write_bit((phy_addr & 0x01) != 0);
221
222 /* REGAD :レジスタアドレスが1番の場合、00001bをライト(MSBから順次ライト)。 */
223 phy_write_bit((reg_addr & 0x10) != 0);
224 phy_write_bit((reg_addr & 0x08) != 0);
225 phy_write_bit((reg_addr & 0x04) != 0);
226 phy_write_bit((reg_addr & 0x02) != 0);
227 phy_write_bit((reg_addr & 0x01) != 0);
228
229 /* TA :MII/RMIIインタフェース上でデータの送信元を切り替える時間 */
230 /* 10bをライト */
231 phy_write_bit(true);
232 phy_write_bit(false);
233
234 /* DATA :16ビットのデータ。MSBから順次ライト */
235 for (bit = 0x8000; bit != 0; bit >>= 1) {
236 phy_write_bit((reg_data & bit) != 0);
237 }
238
239 /* IDLE :次のMII管理フォーマット入力までの待機時間 */
240 /* 「単独バス解放」(Xと表記)を行う */
241 phy_single_rel_bus();
242}
243
244#define ETHERC_PIR_WAIT 4
245
246/*
247 * 1 ビットデータのライト
248 */
249static void phy_write_bit(bool_t bit)
250{
251 int i;
252 uint32_t data = bit ? ETHERC_PIR_MDO : 0;
253
254 /* PHY部インタフェースレジスタへのライト */
255 sil_wrw_mem(ETHERC_PIR, data | ETHERC_PIR_MMD | 0/*ETHERC_PIR_MDC*/);
256
257 for(i = ETHERC_PIR_WAIT; i > 0; i--);
258
259 /* PHY部インタフェースレジスタへのライト */
260 sil_wrw_mem(ETHERC_PIR, data | ETHERC_PIR_MMD | ETHERC_PIR_MDC);
261
262 for(i = 2 * ETHERC_PIR_WAIT; i > 0; i--);
263
264 /* PHY部インタフェースレジスタへのライト */
265 sil_wrw_mem(ETHERC_PIR, data | ETHERC_PIR_MMD | 0/*ETHERC_PIR_MDC*/);
266
267 for(i = ETHERC_PIR_WAIT; i > 0; i--);
268}
269
270/*
271 * バス解放
272 */
273static void phy_release_bus()
274{
275 int i;
276
277 /* PHY部インタフェースレジスタへのライト */
278 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
279
280 for(i = ETHERC_PIR_WAIT; i > 0; i--);
281
282 /* PHY部インタフェースレジスタへのライト */
283 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | ETHERC_PIR_MDC);
284
285 for(i = 2 * ETHERC_PIR_WAIT; i > 0; i--);
286
287 /* PHY部インタフェースレジスタへのライト */
288 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
289
290 for(i = ETHERC_PIR_WAIT; i > 0; i--);
291}
292
293/*
294 * 1 ビットデータのリード
295 */
296static bool_t phy_read_bit()
297{
298 bool_t bit;
299 int i;
300
301 for(i = ETHERC_PIR_WAIT; i > 0; i--);
302
303 /* PHY部インタフェースレジスタへのライト */
304 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | ETHERC_PIR_MDC);
305
306 for(i = ETHERC_PIR_WAIT; i > 0; i--);
307
308 /* PHY部インタフェースレジスタへのライト */
309 bit = (sil_rew_mem(ETHERC_PIR) & ETHERC_PIR_MDI) != 0;
310
311 for(i = ETHERC_PIR_WAIT; i > 0; i--);
312
313 /* PHY部インタフェースレジスタへのライト */
314 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
315
316 for(i = ETHERC_PIR_WAIT; i > 0; i--);
317
318 return bit;
319}
320
321/*
322 * 単独バス解放
323 */
324static void phy_single_rel_bus()
325{
326 int i;
327
328 for(i = ETHERC_PIR_WAIT; i > 0; i--);
329
330 /* PHY部インタフェースレジスタへのライト */
331 sil_wrw_mem(ETHERC_PIR, ETHERC_PIR_MMD | ETHERC_PIR_MDC);
332
333 for(i = 2 * ETHERC_PIR_WAIT; i > 0; i--);
334
335 /* PHY部インタフェースレジスタへのライト */
336 sil_wrw_mem(ETHERC_PIR, 0/*ETHERC_PIR_MMD*/ | 0/*ETHERC_PIR_MDC*/);
337
338 for(i = ETHERC_PIR_WAIT; i > 0; i--);
339}
Note: See TracBrowser for help on using the repository browser.