2 * Faraday FTMAC100 Ethernet
4 * (C) Copyright 2009 Faraday Technology
5 * Po-Yu Chuang <ratbert@faraday-tech.com>
7 * SPDX-License-Identifier: GPL-2.0+
19 DECLARE_GLOBAL_DATA_PTR
;
23 struct ftmac100_data
{
24 struct ftmac100_txdes txdes
[1];
25 struct ftmac100_rxdes rxdes
[PKTBUFSRX
];
34 static void ftmac100_reset(struct ftmac100_data
*priv
)
36 struct ftmac100
*ftmac100
= (struct ftmac100
*)priv
->iobase
;
38 debug ("%s()\n", __func__
);
40 writel (FTMAC100_MACCR_SW_RST
, &ftmac100
->maccr
);
42 while (readl (&ftmac100
->maccr
) & FTMAC100_MACCR_SW_RST
)
49 static void ftmac100_set_mac(struct ftmac100_data
*priv
,
50 const unsigned char *mac
)
52 struct ftmac100
*ftmac100
= (struct ftmac100
*)priv
->iobase
;
53 unsigned int maddr
= mac
[0] << 8 | mac
[1];
54 unsigned int laddr
= mac
[2] << 24 | mac
[3] << 16 | mac
[4] << 8 | mac
[5];
56 debug ("%s(%x %x)\n", __func__
, maddr
, laddr
);
58 writel (maddr
, &ftmac100
->mac_madr
);
59 writel (laddr
, &ftmac100
->mac_ladr
);
65 static void _ftmac100_halt(struct ftmac100_data
*priv
)
67 struct ftmac100
*ftmac100
= (struct ftmac100
*)priv
->iobase
;
68 debug ("%s()\n", __func__
);
69 writel (0, &ftmac100
->maccr
);
75 static int _ftmac100_init(struct ftmac100_data
*priv
, unsigned char enetaddr
[6])
77 struct ftmac100
*ftmac100
= (struct ftmac100
*)priv
->iobase
;
78 struct ftmac100_txdes
*txdes
= priv
->txdes
;
79 struct ftmac100_rxdes
*rxdes
= priv
->rxdes
;
83 debug ("%s()\n", __func__
);
87 /* set the ethernet address */
88 ftmac100_set_mac(priv
, enetaddr
);
91 /* disable all interrupts */
93 writel (0, &ftmac100
->imr
);
95 /* initialize descriptors */
99 txdes
[0].txdes1
= FTMAC100_TXDES1_EDOTR
;
100 rxdes
[PKTBUFSRX
- 1].rxdes1
= FTMAC100_RXDES1_EDORR
;
102 for (i
= 0; i
< PKTBUFSRX
; i
++) {
104 rxdes
[i
].rxdes2
= (unsigned int)net_rx_packets
[i
];
105 rxdes
[i
].rxdes1
|= FTMAC100_RXDES1_RXBUF_SIZE (PKTSIZE_ALIGN
);
106 rxdes
[i
].rxdes0
= FTMAC100_RXDES0_RXDMA_OWN
;
111 writel ((unsigned int)txdes
, &ftmac100
->txr_badr
);
115 writel ((unsigned int)rxdes
, &ftmac100
->rxr_badr
);
117 /* poll receive descriptor automatically */
119 writel (FTMAC100_APTC_RXPOLL_CNT (1), &ftmac100
->aptc
);
121 /* enable transmitter, receiver */
123 maccr
= FTMAC100_MACCR_XMT_EN
|
124 FTMAC100_MACCR_RCV_EN
|
125 FTMAC100_MACCR_XDMA_EN
|
126 FTMAC100_MACCR_RDMA_EN
|
127 FTMAC100_MACCR_CRC_APD
|
128 FTMAC100_MACCR_ENRX_IN_HALFTX
|
129 FTMAC100_MACCR_RX_RUNT
|
130 FTMAC100_MACCR_RX_BROADPKT
;
132 writel (maccr
, &ftmac100
->maccr
);
138 * Free receiving buffer
140 static int _ftmac100_free_pkt(struct ftmac100_data
*priv
)
142 struct ftmac100_rxdes
*curr_des
;
143 curr_des
= &priv
->rxdes
[priv
->rx_index
];
144 /* release buffer to DMA */
145 curr_des
->rxdes0
|= FTMAC100_RXDES0_RXDMA_OWN
;
146 priv
->rx_index
= (priv
->rx_index
+ 1) % PKTBUFSRX
;
151 * Receive a data block via Ethernet
153 static int __ftmac100_recv(struct ftmac100_data
*priv
)
155 struct ftmac100_rxdes
*curr_des
;
156 unsigned short rxlen
;
158 curr_des
= &priv
->rxdes
[priv
->rx_index
];
160 if (curr_des
->rxdes0
& FTMAC100_RXDES0_RXDMA_OWN
)
163 if (curr_des
->rxdes0
& (FTMAC100_RXDES0_RX_ERR
|
164 FTMAC100_RXDES0_CRC_ERR
|
165 FTMAC100_RXDES0_FTL
|
166 FTMAC100_RXDES0_RUNT
|
167 FTMAC100_RXDES0_RX_ODD_NB
)) {
171 rxlen
= FTMAC100_RXDES0_RFL (curr_des
->rxdes0
);
173 debug ("%s(): RX buffer %d, %x received\n",
174 __func__
, priv
->rx_index
, rxlen
);
180 * Send a data block via Ethernet
182 static int _ftmac100_send(struct ftmac100_data
*priv
, void *packet
, int length
)
184 struct ftmac100
*ftmac100
= (struct ftmac100
*)priv
->iobase
;
185 struct ftmac100_txdes
*curr_des
= priv
->txdes
;
188 if (curr_des
->txdes0
& FTMAC100_TXDES0_TXDMA_OWN
) {
189 debug ("%s(): no TX descriptor available\n", __func__
);
193 debug ("%s(%x, %x)\n", __func__
, (int)packet
, length
);
195 length
= (length
< ETH_ZLEN
) ? ETH_ZLEN
: length
;
197 /* initiate a transmit sequence */
199 curr_des
->txdes2
= (unsigned int)packet
; /* TXBUF_BADR */
201 curr_des
->txdes1
&= FTMAC100_TXDES1_EDOTR
;
202 curr_des
->txdes1
|= FTMAC100_TXDES1_FTS
|
203 FTMAC100_TXDES1_LTS
|
204 FTMAC100_TXDES1_TXBUF_SIZE (length
);
206 curr_des
->txdes0
= FTMAC100_TXDES0_TXDMA_OWN
;
210 writel (1, &ftmac100
->txpd
);
212 /* wait for transfer to succeed */
214 start
= get_timer(0);
215 while (curr_des
->txdes0
& FTMAC100_TXDES0_TXDMA_OWN
) {
216 if (get_timer(start
) >= 5) {
217 debug ("%s(): timed out\n", __func__
);
222 debug ("%s(): packet sent\n", __func__
);
227 #ifndef CONFIG_DM_ETH
229 * disable transmitter, receiver
231 static void ftmac100_halt(struct eth_device
*dev
)
233 struct ftmac100_data
*priv
= dev
->priv
;
234 return _ftmac100_halt(priv
);
237 static int ftmac100_init(struct eth_device
*dev
, bd_t
*bd
)
239 struct ftmac100_data
*priv
= dev
->priv
;
240 return _ftmac100_init(priv
, dev
->enetaddr
);
243 static int _ftmac100_recv(struct ftmac100_data
*priv
)
245 struct ftmac100_rxdes
*curr_des
;
247 curr_des
= &priv
->rxdes
[priv
->rx_index
];
248 len
= __ftmac100_recv(priv
);
250 /* pass the packet up to the protocol layers. */
251 net_process_received_packet((void *)curr_des
->rxdes2
, len
);
252 _ftmac100_free_pkt(priv
);
258 * Get a data block via Ethernet
260 static int ftmac100_recv(struct eth_device
*dev
)
262 struct ftmac100_data
*priv
= dev
->priv
;
263 return _ftmac100_recv(priv
);
267 * Send a data block via Ethernet
269 static int ftmac100_send(struct eth_device
*dev
, void *packet
, int length
)
271 struct ftmac100_data
*priv
= dev
->priv
;
272 return _ftmac100_send(priv
, packet
, length
);
275 int ftmac100_initialize (bd_t
*bd
)
277 struct eth_device
*dev
;
278 struct ftmac100_data
*priv
;
279 dev
= malloc (sizeof *dev
);
281 printf ("%s(): failed to allocate dev\n", __func__
);
284 /* Transmit and receive descriptors should align to 16 bytes */
285 priv
= memalign (16, sizeof (struct ftmac100_data
));
287 printf ("%s(): failed to allocate priv\n", __func__
);
290 memset (dev
, 0, sizeof (*dev
));
291 memset (priv
, 0, sizeof (*priv
));
293 strcpy(dev
->name
, "FTMAC100");
294 dev
->iobase
= CONFIG_FTMAC100_BASE
;
295 dev
->init
= ftmac100_init
;
296 dev
->halt
= ftmac100_halt
;
297 dev
->send
= ftmac100_send
;
298 dev
->recv
= ftmac100_recv
;
300 priv
->iobase
= dev
->iobase
;
313 static int ftmac100_start(struct udevice
*dev
)
315 struct eth_pdata
*plat
= dev_get_platdata(dev
);
316 struct ftmac100_data
*priv
= dev_get_priv(dev
);
318 return _ftmac100_init(priv
, plat
->enetaddr
);
321 static void ftmac100_stop(struct udevice
*dev
)
323 struct ftmac100_data
*priv
= dev_get_priv(dev
);
324 _ftmac100_halt(priv
);
327 static int ftmac100_send(struct udevice
*dev
, void *packet
, int length
)
329 struct ftmac100_data
*priv
= dev_get_priv(dev
);
331 ret
= _ftmac100_send(priv
, packet
, length
);
332 return ret
? 0 : -ETIMEDOUT
;
335 static int ftmac100_recv(struct udevice
*dev
, int flags
, uchar
**packetp
)
337 struct ftmac100_data
*priv
= dev_get_priv(dev
);
338 struct ftmac100_rxdes
*curr_des
;
339 curr_des
= &priv
->rxdes
[priv
->rx_index
];
341 len
= __ftmac100_recv(priv
);
343 *packetp
= (void *)curr_des
->rxdes2
;
345 return len
? len
: -EAGAIN
;
348 static int ftmac100_free_pkt(struct udevice
*dev
, uchar
*packet
, int length
)
350 struct ftmac100_data
*priv
= dev_get_priv(dev
);
351 _ftmac100_free_pkt(priv
);
355 int ftmac100_read_rom_hwaddr(struct udevice
*dev
)
357 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
358 eth_getenv_enetaddr("ethaddr", pdata
->enetaddr
);
362 static const char *dtbmacaddr(u32 ifno
)
368 if (gd
->fdt_blob
== NULL
) {
369 printf("%s: don't have a valid gd->fdt_blob!\n", __func__
);
372 node
= fdt_path_offset(gd
->fdt_blob
, "/aliases");
376 sprintf(enet
, "ethernet%d", ifno
);
377 path
= fdt_getprop(gd
->fdt_blob
, node
, enet
, NULL
);
379 printf("no alias for %s\n", enet
);
382 node
= fdt_path_offset(gd
->fdt_blob
, path
);
383 mac
= fdt_getprop(gd
->fdt_blob
, node
, "mac-address", &len
);
384 if (mac
&& is_valid_ethaddr((u8
*)mac
))
390 static int ftmac100_ofdata_to_platdata(struct udevice
*dev
)
392 struct ftmac100_data
*priv
= dev_get_priv(dev
);
393 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
395 pdata
->iobase
= devfdt_get_addr(dev
);
396 priv
->iobase
= pdata
->iobase
;
399 memcpy(pdata
->enetaddr
, mac
, 6);
404 static int ftmac100_probe(struct udevice
*dev
)
406 struct ftmac100_data
*priv
= dev_get_priv(dev
);
407 priv
->name
= dev
->name
;
411 static int ftmac100_bind(struct udevice
*dev
)
413 return device_set_name(dev
, dev
->name
);
416 static const struct eth_ops ftmac100_ops
= {
417 .start
= ftmac100_start
,
418 .send
= ftmac100_send
,
419 .recv
= ftmac100_recv
,
420 .stop
= ftmac100_stop
,
421 .free_pkt
= ftmac100_free_pkt
,
424 static const struct udevice_id ftmac100_ids
[] = {
425 { .compatible
= "andestech,atmac100" },
429 U_BOOT_DRIVER(ftmac100
) = {
432 .of_match
= ftmac100_ids
,
433 .bind
= ftmac100_bind
,
434 .ofdata_to_platdata
= ftmac100_ofdata_to_platdata
,
435 .probe
= ftmac100_probe
,
436 .ops
= &ftmac100_ops
,
437 .priv_auto_alloc_size
= sizeof(struct ftmac100_data
),
438 .platdata_auto_alloc_size
= sizeof(struct eth_pdata
),
439 .flags
= DM_FLAG_ALLOC_PRIV_DMA
,