Blame view

drivers/net/sh_eth.c 15.7 KB
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
1
  /*
262350932   Yoshihiro Shimoda   net: sh_eth: add ...
2
   * sh_eth.c - Driver for Renesas ethernet controler.
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
3
   *
3bb4cc312   Nobuhiro Iwamatsu   sh: sh_eth: Add s...
4
5
   * Copyright (C) 2008, 2011 Renesas Solutions Corp.
   * Copyright (c) 2008, 2011 Nobuhiro Iwamatsu
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
6
   * Copyright (c) 2007 Carlos Munoz <carlos@kenati.com>
8707678cc   Nobuhiro Iwamatsu   net: sh-eth: Add ...
7
   * Copyright (C) 2013  Renesas Electronics Corporation
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
8
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
9
   * SPDX-License-Identifier:	GPL-2.0+
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
10
11
12
13
14
15
   */
  
  #include <config.h>
  #include <common.h>
  #include <malloc.h>
  #include <net.h>
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
16
  #include <netdev.h>
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
17
  #include <miiphy.h>
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
18
19
20
21
22
23
24
25
26
27
28
  #include <asm/errno.h>
  #include <asm/io.h>
  
  #include "sh_eth.h"
  
  #ifndef CONFIG_SH_ETHER_USE_PORT
  # error "Please define CONFIG_SH_ETHER_USE_PORT"
  #endif
  #ifndef CONFIG_SH_ETHER_PHY_ADDR
  # error "Please define CONFIG_SH_ETHER_PHY_ADDR"
  #endif
870cc23f0   Nobuhiro Iwamatsu   net: sh-eth: Chan...
29

92f071340   Nobuhiro Iwamatsu   net: sh-eth: Add ...
30
31
32
  #if defined(CONFIG_SH_ETHER_CACHE_WRITEBACK) && !defined(CONFIG_SYS_DCACHE_OFF)
  #define flush_cache_wback(addr, len)    \
  		flush_dcache_range((u32)addr, (u32)(addr + len - 1))
68260aab9   Yoshihiro Shimoda   net: sh_eth: add ...
33
34
35
  #else
  #define flush_cache_wback(...)
  #endif
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
36

92f071340   Nobuhiro Iwamatsu   net: sh-eth: Add ...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  #if defined(CONFIG_SH_ETHER_CACHE_INVALIDATE) && defined(CONFIG_ARM)
  #define invalidate_cache(addr, len)		\
  	{	\
  		u32 line_size = CONFIG_SH_ETHER_ALIGNE_SIZE;	\
  		u32 start, end;	\
  		\
  		start = (u32)addr;	\
  		end = start + len;	\
  		start &= ~(line_size - 1);	\
  		end = ((end + line_size - 1) & ~(line_size - 1));	\
  		\
  		invalidate_dcache_range(start, end);	\
  	}
  #else
  #define invalidate_cache(...)
  #endif
4ba62c729   Nobuhiro Iwamatsu   net: sh_eth: Coll...
53
  #define TIMEOUT_CNT 1000
10cbe3b6a   Joe Hershberger   net: Fix remainin...
54
  int sh_eth_send(struct eth_device *dev, void *packet, int len)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
