1 // SPDX-License-Identifier: GPL-2.0+
3 * Faraday FTMAC100 Ethernet
5 * (C) Copyright 2009 Faraday Technology
6 * Po-Yu Chuang <ratbert@faraday-tech.com>
18 DECLARE_GLOBAL_DATA_PTR
;
22 struct ftmac100_data
{
23 struct ftmac100_txdes txdes
[1];
24 struct ftmac100_rxdes rxdes
[PKTBUFSRX
];
33 static void ftmac100_reset(struct ftmac100_data
*priv
)
35 struct ftmac100
*ftmac100
= (struct ftmac100
*)priv
->iobase
;
37 debug ("%s()\n", __func__
);
39 writel (FTMAC100_MACCR_SW_RST
, &ftmac100
->maccr
);
41 while (readl (&ftmac100
->maccr
) & FTMAC100_MACCR_SW_RST
)
44 * When soft reset complete, write mac address immediately maybe fail somehow
45 * Wait for a while can avoid this problem
53 static void ftmac100_set_mac(struct ftmac100_data
*priv
,
54 const unsigned char *mac
)
56 struct ftmac100
*ftmac100
= (struct ftmac100
*)priv
->iobase
;
57 unsigned int maddr
= mac
[0] << 8 | mac
[1];
58 unsigned int laddr
= mac
[2] << 24 | mac
[3] << 16 | mac
[4] << 8 | mac
[5];
60 debug ("%s(%x %x)\n", __func__
, maddr
, laddr
);
62 writel (maddr
, &ftmac100
->mac_madr
);
63 writel (laddr
, &ftmac100
->mac_ladr
);
69 static void _ftmac100_halt(struct ftmac100_data
*priv
)
71 struct ftmac100
*ftmac100
= (struct ftmac100
*)priv
->iobase
;
72 debug ("%s()\n", __func__
);
73 writel (0, &ftmac100
->maccr
);
79 static int _ftmac100_init(struct ftmac100_data
*priv
, unsigned char enetaddr
[6])
81 struct ftmac100
*ftmac100
= (struct ftmac100
*)priv
->iobase
;
82 struct ftmac100_txdes
*txdes
= priv
->txdes
;
83 struct ftmac100_rxdes
*rxdes
= priv
->rxdes
;
86 debug ("%s()\n", __func__
);
90 /* set the ethernet address */
91 ftmac100_set_mac(priv
, enetaddr
);
94 /* disable all interrupts */
96 writel (0, &ftmac100
->imr
);
98 /* initialize descriptors */
102 txdes
[0].txdes1
= FTMAC100_TXDES1_EDOTR
;
103 rxdes
[PKTBUFSRX
- 1].rxdes1
= FTMAC100_RXDES1_EDORR
;
105 for (i
= 0; i
< PKTBUFSRX
; i
++) {
107 rxdes
[i
].rxdes2
= (unsigned int)net_rx_packets
[i
];
108 rxdes
[i
].rxdes1
|= FTMAC100_RXDES1_RXBUF_SIZE (PKTSIZE_ALIGN
);
109 rxdes
[i
].rxdes0
= FTMAC100_RXDES0_RXDMA_OWN
;
114 writel ((unsigned int)txdes
, &ftmac100
->txr_badr
);
118 writel ((unsigned int)rxdes
, &ftmac100
->rxr_badr
);
120 /* poll receive descriptor automatically */
122 writel (FTMAC100_APTC_RXPOLL_CNT (1), &ftmac100
->aptc
);
124 /* enable transmitter, receiver */
126 maccr
= FTMAC100_MACCR_XMT_EN
|
127 FTMAC100_MACCR_RCV_EN
|
128 FTMAC100_MACCR_XDMA_EN
|
129 FTMAC100_MACCR_RDMA_EN
|
130 FTMAC100_MACCR_CRC_APD
|
131 FTMAC100_MACCR_ENRX_IN_HALFTX
|
132 FTMAC100_MACCR_RX_RUNT
|
133 FTMAC100_MACCR_RX_BROADPKT
;
135 writel (maccr
, &ftmac100
->maccr
);
141 * Free receiving buffer
143 static int _ftmac100_free_pkt(struct ftmac100_data
*priv
)
145 struct ftmac100_rxdes
*curr_des
;
146 curr_des
= &priv
->rxdes
[priv
->rx_index
];
147 /* release buffer to DMA */
148 curr_des
->rxdes0
|= FTMAC100_RXDES0_RXDMA_OWN
;
149 priv
->rx_index
= (priv
->rx_index
+ 1) % PKTBUFSRX
;
154 * Receive a data block via Ethernet
156 static int __ftmac100_recv(struct ftmac100_data
*priv
)
158 struct ftmac100_rxdes
*curr_des
;
159 unsigned short rxlen
;
161 curr_des
= &priv
->rxdes
[priv
->rx_index
];
162 if (curr_des
->rxdes0
& FTMAC100_RXDES0_RXDMA_OWN
)
165 if (curr_des
->rxdes0
& (FTMAC100_RXDES0_RX_ERR
|
166 FTMAC100_RXDES0_CRC_ERR
|
167 FTMAC100_RXDES0_FTL
|
168 FTMAC100_RXDES0_RUNT
|
169 FTMAC100_RXDES0_RX_ODD_NB
)) {
173 rxlen
= FTMAC100_RXDES0_RFL (curr_des
->rxdes0
);
174 invalidate_dcache_range(curr_des
->rxdes2
,curr_des
->rxdes2
+rxlen
);
175 debug ("%s(): RX buffer %d, %x received\n",
176 __func__
, priv
->rx_index
, rxlen
);
182 * Send a data block via Ethernet
184 static int _ftmac100_send(struct ftmac100_data
*priv
, void *packet
, int length
)
186 struct ftmac100
*ftmac100
= (struct ftmac100
*)priv
->iobase
;
187 struct ftmac100_txdes
*curr_des
= priv
->txdes
;
190 if (curr_des
->txdes0
& FTMAC100_TXDES0_TXDMA_OWN
) {
191 debug ("%s(): no TX descriptor available\n", __func__
);
195 debug ("%s(%x, %x)\n", __func__
, (int)packet
, length
);
197 length
= (length
< ETH_ZLEN
) ? ETH_ZLEN
: length
;
199 /* initiate a transmit sequence */
201 flush_dcache_range((u32
)packet
,(u32
)packet
+length
);
202 curr_des
->txdes2
= (unsigned int)packet
; /* TXBUF_BADR */
204 curr_des
->txdes1
&= FTMAC100_TXDES1_EDOTR
;
205 curr_des
->txdes1
|= FTMAC100_TXDES1_FTS
|
206 FTMAC100_TXDES1_LTS
|
207 FTMAC100_TXDES1_TXBUF_SIZE (length
);
209 curr_des
->txdes0
= FTMAC100_TXDES0_TXDMA_OWN
;
213 writel (1, &ftmac100
->txpd
);
215 /* wait for transfer to succeed */
217 start
= get_timer(0);
218 while (curr_des
->txdes0
& FTMAC100_TXDES0_TXDMA_OWN
) {
219 if (get_timer(start
) >= 5) {
220 debug ("%s(): timed out\n", __func__
);
225 debug ("%s(): packet sent\n", __func__
);
230 #ifndef CONFIG_DM_ETH
232 * disable transmitter, receiver
234 static void ftmac100_halt(struct eth_device
*dev
)
236 struct ftmac100_data
*priv
= dev
->priv
;
237 return _ftmac100_halt(priv
);
240 static int ftmac100_init(struct eth_device
*dev
, bd_t
*bd
)
242 struct ftmac100_data
*priv
= dev
->priv
;
243 return _ftmac100_init(priv
, dev
->enetaddr
);
246 static int _ftmac100_recv(struct ftmac100_data
*priv
)
248 struct ftmac100_rxdes
*curr_des
;
250 curr_des
= &priv
->rxdes
[priv
->rx_index
];
251 len
= __ftmac100_recv(priv
);
253 /* pass the packet up to the protocol layers. */
254 net_process_received_packet((void *)curr_des
->rxdes2
, len
);
255 _ftmac100_free_pkt(priv
);
261 * Get a data block via Ethernet
263 static int ftmac100_recv(struct eth_device
*dev
)
265 struct ftmac100_data
*priv
= dev
->priv
;
266 return _ftmac100_recv(priv
);
270 * Send a data block via Ethernet
272 static int ftmac100_send(struct eth_device
*dev
, void *packet
, int length
)
274 struct ftmac100_data
*priv
= dev
->priv
;
275 return _ftmac100_send(priv
, packet
, length
);
278 int ftmac100_initialize (bd_t
*bd
)
280 struct eth_device
*dev
;
281 struct ftmac100_data
*priv
;
282 dev
= malloc (sizeof *dev
);
284 printf ("%s(): failed to allocate dev\n", __func__
);
287 /* Transmit and receive descriptors should align to 16 bytes */
288 priv
= memalign (16, sizeof (struct ftmac100_data
));
290 printf ("%s(): failed to allocate priv\n", __func__
);
293 memset (dev
, 0, sizeof (*dev
));
294 memset (priv
, 0, sizeof (*priv
));
296 strcpy(dev
->name
, "FTMAC100");
297 dev
->iobase
= CONFIG_FTMAC100_BASE
;
298 dev
->init
= ftmac100_init
;
299 dev
->halt
= ftmac100_halt
;
300 dev
->send
= ftmac100_send
;
301 dev
->recv
= ftmac100_recv
;
303 priv
->iobase
= dev
->iobase
;
316 static int ftmac100_start(struct udevice
*dev
)
318 struct eth_pdata
*plat
= dev_get_platdata(dev
);
319 struct ftmac100_data
*priv
= dev_get_priv(dev
);
321 return _ftmac100_init(priv
, plat
->enetaddr
);
324 static void ftmac100_stop(struct udevice
*dev
)
326 struct ftmac100_data
*priv
= dev_get_priv(dev
);
327 _ftmac100_halt(priv
);
330 static int ftmac100_send(struct udevice
*dev
, void *packet
, int length
)
332 struct ftmac100_data
*priv
= dev_get_priv(dev
);
334 ret
= _ftmac100_send(priv
, packet
, length
);
335 return ret
? 0 : -ETIMEDOUT
;
338 static int ftmac100_recv(struct udevice
*dev
, int flags
, uchar
**packetp
)
340 struct ftmac100_data
*priv
= dev_get_priv(dev
);
341 struct ftmac100_rxdes
*curr_des
;
342 curr_des
= &priv
->rxdes
[priv
->rx_index
];
344 len
= __ftmac100_recv(priv
);
346 *packetp
= (void *)curr_des
->rxdes2
;
348 return len
? len
: -EAGAIN
;
351 static int ftmac100_free_pkt(struct udevice
*dev
, uchar
*packet
, int length
)
353 struct ftmac100_data
*priv
= dev_get_priv(dev
);
354 _ftmac100_free_pkt(priv
);
358 int ftmac100_read_rom_hwaddr(struct udevice
*dev
)
360 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
361 eth_env_get_enetaddr("ethaddr", pdata
->enetaddr
);
365 static const char *dtbmacaddr(u32 ifno
)
371 if (gd
->fdt_blob
== NULL
) {
372 printf("%s: don't have a valid gd->fdt_blob!\n", __func__
);
375 node
= fdt_path_offset(gd
->fdt_blob
, "/aliases");
379 sprintf(enet
, "ethernet%d", ifno
);
380 path
= fdt_getprop(gd
->fdt_blob
, node
, enet
, NULL
);
382 printf("no alias for %s\n", enet
);
385 node
= fdt_path_offset(gd
->fdt_blob
, path
);
386 mac
= fdt_getprop(gd
->fdt_blob
, node
, "mac-address", &len
);
387 if (mac
&& is_valid_ethaddr((u8
*)mac
))
393 static int ftmac100_ofdata_to_platdata(struct udevice
*dev
)
395 struct ftmac100_data
*priv
= dev_get_priv(dev
);
396 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
398 pdata
->iobase
= devfdt_get_addr(dev
);
399 priv
->iobase
= pdata
->iobase
;
402 memcpy(pdata
->enetaddr
, mac
, 6);
407 static int ftmac100_probe(struct udevice
*dev
)
409 struct ftmac100_data
*priv
= dev_get_priv(dev
);
410 priv
->name
= dev
->name
;
414 static int ftmac100_bind(struct udevice
*dev
)
416 return device_set_name(dev
, dev
->name
);
419 static const struct eth_ops ftmac100_ops
= {
420 .start
= ftmac100_start
,
421 .send
= ftmac100_send
,
422 .recv
= ftmac100_recv
,
423 .stop
= ftmac100_stop
,
424 .free_pkt
= ftmac100_free_pkt
,
427 static const struct udevice_id ftmac100_ids
[] = {
428 { .compatible
= "andestech,atmac100" },
432 U_BOOT_DRIVER(ftmac100
) = {
435 .of_match
= ftmac100_ids
,
436 .bind
= ftmac100_bind
,
437 .ofdata_to_platdata
= ftmac100_ofdata_to_platdata
,
438 .probe
= ftmac100_probe
,
439 .ops
= &ftmac100_ops
,
440 .priv_auto_alloc_size
= sizeof(struct ftmac100_data
),
441 .platdata_auto_alloc_size
= sizeof(struct eth_pdata
),
442 .flags
= DM_FLAG_ALLOC_PRIV_DMA
,