nds32: ftmac100: support cache enable.
[oweals/u-boot.git] / drivers / net / ftmac100.c
1 /*
2  * Faraday FTMAC100 Ethernet
3  *
4  * (C) Copyright 2009 Faraday Technology
5  * Po-Yu Chuang <ratbert@faraday-tech.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <config.h>
11 #include <common.h>
12 #include <malloc.h>
13 #include <net.h>
14 #include <linux/io.h>
15
16 #include "ftmac100.h"
17 #ifdef CONFIG_DM_ETH
18 #include <dm.h>
19 DECLARE_GLOBAL_DATA_PTR;
20 #endif
21 #define ETH_ZLEN        60
22
23 struct ftmac100_data {
24         struct ftmac100_txdes txdes[1];
25         struct ftmac100_rxdes rxdes[PKTBUFSRX];
26         int rx_index;
27         const char *name;
28         phys_addr_t iobase;
29 };
30
31 /*
32  * Reset MAC
33  */
34 static void ftmac100_reset(struct ftmac100_data *priv)
35 {
36         struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
37
38         debug ("%s()\n", __func__);
39
40         writel (FTMAC100_MACCR_SW_RST, &ftmac100->maccr);
41
42         while (readl (&ftmac100->maccr) & FTMAC100_MACCR_SW_RST)
43                 ;
44 }
45
46 /*
47  * Set MAC address
48  */
49 static void ftmac100_set_mac(struct ftmac100_data *priv ,
50         const unsigned char *mac)
51 {
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];
55
56         debug ("%s(%x %x)\n", __func__, maddr, laddr);
57
58         writel (maddr, &ftmac100->mac_madr);
59         writel (laddr, &ftmac100->mac_ladr);
60 }
61
62 /*
63  * Disable MAC
64  */
65 static void _ftmac100_halt(struct ftmac100_data *priv)
66 {
67         struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
68         debug ("%s()\n", __func__);
69         writel (0, &ftmac100->maccr);
70 }
71
72 /*
73  * Initialize MAC
74  */
75 static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6])
76 {
77         struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
78         struct ftmac100_txdes *txdes = priv->txdes;
79         struct ftmac100_rxdes *rxdes = priv->rxdes;
80         unsigned int maccr;
81         int i;
82         debug ("%s()\n", __func__);
83
84         ftmac100_reset(priv);
85
86         /* set the ethernet address */
87         ftmac100_set_mac(priv, enetaddr);
88
89
90         /* disable all interrupts */
91
92         writel (0, &ftmac100->imr);
93
94         /* initialize descriptors */
95
96         priv->rx_index = 0;
97
98         txdes[0].txdes1                 = FTMAC100_TXDES1_EDOTR;
99         rxdes[PKTBUFSRX - 1].rxdes1     = FTMAC100_RXDES1_EDORR;
100
101         for (i = 0; i < PKTBUFSRX; i++) {
102                 /* RXBUF_BADR */
103                 rxdes[i].rxdes2 = (unsigned int)net_rx_packets[i];
104                 rxdes[i].rxdes1 |= FTMAC100_RXDES1_RXBUF_SIZE (PKTSIZE_ALIGN);
105                 rxdes[i].rxdes0 = FTMAC100_RXDES0_RXDMA_OWN;
106         }
107
108         /* transmit ring */
109
110         writel ((unsigned int)txdes, &ftmac100->txr_badr);
111
112         /* receive ring */
113
114         writel ((unsigned int)rxdes, &ftmac100->rxr_badr);
115
116         /* poll receive descriptor automatically */
117
118         writel (FTMAC100_APTC_RXPOLL_CNT (1), &ftmac100->aptc);
119
120         /* enable transmitter, receiver */
121
122         maccr = FTMAC100_MACCR_XMT_EN |
123                 FTMAC100_MACCR_RCV_EN |
124                 FTMAC100_MACCR_XDMA_EN |
125                 FTMAC100_MACCR_RDMA_EN |
126                 FTMAC100_MACCR_CRC_APD |
127                 FTMAC100_MACCR_ENRX_IN_HALFTX |
128                 FTMAC100_MACCR_RX_RUNT |
129                 FTMAC100_MACCR_RX_BROADPKT;
130
131         writel (maccr, &ftmac100->maccr);
132
133         return 0;
134 }
135
136 /*
137  * Free receiving buffer
138  */
139 static int _ftmac100_free_pkt(struct ftmac100_data *priv)
140 {
141         struct ftmac100_rxdes *curr_des;
142         curr_des = &priv->rxdes[priv->rx_index];
143         /* release buffer to DMA */
144         curr_des->rxdes0 |= FTMAC100_RXDES0_RXDMA_OWN;
145         priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
146         return 0;
147 }
148
149 /*
150  * Receive a data block via Ethernet
151  */
152 static int __ftmac100_recv(struct ftmac100_data *priv)
153 {
154         struct ftmac100_rxdes *curr_des;
155         unsigned short rxlen;
156
157         curr_des = &priv->rxdes[priv->rx_index];
158         if (curr_des->rxdes0 & FTMAC100_RXDES0_RXDMA_OWN)
159                 return 0;
160
161         if (curr_des->rxdes0 & (FTMAC100_RXDES0_RX_ERR |
162                                 FTMAC100_RXDES0_CRC_ERR |
163                                 FTMAC100_RXDES0_FTL |
164                                 FTMAC100_RXDES0_RUNT |
165                                 FTMAC100_RXDES0_RX_ODD_NB)) {
166                 return 0;
167         }
168
169         rxlen = FTMAC100_RXDES0_RFL (curr_des->rxdes0);
170         invalidate_dcache_range(curr_des->rxdes2,curr_des->rxdes2+rxlen);
171         debug ("%s(): RX buffer %d, %x received\n",
172                __func__, priv->rx_index, rxlen);
173
174         return rxlen;
175 }
176
177 /*
178  * Send a data block via Ethernet
179  */
180 static int _ftmac100_send(struct ftmac100_data *priv, void *packet, int length)
181 {
182         struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
183         struct ftmac100_txdes *curr_des = priv->txdes;
184         ulong start;
185
186         if (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) {
187                 debug ("%s(): no TX descriptor available\n", __func__);
188                 return -1;
189         }
190
191         debug ("%s(%x, %x)\n", __func__, (int)packet, length);
192
193         length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
194
195         /* initiate a transmit sequence */
196
197         flush_dcache_range((u32)packet,(u32)packet+length);
198         curr_des->txdes2 = (unsigned int)packet;        /* TXBUF_BADR */
199
200         curr_des->txdes1 &= FTMAC100_TXDES1_EDOTR;
201         curr_des->txdes1 |= FTMAC100_TXDES1_FTS |
202                             FTMAC100_TXDES1_LTS |
203                             FTMAC100_TXDES1_TXBUF_SIZE (length);
204
205         curr_des->txdes0 = FTMAC100_TXDES0_TXDMA_OWN;
206
207         /* start transmit */
208
209         writel (1, &ftmac100->txpd);
210
211         /* wait for transfer to succeed */
212
213         start = get_timer(0);
214         while (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) {
215                 if (get_timer(start) >= 5) {
216                         debug ("%s(): timed out\n", __func__);
217                         return -1;
218                 }
219         }
220
221         debug ("%s(): packet sent\n", __func__);
222
223         return 0;
224 }
225
226 #ifndef CONFIG_DM_ETH
227 /*
228  * disable transmitter, receiver
229  */
230 static void ftmac100_halt(struct eth_device *dev)
231 {
232         struct ftmac100_data *priv = dev->priv;
233         return _ftmac100_halt(priv);
234 }
235
236 static int ftmac100_init(struct eth_device *dev, bd_t *bd)
237 {
238         struct ftmac100_data *priv = dev->priv;
239         return _ftmac100_init(priv , dev->enetaddr);
240 }
241
242 static int _ftmac100_recv(struct ftmac100_data *priv)
243 {
244         struct ftmac100_rxdes *curr_des;
245         unsigned short len;
246         curr_des = &priv->rxdes[priv->rx_index];
247         len = __ftmac100_recv(priv);
248         if (len) {
249                 /* pass the packet up to the protocol layers. */
250                 net_process_received_packet((void *)curr_des->rxdes2, len);
251                 _ftmac100_free_pkt(priv);
252         }
253         return len ? 1 : 0;
254 }
255
256 /*
257  * Get a data block via Ethernet
258  */
259 static int ftmac100_recv(struct eth_device *dev)
260 {
261         struct ftmac100_data *priv = dev->priv;
262         return _ftmac100_recv(priv);
263 }
264
265 /*
266  * Send a data block via Ethernet
267  */
268 static int ftmac100_send(struct eth_device *dev, void *packet, int length)
269 {
270         struct ftmac100_data *priv = dev->priv;
271         return _ftmac100_send(priv , packet , length);
272 }
273
274 int ftmac100_initialize (bd_t *bd)
275 {
276         struct eth_device *dev;
277         struct ftmac100_data *priv;
278         dev = malloc (sizeof *dev);
279         if (!dev) {
280                 printf ("%s(): failed to allocate dev\n", __func__);
281                 goto out;
282         }
283         /* Transmit and receive descriptors should align to 16 bytes */
284         priv = memalign (16, sizeof (struct ftmac100_data));
285         if (!priv) {
286                 printf ("%s(): failed to allocate priv\n", __func__);
287                 goto free_dev;
288         }
289         memset (dev, 0, sizeof (*dev));
290         memset (priv, 0, sizeof (*priv));
291
292         strcpy(dev->name, "FTMAC100");
293         dev->iobase     = CONFIG_FTMAC100_BASE;
294         dev->init       = ftmac100_init;
295         dev->halt       = ftmac100_halt;
296         dev->send       = ftmac100_send;
297         dev->recv       = ftmac100_recv;
298         dev->priv       = priv;
299         priv->iobase    = dev->iobase;
300         eth_register (dev);
301
302         return 1;
303
304 free_dev:
305         free (dev);
306 out:
307         return 0;
308 }
309 #endif
310
311 #ifdef CONFIG_DM_ETH
312 static int ftmac100_start(struct udevice *dev)
313 {
314         struct eth_pdata *plat = dev_get_platdata(dev);
315         struct ftmac100_data *priv = dev_get_priv(dev);
316
317         return _ftmac100_init(priv, plat->enetaddr);
318 }
319
320 static void ftmac100_stop(struct udevice *dev)
321 {
322         struct ftmac100_data *priv = dev_get_priv(dev);
323         _ftmac100_halt(priv);
324 }
325
326 static int ftmac100_send(struct udevice *dev, void *packet, int length)
327 {
328         struct ftmac100_data *priv = dev_get_priv(dev);
329         int ret;
330         ret = _ftmac100_send(priv , packet , length);
331         return ret ? 0 : -ETIMEDOUT;
332 }
333
334 static int ftmac100_recv(struct udevice *dev, int flags, uchar **packetp)
335 {
336         struct ftmac100_data *priv = dev_get_priv(dev);
337         struct ftmac100_rxdes *curr_des;
338         curr_des = &priv->rxdes[priv->rx_index];
339         int len;
340         len = __ftmac100_recv(priv);
341         if (len)
342                 *packetp = (void *)curr_des->rxdes2;
343
344         return len ? len : -EAGAIN;
345 }
346
347 static int ftmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
348 {
349         struct ftmac100_data *priv = dev_get_priv(dev);
350         _ftmac100_free_pkt(priv);
351         return 0;
352 }
353
354 int ftmac100_read_rom_hwaddr(struct udevice *dev)
355 {
356         struct eth_pdata *pdata = dev_get_platdata(dev);
357         eth_env_get_enetaddr("ethaddr", pdata->enetaddr);
358         return 0;
359 }
360
361 static const char *dtbmacaddr(u32 ifno)
362 {
363         int node, len;
364         char enet[16];
365         const char *mac;
366         const char *path;
367         if (gd->fdt_blob == NULL) {
368                 printf("%s: don't have a valid gd->fdt_blob!\n", __func__);
369                 return NULL;
370         }
371         node = fdt_path_offset(gd->fdt_blob, "/aliases");
372         if (node < 0)
373                 return NULL;
374
375         sprintf(enet, "ethernet%d", ifno);
376         path = fdt_getprop(gd->fdt_blob, node, enet, NULL);
377         if (!path) {
378                 printf("no alias for %s\n", enet);
379                 return NULL;
380         }
381         node = fdt_path_offset(gd->fdt_blob, path);
382         mac = fdt_getprop(gd->fdt_blob, node, "mac-address", &len);
383         if (mac && is_valid_ethaddr((u8 *)mac))
384                 return mac;
385
386         return NULL;
387 }
388
389 static int ftmac100_ofdata_to_platdata(struct udevice *dev)
390 {
391         struct ftmac100_data *priv = dev_get_priv(dev);
392         struct eth_pdata *pdata = dev_get_platdata(dev);
393         const char *mac;
394         pdata->iobase = devfdt_get_addr(dev);
395         priv->iobase = pdata->iobase;
396         mac = dtbmacaddr(0);
397         if (mac)
398                 memcpy(pdata->enetaddr , mac , 6);
399
400         return 0;
401 }
402
403 static int ftmac100_probe(struct udevice *dev)
404 {
405         struct ftmac100_data *priv = dev_get_priv(dev);
406         priv->name = dev->name;
407         return 0;
408 }
409
410 static int ftmac100_bind(struct udevice *dev)
411 {
412         return device_set_name(dev, dev->name);
413 }
414
415 static const struct eth_ops ftmac100_ops = {
416         .start  = ftmac100_start,
417         .send   = ftmac100_send,
418         .recv   = ftmac100_recv,
419         .stop   = ftmac100_stop,
420         .free_pkt = ftmac100_free_pkt,
421 };
422
423 static const struct udevice_id ftmac100_ids[] = {
424         { .compatible = "andestech,atmac100" },
425         { }
426 };
427
428 U_BOOT_DRIVER(ftmac100) = {
429         .name   = "nds32_mac",
430         .id     = UCLASS_ETH,
431         .of_match = ftmac100_ids,
432         .bind   = ftmac100_bind,
433         .ofdata_to_platdata = ftmac100_ofdata_to_platdata,
434         .probe  = ftmac100_probe,
435         .ops    = &ftmac100_ops,
436         .priv_auto_alloc_size = sizeof(struct ftmac100_data),
437         .platdata_auto_alloc_size = sizeof(struct eth_pdata),
438         .flags  = DM_FLAG_ALLOC_PRIV_DMA,
439 };
440 #endif