55
  {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
56
57
58
  	struct sh_eth_dev *eth = dev->priv;
  	int port = eth->port, ret = 0, timeout;
  	struct sh_eth_info *port_info = &eth->port_info[port];
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
59
60
  
  	if (!packet || len > 0xffff) {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
61
62
63
64
  		printf(SHETHER_NAME ": %s: Invalid argument
  ", __func__);
  		ret = -EINVAL;
  		goto err;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
65
66
67
  	}
  
  	/* packet must be a 4 byte boundary */
ee6ec5d4d   Nobuhiro Iwamatsu   net: sh_eth: Add ...
68
  	if ((int)packet & 3) {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
69
70
71
72
  		printf(SHETHER_NAME ": %s: packet not 4 byte alligned
  ", __func__);
  		ret = -EFAULT;
  		goto err;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
73
74
75
  	}
  
  	/* Update tx descriptor */
68260aab9   Yoshihiro Shimoda   net: sh_eth: add ...
76
  	flush_cache_wback(packet, len);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
77
78
79
80
81
82
83
84
85
  	port_info->tx_desc_cur->td2 = ADDR_TO_PHY(packet);
  	port_info->tx_desc_cur->td1 = len << 16;
  	/* Must preserve the end of descriptor list indication */
  	if (port_info->tx_desc_cur->td0 & TD_TDLE)
  		port_info->tx_desc_cur->td0 = TD_TACT | TD_TFP | TD_TDLE;
  	else
  		port_info->tx_desc_cur->td0 = TD_TACT | TD_TFP;
  
  	/* Restart the transmitter if disabled */
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
86
87
  	if (!(sh_eth_read(eth, EDTRR) & EDTRR_TRNS))
  		sh_eth_write(eth, EDTRR_TRNS, EDTRR);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
88
89
  
  	/* Wait until packet is transmitted */
4ba62c729   Nobuhiro Iwamatsu   net: sh_eth: Coll...
90
  	timeout = TIMEOUT_CNT;
92f071340   Nobuhiro Iwamatsu   net: sh-eth: Add ...
91
92
93
  	do {
  		invalidate_cache(port_info->tx_desc_cur,
  				 sizeof(struct tx_desc_s));
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
94
  		udelay(100);
92f071340   Nobuhiro Iwamatsu   net: sh-eth: Add ...
95
  	} while (port_info->tx_desc_cur->td0 & TD_TACT && timeout--);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
96
97
  
  	if (timeout < 0) {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
98
99
100
  		printf(SHETHER_NAME ": transmit timeout
  ");
  		ret = -ETIMEDOUT;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
101
102
  		goto err;
  	}
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
103
104
105
  	port_info->tx_desc_cur++;
  	if (port_info->tx_desc_cur >= port_info->tx_desc_base + NUM_TX_DESC)
  		port_info->tx_desc_cur = port_info->tx_desc_base;
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
106
107
  err:
  	return ret;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
108
  }
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
109
  int sh_eth_recv(struct eth_device *dev)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
110
  {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
111
112
113
  	struct sh_eth_dev *eth = dev->priv;
  	int port = eth->port, len = 0;
  	struct sh_eth_info *port_info = &eth->port_info[port];
10cbe3b6a   Joe Hershberger   net: Fix remainin...
114
  	uchar *packet;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
115
116
  
  	/* Check if the rx descriptor is ready */
92f071340   Nobuhiro Iwamatsu   net: sh-eth: Add ...
117
  	invalidate_cache(port_info->rx_desc_cur, sizeof(struct rx_desc_s));
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
118
119
120
121
  	if (!(port_info->rx_desc_cur->rd0 & RD_RACT)) {
  		/* Check for errors */
  		if (!(port_info->rx_desc_cur->rd0 & RD_RFE)) {
  			len = port_info->rx_desc_cur->rd1 & 0xffff;
10cbe3b6a   Joe Hershberger   net: Fix remainin...
122
123
  			packet = (uchar *)
  				ADDR_TO_P2(port_info->rx_desc_cur->rd2);
92f071340   Nobuhiro Iwamatsu   net: sh-eth: Add ...
124
  			invalidate_cache(packet, len);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
125
126
127
128
129
130
131
132
  			NetReceive(packet, len);
  		}
  
  		/* Make current descriptor available again */
  		if (port_info->rx_desc_cur->rd0 & RD_RDLE)
  			port_info->rx_desc_cur->rd0 = RD_RACT | RD_RDLE;
  		else
  			port_info->rx_desc_cur->rd0 = RD_RACT;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
133
134
135
136
137
138
139
140
  		/* Point to the next descriptor */
  		port_info->rx_desc_cur++;
  		if (port_info->rx_desc_cur >=
  		    port_info->rx_desc_base + NUM_RX_DESC)
  			port_info->rx_desc_cur = port_info->rx_desc_base;
  	}
  
  	/* Restart the receiver if disabled */
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
141
142
  	if (!(sh_eth_read(eth, EDRRR) & EDRRR_R))
  		sh_eth_write(eth, EDRRR_R, EDRRR);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
143
144
145
  
  	return len;
  }
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
146
  static int sh_eth_reset(struct sh_eth_dev *eth)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
147
  {
262350932   Yoshihiro Shimoda   net: sh_eth: add ...
148
  #if defined(SH_ETH_TYPE_GETHER)
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
149
  	int ret = 0, i;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
150
151
  
  	/* Start e-dmac transmitter and receiver */
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
152
  	sh_eth_write(eth, EDSR_ENALL, EDSR);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
153
154
  
  	/* Perform a software reset and wait for it to complete */
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
155
  	sh_eth_write(eth, EDMR_SRST, EDMR);
4ba62c729   Nobuhiro Iwamatsu   net: sh_eth: Coll...
156
  	for (i = 0; i < TIMEOUT_CNT ; i++) {
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
157
  		if (!(sh_eth_read(eth, EDMR) & EDMR_SRST))
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
158
159
160
  			break;
  		udelay(1000);
  	}
4ba62c729   Nobuhiro Iwamatsu   net: sh_eth: Coll...
161
  	if (i == TIMEOUT_CNT) {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
162
163
164
  		printf(SHETHER_NAME  ": Software reset timeout
  ");
  		ret = -EIO;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
165
  	}
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
166
167
  
  	return ret;
903de461e   Yoshihiro Shimoda   net: sh_eth: add ...
168
  #else
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
169
  	sh_eth_write(eth, sh_eth_read(eth, EDMR) | EDMR_SRST, EDMR);
903de461e   Yoshihiro Shimoda   net: sh_eth: add ...
170
  	udelay(3000);
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
171
  	sh_eth_write(eth, sh_eth_read(eth, EDMR) & ~EDMR_SRST, EDMR);
903de461e   Yoshihiro Shimoda   net: sh_eth: add ...
172
173
174
  
  	return 0;
  #endif
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
175
  }
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
176
  static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
177
  {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
178
  	int port = eth->port, i, ret = 0;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
179
  	u32 tmp_addr;
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
180
  	struct sh_eth_info *port_info = &eth->port_info[port];
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
181
  	struct tx_desc_s *cur_tx_desc;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
182

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
183
184
185
186
  	/*
  	 * Allocate tx descriptors. They must be TX_DESC_SIZE bytes aligned
  	 */
  	port_info->tx_desc_malloc = malloc(NUM_TX_DESC *
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
187
  						 sizeof(struct tx_desc_s) +
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
188
189
190
191
192
193
  						 TX_DESC_SIZE - 1);
  	if (!port_info->tx_desc_malloc) {
  		printf(SHETHER_NAME ": malloc failed
  ");
  		ret = -ENOMEM;
  		goto err;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
194
  	}
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
195

9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
196
197
  	tmp_addr = (u32) (((int)port_info->tx_desc_malloc + TX_DESC_SIZE - 1) &
  			  ~(TX_DESC_SIZE - 1));
68260aab9   Yoshihiro Shimoda   net: sh_eth: add ...
198
  	flush_cache_wback(tmp_addr, NUM_TX_DESC * sizeof(struct tx_desc_s));
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
199
200
  	/* Make sure we use a P2 address (non-cacheable) */
  	port_info->tx_desc_base = (struct tx_desc_s *)ADDR_TO_P2(tmp_addr);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
  	port_info->tx_desc_cur = port_info->tx_desc_base;
  
  	/* Initialize all descriptors */
  	for (cur_tx_desc = port_info->tx_desc_base, i = 0; i < NUM_TX_DESC;
  	     cur_tx_desc++, i++) {
  		cur_tx_desc->td0 = 0x00;
  		cur_tx_desc->td1 = 0x00;
  		cur_tx_desc->td2 = 0x00;
  	}
  
  	/* Mark the end of the descriptors */
  	cur_tx_desc--;
  	cur_tx_desc->td0 |= TD_TDLE;
  
  	/* Point the controller to the tx descriptor list. Must use physical
  	   addresses */
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
217
  	sh_eth_write(eth, ADDR_TO_PHY(port_info->tx_desc_base), TDLAR);
262350932   Yoshihiro Shimoda   net: sh_eth: add ...
218
  #if defined(SH_ETH_TYPE_GETHER)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
219
220
221
  	sh_eth_write(eth, ADDR_TO_PHY(port_info->tx_desc_base), TDFAR);
  	sh_eth_write(eth, ADDR_TO_PHY(cur_tx_desc), TDFXR);
  	sh_eth_write(eth, 0x01, TDFFR);/* Last discriptor bit */
903de461e   Yoshihiro Shimoda   net: sh_eth: add ...
222
  #endif
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
223

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
224
225
  err:
  	return ret;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
226
  }
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
227
  static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
228
  {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
229
230
  	int port = eth->port, i , ret = 0;
  	struct sh_eth_info *port_info = &eth->port_info[port];
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
231
  	struct rx_desc_s *cur_rx_desc;
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
232
  	u32 tmp_addr;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
233
  	u8 *rx_buf;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
234

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
235
236
237
238
  	/*
  	 * Allocate rx descriptors. They must be RX_DESC_SIZE bytes aligned
  	 */
  	port_info->rx_desc_malloc = malloc(NUM_RX_DESC *
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
239
  						 sizeof(struct rx_desc_s) +
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
240
241
242
243
244
245
  						 RX_DESC_SIZE - 1);
  	if (!port_info->rx_desc_malloc) {
  		printf(SHETHER_NAME ": malloc failed
  ");
  		ret = -ENOMEM;
  		goto err;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
246
  	}
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
247

9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
248
249
  	tmp_addr = (u32) (((int)port_info->rx_desc_malloc + RX_DESC_SIZE - 1) &
  			  ~(RX_DESC_SIZE - 1));
68260aab9   Yoshihiro Shimoda   net: sh_eth: add ...
250
  	flush_cache_wback(tmp_addr, NUM_RX_DESC * sizeof(struct rx_desc_s));
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
251
252
253
254
  	/* Make sure we use a P2 address (non-cacheable) */
  	port_info->rx_desc_base = (struct rx_desc_s *)ADDR_TO_P2(tmp_addr);
  
  	port_info->rx_desc_cur = port_info->rx_desc_base;
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
255
256
257
258
  	/*
  	 * Allocate rx data buffers. They must be 32 bytes aligned  and in
  	 * P2 area
  	 */
f8b7507d4   Nobuhiro Iwamatsu   net: sh-eth: Add ...
259
260
  	port_info->rx_buf_malloc = malloc(
  		NUM_RX_DESC * MAX_BUF_SIZE + RX_BUF_ALIGNE_SIZE - 1);
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
261
262
263
264
265
  	if (!port_info->rx_buf_malloc) {
  		printf(SHETHER_NAME ": malloc failed
  ");
  		ret = -ENOMEM;
  		goto err_buf_malloc;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
266
  	}
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
267

f8b7507d4   Nobuhiro Iwamatsu   net: sh-eth: Add ...
268
269
270
  	tmp_addr = (u32)(((int)port_info->rx_buf_malloc
  			  + (RX_BUF_ALIGNE_SIZE - 1)) &
  			  ~(RX_BUF_ALIGNE_SIZE - 1));
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
  	port_info->rx_buf_base = (u8 *)ADDR_TO_P2(tmp_addr);
  
  	/* Initialize all descriptors */
  	for (cur_rx_desc = port_info->rx_desc_base,
  	     rx_buf = port_info->rx_buf_base, i = 0;
  	     i < NUM_RX_DESC; cur_rx_desc++, rx_buf += MAX_BUF_SIZE, i++) {
  		cur_rx_desc->rd0 = RD_RACT;
  		cur_rx_desc->rd1 = MAX_BUF_SIZE << 16;
  		cur_rx_desc->rd2 = (u32) ADDR_TO_PHY(rx_buf);
  	}
  
  	/* Mark the end of the descriptors */
  	cur_rx_desc--;
  	cur_rx_desc->rd0 |= RD_RDLE;
  
  	/* Point the controller to the rx descriptor list */
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
287
  	sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDLAR);
262350932   Yoshihiro Shimoda   net: sh_eth: add ...
288
  #if defined(SH_ETH_TYPE_GETHER)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
289
290
291
  	sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDFAR);
  	sh_eth_write(eth, ADDR_TO_PHY(cur_rx_desc), RDFXR);
  	sh_eth_write(eth, RDFFR_RDLF, RDFFR);
903de461e   Yoshihiro Shimoda   net: sh_eth: add ...
292
  #endif
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
293

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
294
295
296
297
298
299
300
301
  	return ret;
  
  err_buf_malloc:
  	free(port_info->rx_desc_malloc);
  	port_info->rx_desc_malloc = NULL;
  
  err:
  	return ret;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
302
  }
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
303
  static void sh_eth_tx_desc_free(struct sh_eth_dev *eth)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
304
  {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
305
306
  	int port = eth->port;
  	struct sh_eth_info *port_info = &eth->port_info[port];
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
307
308
309
310
311
  
  	if (port_info->tx_desc_malloc) {
  		free(port_info->tx_desc_malloc);
  		port_info->tx_desc_malloc = NULL;
  	}
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
312
313
314
315
316
317
  }
  
  static void sh_eth_rx_desc_free(struct sh_eth_dev *eth)
  {
  	int port = eth->port;
  	struct sh_eth_info *port_info = &eth->port_info[port];
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
318
319
320
321
322
323
324
325
326
327
328
  
  	if (port_info->rx_desc_malloc) {
  		free(port_info->rx_desc_malloc);
  		port_info->rx_desc_malloc = NULL;
  	}
  
  	if (port_info->rx_buf_malloc) {
  		free(port_info->rx_buf_malloc);
  		port_info->rx_buf_malloc = NULL;
  	}
  }
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
329
  static int sh_eth_desc_init(struct sh_eth_dev *eth)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
330
  {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
331
  	int ret = 0;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
332

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
333
334
335
  	ret = sh_eth_tx_desc_init(eth);
  	if (ret)
  		goto err_tx_init;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
336

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
337
338
339
340
341
342
343
344
345
346
  	ret = sh_eth_rx_desc_init(eth);
  	if (ret)
  		goto err_rx_init;
  
  	return ret;
  err_rx_init:
  	sh_eth_tx_desc_free(eth);
  
  err_tx_init:
  	return ret;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
347
  }
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
348
  static int sh_eth_phy_config(struct sh_eth_dev *eth)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
349
  {
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
350
  	int port = eth->port, ret = 0;
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
351
  	struct sh_eth_info *port_info = &eth->port_info[port];
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
352
353
  	struct eth_device *dev = port_info->dev;
  	struct phy_device *phydev;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
354

ee6ec5d4d   Nobuhiro Iwamatsu   net: sh_eth: Add ...
355
356
  	phydev = phy_connect(
  			miiphy_get_dev_by_name(dev->name),
4398d5599   Nobuhiro Iwamatsu   net: sh-eth: Add ...
357
  			port_info->phy_addr, dev, CONFIG_SH_ETHER_PHY_MODE);
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
358
359
  	port_info->phydev = phydev;
  	phy_config(phydev);
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
360

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
361
  	return ret;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
362
  }
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
363
  static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
364
  {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
365
  	int port = eth->port, ret = 0;
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
366
  	u32 val;
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
367
  	struct sh_eth_info *port_info = &eth->port_info[port];
c527ce925   Mike Frysinger   sh_eth: get mac a...
368
  	struct eth_device *dev = port_info->dev;
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
369
  	struct phy_device *phy;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
370
371
  
  	/* Configure e-dmac registers */
f8b7507d4   Nobuhiro Iwamatsu   net: sh-eth: Add ...
372
373
  	sh_eth_write(eth, (sh_eth_read(eth, EDMR) & ~EMDR_DESC_R) |
  			(EMDR_DESC | EDMR_EL), EDMR);
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
374
375
376
377
378
  	sh_eth_write(eth, 0, EESIPR);
  	sh_eth_write(eth, 0, TRSCER);
  	sh_eth_write(eth, 0, TFTR);
  	sh_eth_write(eth, (FIFO_SIZE_T | FIFO_SIZE_R), FDR);
  	sh_eth_write(eth, RMCR_RST, RMCR);
262350932   Yoshihiro Shimoda   net: sh_eth: add ...
379
  #if defined(SH_ETH_TYPE_GETHER)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
380
  	sh_eth_write(eth, 0, RPADIR);
903de461e   Yoshihiro Shimoda   net: sh_eth: add ...
381
  #endif
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
382
  	sh_eth_write(eth, (FIFO_F_D_RFF | FIFO_F_D_RFD), FCFTR);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
383
384
  
  	/* Configure e-mac registers */
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
385
  	sh_eth_write(eth, 0, ECSIPR);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
386
387
  
  	/* Set Mac address */
c527ce925   Mike Frysinger   sh_eth: get mac a...
388
389
  	val = dev->enetaddr[0] << 24 | dev->enetaddr[1] << 16 |
  	    dev->enetaddr[2] << 8 | dev->enetaddr[3];
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
390
  	sh_eth_write(eth, val, MAHR);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
391

c527ce925   Mike Frysinger   sh_eth: get mac a...
392
  	val = dev->enetaddr[4] << 8 | dev->enetaddr[5];
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
393
  	sh_eth_write(eth, val, MALR);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
394

49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
395
  	sh_eth_write(eth, RFLR_RFL_MIN, RFLR);
262350932   Yoshihiro Shimoda   net: sh_eth: add ...
396
  #if defined(SH_ETH_TYPE_GETHER)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
397
398
399
400
  	sh_eth_write(eth, 0, PIPR);
  	sh_eth_write(eth, APR_AP, APR);
  	sh_eth_write(eth, MPR_MP, MPR);
  	sh_eth_write(eth, TPAUSER_TPAUSE, TPAUSER);
903de461e   Yoshihiro Shimoda   net: sh_eth: add ...
401
  #endif
3bb4cc312   Nobuhiro Iwamatsu   sh: sh_eth: Add s...
402

dcd5a593f   Nobuhiro Iwamatsu   net: sh_eth: Add ...
403
  #if defined(CONFIG_CPU_SH7734) || defined(CONFIG_R8A7740)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
404
  	sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII);
47ce88904   Nobuhiro Iwamatsu   net: sh-eth: Add ...
405
  #elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791)
8707678cc   Nobuhiro Iwamatsu   net: sh-eth: Add ...
406
  	sh_eth_write(eth, sh_eth_read(eth, RMIIMR) | 0x1, RMIIMR);
4398d5599   Nobuhiro Iwamatsu   net: sh-eth: Add ...
407
  #endif
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
408
  	/* Configure phy */
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
409
410
  	ret = sh_eth_phy_config(eth);
  	if (ret) {
88a4c2e77   Nobuhiro Iwamatsu   sh: sh_eth: Remov...
411
412
  		printf(SHETHER_NAME ": phy config timeout
  ");
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
413
414
  		goto err_phy_cfg;
  	}
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
415
  	phy = port_info->phydev;
11af8d652   Timur Tabi   net: abort networ...
416
417
418
419
420
421
  	ret = phy_startup(phy);
  	if (ret) {
  		printf(SHETHER_NAME ": phy startup failure
  ");
  		return ret;
  	}
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
422

3bb4cc312   Nobuhiro Iwamatsu   sh: sh_eth: Add s...
423
  	val = 0;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
424
  	/* Set the transfer speed */
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
425
  	if (phy->speed == 100) {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
426
  		printf(SHETHER_NAME ": 100Base/");
262350932   Yoshihiro Shimoda   net: sh_eth: add ...
427
  #if defined(SH_ETH_TYPE_GETHER)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
428
  		sh_eth_write(eth, GECMR_100B, GECMR);
e3bb3254f   Yoshihiro Shimoda   net: sh_eth: add ...
429
  #elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
430
  		sh_eth_write(eth, 1, RTRATE);
47ce88904   Nobuhiro Iwamatsu   net: sh-eth: Add ...
431
432
  #elif defined(CONFIG_CPU_SH7724) || defined(CONFIG_R8A7790) || \
  		defined(CONFIG_R8A7791)
3bb4cc312   Nobuhiro Iwamatsu   sh: sh_eth: Add s...
433
434
  		val = ECMR_RTM;
  #endif
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
435
  	} else if (phy->speed == 10) {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
436
  		printf(SHETHER_NAME ": 10Base/");
262350932   Yoshihiro Shimoda   net: sh_eth: add ...
437
  #if defined(SH_ETH_TYPE_GETHER)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
438
  		sh_eth_write(eth, GECMR_10B, GECMR);
e3bb3254f   Yoshihiro Shimoda   net: sh_eth: add ...
439
  #elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
440
  		sh_eth_write(eth, 0, RTRATE);
903de461e   Yoshihiro Shimoda   net: sh_eth: add ...
441
  #endif
3bb4cc312   Nobuhiro Iwamatsu   sh: sh_eth: Add s...
442
  	}
262350932   Yoshihiro Shimoda   net: sh_eth: add ...
443
  #if defined(SH_ETH_TYPE_GETHER)
4398d5599   Nobuhiro Iwamatsu   net: sh-eth: Add ...
444
445
  	else if (phy->speed == 1000) {
  		printf(SHETHER_NAME ": 1000Base/");
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
446
  		sh_eth_write(eth, GECMR_1000B, GECMR);
4398d5599   Nobuhiro Iwamatsu   net: sh-eth: Add ...
447
448
  	}
  #endif
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
449
450
  
  	/* Check if full duplex mode is supported by the phy */
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
451
  	if (phy->duplex) {
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
452
453
  		printf("Full
  ");
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
454
455
  		sh_eth_write(eth, val | (ECMR_CHG_DM|ECMR_RE|ECMR_TE|ECMR_DM),
  			     ECMR);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
456
457
458
  	} else {
  		printf("Half
  ");
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
459
  		sh_eth_write(eth, val | (ECMR_CHG_DM|ECMR_RE|ECMR_TE), ECMR);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
460
  	}
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
461
462
463
464
465
  
  	return ret;
  
  err_phy_cfg:
  	return ret;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
466
  }
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
467
  static void sh_eth_start(struct sh_eth_dev *eth)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
468
469
470
471
472
  {
  	/*
  	 * Enable the e-dmac receiver only. The transmitter will be enabled when
  	 * we have something to transmit
  	 */
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
473
  	sh_eth_write(eth, EDRRR_R, EDRRR);
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
474
  }
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
475

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
476
477
  static void sh_eth_stop(struct sh_eth_dev *eth)
  {
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
478
  	sh_eth_write(eth, ~EDRRR_R, EDRRR);
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
479
  }
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
480
  int sh_eth_init(struct eth_device *dev, bd_t *bd)
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
481
  {
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
482
483
  	int ret = 0;
  	struct sh_eth_dev *eth = dev->priv;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
484

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
485
486
487
  	ret = sh_eth_reset(eth);
  	if (ret)
  		goto err;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
488

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
489
490
491
  	ret = sh_eth_desc_init(eth);
  	if (ret)
  		goto err;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
492

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
493
494
495
496
497
498
499
  	ret = sh_eth_config(eth, bd);
  	if (ret)
  		goto err_config;
  
  	sh_eth_start(eth);
  
  	return ret;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
500

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
501
502
503
504
505
506
507
508
509
510
511
  err_config:
  	sh_eth_tx_desc_free(eth);
  	sh_eth_rx_desc_free(eth);
  
  err:
  	return ret;
  }
  
  void sh_eth_halt(struct eth_device *dev)
  {
  	struct sh_eth_dev *eth = dev->priv;
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
512
513
514
515
516
517
518
519
520
521
522
523
524
525
  	sh_eth_stop(eth);
  }
  
  int sh_eth_initialize(bd_t *bd)
  {
      int ret = 0;
  	struct sh_eth_dev *eth = NULL;
      struct eth_device *dev = NULL;
  
      eth = (struct sh_eth_dev *)malloc(sizeof(struct sh_eth_dev));
  	if (!eth) {
  		printf(SHETHER_NAME ": %s: malloc failed
  ", __func__);
  		ret = -ENOMEM;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
526
  		goto err;
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
527
  	}
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
528

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
529
530
531
532
533
534
535
536
537
      dev = (struct eth_device *)malloc(sizeof(struct eth_device));
  	if (!dev) {
  		printf(SHETHER_NAME ": %s: malloc failed
  ", __func__);
  		ret = -ENOMEM;
  		goto err;
  	}
      memset(dev, 0, sizeof(struct eth_device));
      memset(eth, 0, sizeof(struct sh_eth_dev));
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
538

bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
  	eth->port = CONFIG_SH_ETHER_USE_PORT;
  	eth->port_info[eth->port].phy_addr = CONFIG_SH_ETHER_PHY_ADDR;
  
      dev->priv = (void *)eth;
      dev->iobase = 0;
      dev->init = sh_eth_init;
      dev->halt = sh_eth_halt;
      dev->send = sh_eth_send;
      dev->recv = sh_eth_recv;
      eth->port_info[eth->port].dev = dev;
  
  	sprintf(dev->name, SHETHER_NAME);
  
      /* Register Device to EtherNet subsystem  */
      eth_register(dev);
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
554
555
  	bb_miiphy_buses[0].priv = eth;
  	miiphy_register(dev->name, bb_miiphy_read, bb_miiphy_write);
c527ce925   Mike Frysinger   sh_eth: get mac a...
556
557
558
  	if (!eth_getenv_enetaddr("ethaddr", dev->enetaddr))
  		puts("Please set MAC address
  ");
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
559
560
  
  	return ret;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
561

9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
562
  err:
bd3980cc0   Nobuhiro Iwamatsu   sh: sh_eth: Chang...
563
564
565
566
567
568
569
570
571
  	if (dev)
  		free(dev);
  
  	if (eth)
  		free(eth);
  
  	printf(SHETHER_NAME ": Failed
  ");
  	return ret;
9751ee099   Nobuhiro Iwamatsu   net: sh: Renesas ...
572
  }
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
573
574
575
576
577
578
579
580
581
582
  
  /******* for bb_miiphy *******/
  static int sh_eth_bb_init(struct bb_miiphy_bus *bus)
  {
  	return 0;
  }
  
  static int sh_eth_bb_mdio_active(struct bb_miiphy_bus *bus)
  {
  	struct sh_eth_dev *eth = bus->priv;
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
583

49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
584
  	sh_eth_write(eth, sh_eth_read(eth, PIR) | PIR_MMD, PIR);
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
585
586
587
588
589
590
591
  
  	return 0;
  }
  
  static int sh_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus)
  {
  	struct sh_eth_dev *eth = bus->priv;
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
592

49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
593
  	sh_eth_write(eth, sh_eth_read(eth, PIR) & ~PIR_MMD, PIR);
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
594
595
596
597
598
599
600
  
  	return 0;
  }
  
  static int sh_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v)
  {
  	struct sh_eth_dev *eth = bus->priv;
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
601
602
  
  	if (v)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
603
  		sh_eth_write(eth, sh_eth_read(eth, PIR) | PIR_MDO, PIR);
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
604
  	else
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
605
  		sh_eth_write(eth, sh_eth_read(eth, PIR) & ~PIR_MDO, PIR);
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
606
607
608
609
610
611
612
  
  	return 0;
  }
  
  static int sh_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v)
  {
  	struct sh_eth_dev *eth = bus->priv;
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
613

49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
614
  	*v = (sh_eth_read(eth, PIR) & PIR_MDI) >> 3;
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
615
616
617
618
619
620
621
  
  	return 0;
  }
  
  static int sh_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v)
  {
  	struct sh_eth_dev *eth = bus->priv;
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
622
623
  
  	if (v)
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
624
  		sh_eth_write(eth, sh_eth_read(eth, PIR) | PIR_MDC, PIR);
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
625
  	else
49afb8caf   Yoshihiro Shimoda   net: sh_eth: modi...
626
  		sh_eth_write(eth, sh_eth_read(eth, PIR) & ~PIR_MDC, PIR);
bd1024b05   Yoshihiro Shimoda   net: sh_eth: use ...
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
  
  	return 0;
  }
  
  static int sh_eth_bb_delay(struct bb_miiphy_bus *bus)
  {
  	udelay(10);
  
  	return 0;
  }
  
  struct bb_miiphy_bus bb_miiphy_buses[] = {
  	{
  		.name		= "sh_eth",
  		.init		= sh_eth_bb_init,
  		.mdio_active	= sh_eth_bb_mdio_active,
  		.mdio_tristate	= sh_eth_bb_mdio_tristate,
  		.set_mdio	= sh_eth_bb_set_mdio,
  		.get_mdio	= sh_eth_bb_get_mdio,
  		.set_mdc	= sh_eth_bb_set_mdc,
  		.delay		= sh_eth_bb_delay,
  	}
  };
  int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);