uboot-lantiq: update to v2013.10
[openwrt.git] / package / boot / uboot-lantiq / patches / 0016-net-add-driver-for-Lantiq-XWAY-ARX100-switch.patch
1 From 7288414298b34dcda1216fee1fe38d05ea0027a2 Mon Sep 17 00:00:00 2001
2 From: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
3 Date: Mon, 17 Dec 2012 23:32:39 +0100
4 Subject: net: add driver for Lantiq XWAY ARX100 switch
5
6 Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
7
8 diff --git a/arch/mips/include/asm/arch-arx100/config.h b/arch/mips/include/asm/arch-arx100/config.h
9 index 1a6c9bc..8f955e8 100644
10 --- a/arch/mips/include/asm/arch-arx100/config.h
11 +++ b/arch/mips/include/asm/arch-arx100/config.h
12 @@ -10,17 +10,21 @@
13   * and drivers for this SoC:
14   *
15   * CONFIG_LTQ_SUPPORT_UART
16 - * - support the Danube ASC/UART interface and console
17 + * - support the ARX100 ASC/UART interface and console
18   *
19   * CONFIG_LTQ_SUPPORT_NOR_FLASH
20   * - support a parallel NOR flash via the CFI interface in flash bank 0
21   *
22   * CONFIG_LTQ_SUPPORT_ETHERNET
23 - * - support the Danube ETOP and MAC interface
24 + * - support the ARX100 ETOP and MAC interface
25   *
26   * CONFIG_LTQ_SUPPORT_SPI_FLASH
27 - * - support the Danube SPI interface and serial flash drivers
28 + * - support the ARX100 SPI interface and serial flash drivers
29   * - specific SPI flash drivers must be configured separately
30 + *
31 + * CONFIG_LTQ_SUPPORT_SPL_SPI_FLASH
32 + * - build a preloader that runs in the internal SRAM and loads
33 + *   the U-Boot from SPI flash into RAM
34   */
35  
36  #ifndef __ARX100_CONFIG_H__
37 diff --git a/arch/mips/include/asm/arch-arx100/switch.h b/arch/mips/include/asm/arch-arx100/switch.h
38 new file mode 100644
39 index 0000000..301056c
40 --- /dev/null
41 +++ b/arch/mips/include/asm/arch-arx100/switch.h
42 @@ -0,0 +1,86 @@
43 +/*
44 + *   Copyright (C) 2012-2013 Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
45 + *
46 + *   SPDX-License-Identifier:  GPL-2.0+
47 + */
48 +
49 +#ifndef __ARX100_SWITCH_H__
50 +#define __ARX100_SWITCH_H__
51 +
52 +struct ar9_switch_regs {
53 +       __be32  ps;             /* Port status*/
54 +       __be32  p0_ctl;         /* Port 0 control */
55 +       __be32  p1_ctl;         /* Port 1 control */
56 +       __be32  p2_ctl;         /* Port 2 control */
57 +       __be32  p0_vlan;        /* Port 0 VLAN control */
58 +       __be32  p1_vlan;        /* Port 1 VLAN control */
59 +       __be32  p2_vlan;        /* Port 2 VLAN control */
60 +       __be32  p0_inctl;       /* Port 0 ingress control */
61 +       __be32  p1_inctl;       /* Port 1 ingress control */
62 +       __be32  p2_inctl;       /* Port 2 ingress control */
63 +       u32     rsvd0[16];
64 +       __be32  sw_gctl0;       /* Switch global control 0 */
65 +       __be32  sw_gctl1;       /* Switch global control 1 */
66 +       __be32  arp;            /* ARP/RARP */
67 +       __be32  strm_ctl;       /* Storm control */
68 +       __be32  rgmii_ctl;      /* RGMII/GMII port control */
69 +       u32     rsvd1[4];
70 +       __be32  pmac_hd_ctl;    /* PMAC header control */
71 +       u32     rsvd2[15];
72 +       __be32  mdio_ctrl;      /* MDIO indirect access control */
73 +       __be32  mdio_data;      /* MDIO indirect read data */
74 +};
75 +
76 +#define BUILD_CHECK_AR9_REG(name, offset)      \
77 +       BUILD_BUG_ON(offsetof(struct ar9_switch_regs, name) != (offset))
78 +
79 +static inline void build_check_ar9_registers(void)
80 +{
81 +       BUILD_CHECK_AR9_REG(sw_gctl0, 0x68);
82 +       BUILD_CHECK_AR9_REG(rgmii_ctl, 0x78);
83 +       BUILD_CHECK_AR9_REG(pmac_hd_ctl, 0x8c);
84 +       BUILD_CHECK_AR9_REG(mdio_ctrl, 0xcc);
85 +       BUILD_CHECK_AR9_REG(mdio_data, 0xd0);
86 +}
87 +
88 +#define P0_CTL_FLP             (1 << 18)
89 +#define P0_CTL_FLD             (1 << 17)
90 +
91 +#define SW_GCTL0_SE            (1 << 31)
92 +
93 +#define RGMII_CTL_P1_SHIFT     10
94 +#define RGMII_CTL_P1_MASK      (0x3FF << RGMII_CTL_P1_SHIFT)
95 +#define RGMII_CTL_P0_MASK      0x3FF
96 +#define RGMII_CTL_P0IS_SHIFT   8
97 +#define RGMII_CTL_P0IS_RGMII   (0x0 << RGMII_CTL_P0IS_SHIFT)
98 +#define RGMII_CTL_P0IS_MII     (0x1 << RGMII_CTL_P0IS_SHIFT)
99 +#define RGMII_CTL_P0IS_REVMII  (0x2 << RGMII_CTL_P0IS_SHIFT)
100 +#define RGMII_CTL_P0IS_RMII    (0x3 << RGMII_CTL_P0IS_SHIFT)
101 +#define RGMII_CTL_P0RDLY_SHIFT 6
102 +#define RGMII_CTL_P0RDLY_0_0   (0x0 << RGMII_CTL_P0RDLY_SHIFT)
103 +#define RGMII_CTL_P0RDLY_1_5   (0x1 << RGMII_CTL_P0RDLY_SHIFT)
104 +#define RGMII_CTL_P0RDLY_1_75  (0x2 << RGMII_CTL_P0RDLY_SHIFT)
105 +#define RGMII_CTL_P0RDLY_2_0   (0x3 << RGMII_CTL_P0RDLY_SHIFT)
106 +#define RGMII_CTL_P0TDLY_SHIFT 4
107 +#define RGMII_CTL_P0TDLY_0_0   (0x0 << RGMII_CTL_P0TDLY_SHIFT)
108 +#define RGMII_CTL_P0TDLY_1_5   (0x1 << RGMII_CTL_P0TDLY_SHIFT)
109 +#define RGMII_CTL_P0TDLY_1_75  (0x2 << RGMII_CTL_P0TDLY_SHIFT)
110 +#define RGMII_CTL_P0TDLY_2_0   (0x3 << RGMII_CTL_P0TDLY_SHIFT)
111 +#define RGMII_CTL_P0SPD_SHIFT  2
112 +#define RGMII_CTL_P0SPD_10     (0x0 << RGMII_CTL_P0SPD_SHIFT)
113 +#define RGMII_CTL_P0SPD_100    (0x1 << RGMII_CTL_P0SPD_SHIFT)
114 +#define RGMII_CTL_P0SPD_1000   (0x2 << RGMII_CTL_P0SPD_SHIFT)
115 +#define RGMII_CTL_P0DUP_FULL   (1 << 1)
116 +#define RGMII_CTL_P0FCE_EN     (1 << 0)
117 +
118 +#define PMAC_HD_CTL_AC         (1 << 18)
119 +
120 +#define MDIO_CTRL_WD_SHIFT     16
121 +#define MDIO_CTRL_MBUSY                (1 << 15)
122 +#define MDIO_CTRL_OP_READ      (1 << 11)
123 +#define MDIO_CTRL_OP_WRITE     (1 << 10)
124 +#define MDIO_CTRL_PHYAD_SHIFT  5
125 +#define MDIO_CTRL_PHYAD_MASK   (0x1f << MDIO_CTRL_PHYAD_SHIFT)
126 +#define MDIO_CTRL_REGAD_MASK   0x1f
127 +
128 +#endif /* __ARX100_SWITCH_H__ */
129 diff --git a/drivers/net/Makefile b/drivers/net/Makefile
130 index bbc2c92..926b8c2 100644
131 --- a/drivers/net/Makefile
132 +++ b/drivers/net/Makefile
133 @@ -38,6 +38,7 @@ COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o
134  COBJS-$(CONFIG_KS8851_MLL) += ks8851_mll.o
135  COBJS-$(CONFIG_LAN91C96) += lan91c96.o
136  COBJS-$(CONFIG_LANTIQ_DANUBE_ETOP) += lantiq_danube_etop.o
137 +COBJS-$(CONFIG_LANTIQ_ARX100_SWITCH) += lantiq_arx100_switch.o
138  COBJS-$(CONFIG_LANTIQ_VRX200_SWITCH) += lantiq_vrx200_switch.o
139  COBJS-$(CONFIG_MACB) += macb.o
140  COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
141 diff --git a/drivers/net/lantiq_arx100_switch.c b/drivers/net/lantiq_arx100_switch.c
142 new file mode 100644
143 index 0000000..cc65249
144 --- /dev/null
145 +++ b/drivers/net/lantiq_arx100_switch.c
146 @@ -0,0 +1,410 @@
147 +/*
148 + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
149 + *
150 + * SPDX-License-Identifier:    GPL-2.0+
151 + */
152 +#define DEBUG
153 +#include <common.h>
154 +#include <malloc.h>
155 +#include <netdev.h>
156 +#include <miiphy.h>
157 +#include <switch.h>
158 +#include <linux/compiler.h>
159 +#include <asm/gpio.h>
160 +#include <asm/processor.h>
161 +#include <asm/lantiq/io.h>
162 +#include <asm/lantiq/eth.h>
163 +#include <asm/lantiq/pm.h>
164 +#include <asm/lantiq/reset.h>
165 +#include <asm/lantiq/dma.h>
166 +#include <asm/arch/soc.h>
167 +#include <asm/arch/switch.h>
168 +
169 +#define LTQ_ETH_RX_BUFFER_CNT          PKTBUFSRX
170 +#define LTQ_ETH_TX_BUFFER_CNT          8
171 +#define LTQ_ETH_RX_DATA_SIZE           PKTSIZE_ALIGN
172 +#define LTQ_ETH_IP_ALIGN               2
173 +
174 +#define LTQ_MDIO_DRV_NAME              "ltq-mdio"
175 +#define LTQ_ETH_DRV_NAME               "ltq-eth"
176 +
177 +#define LTQ_ETHSW_MAX_GMAC             2
178 +#define LTQ_ETHSW_PMAC                 2
179 +
180 +struct ltq_eth_priv {
181 +       struct ltq_dma_device dma_dev;
182 +       struct mii_dev *bus;
183 +       struct eth_device *dev;
184 +       struct phy_device *phymap[LTQ_ETHSW_MAX_GMAC];
185 +       int rx_num;
186 +       int tx_num;
187 +};
188 +
189 +static struct ar9_switch_regs *switch_regs =
190 +       (struct ar9_switch_regs *) CKSEG1ADDR(LTQ_SWITCH_BASE);
191 +
192 +static int ltq_mdio_is_busy(void)
193 +{
194 +       u32 mdio_ctrl = ltq_readl(&switch_regs->mdio_ctrl);
195 +
196 +       return mdio_ctrl & MDIO_CTRL_MBUSY;
197 +}
198 +
199 +static void ltq_mdio_poll(void)
200 +{
201 +       while (ltq_mdio_is_busy())
202 +               cpu_relax();
203 +
204 +       __udelay(1000);
205 +}
206 +
207 +static int ltq_mdio_read(struct mii_dev *bus, int phyad, int devad,
208 +                                       int regad)
209 +{
210 +       u32 mdio_ctrl;
211 +       int retval;
212 +
213 +       mdio_ctrl = MDIO_CTRL_MBUSY | MDIO_CTRL_OP_READ |
214 +               ((phyad << MDIO_CTRL_PHYAD_SHIFT) & MDIO_CTRL_PHYAD_MASK) |
215 +               (regad & MDIO_CTRL_REGAD_MASK);
216 +
217 +       ltq_mdio_poll();
218 +       ltq_writel(&switch_regs->mdio_ctrl, mdio_ctrl);
219 +       ltq_mdio_poll();
220 +       retval = ltq_readl(&switch_regs->mdio_data);
221 +       ltq_writel(&switch_regs->mdio_data, 0xFFFF);
222 +
223 +       debug("%s: phyad %02x, regad %02x, val %02x\n", __func__, phyad, regad, retval);
224 +
225 +       return retval;
226 +}
227 +
228 +static int ltq_mdio_write(struct mii_dev *bus, int phyad, int devad,
229 +                                       int regad, u16 val)
230 +{
231 +       u32 mdio_ctrl;
232 +
233 +       debug("%s: phyad %02x, regad %02x, val %02x\n", __func__, phyad, regad, val);
234 +
235 +       mdio_ctrl = (val << MDIO_CTRL_WD_SHIFT) | MDIO_CTRL_MBUSY |
236 +               MDIO_CTRL_OP_WRITE |
237 +               ((phyad << MDIO_CTRL_PHYAD_SHIFT) & MDIO_CTRL_PHYAD_MASK) |
238 +               (regad & MDIO_CTRL_REGAD_MASK);
239 +
240 +       ltq_mdio_poll();
241 +       ltq_writel(&switch_regs->mdio_ctrl, mdio_ctrl);
242 +
243 +       return 0;
244 +}
245 +
246 +static void ltq_eth_gmac_update(struct phy_device *phydev, int num)
247 +{
248 +}
249 +
250 +static inline u8 *ltq_eth_rx_packet_align(int rx_num)
251 +{
252 +       u8 *packet = (u8 *) NetRxPackets[rx_num];
253 +
254 +       /*
255 +        * IP header needs
256 +        */
257 +       return packet + LTQ_ETH_IP_ALIGN;
258 +}
259 +
260 +static int ltq_eth_init(struct eth_device *dev, bd_t *bis)
261 +{
262 +       struct ltq_eth_priv *priv = dev->priv;
263 +       struct ltq_dma_device *dma_dev = &priv->dma_dev;
264 +       struct phy_device *phydev;
265 +       int i;
266 +
267 +       for (i = 0; i < LTQ_ETHSW_MAX_GMAC; i++) {
268 +               phydev = priv->phymap[i];
269 +               if (!phydev)
270 +                       continue;
271 +
272 +               phy_startup(phydev);
273 +               ltq_eth_gmac_update(phydev, i);
274 +       }
275 +
276 +       for (i = 0; i < LTQ_ETH_RX_BUFFER_CNT; i++)
277 +               ltq_dma_rx_map(dma_dev, i, ltq_eth_rx_packet_align(i),
278 +                       LTQ_ETH_RX_DATA_SIZE);
279 +
280 +       ltq_dma_enable(dma_dev);
281 +
282 +       priv->rx_num = 0;
283 +       priv->tx_num = 0;
284 +
285 +       return 0;
286 +}
287 +
288 +static void ltq_eth_halt(struct eth_device *dev)
289 +{
290 +       struct ltq_eth_priv *priv = dev->priv;
291 +       struct ltq_dma_device *dma_dev = &priv->dma_dev;
292 +       struct phy_device *phydev;
293 +       int i;
294 +
295 +       ltq_dma_reset(dma_dev);
296 +
297 +       for (i = 0; i < LTQ_ETHSW_MAX_GMAC; i++) {
298 +               phydev = priv->phymap[i];
299 +               if (!phydev)
300 +                       continue;
301 +
302 +               phy_shutdown(phydev);
303 +               phydev->link = 0;
304 +               ltq_eth_gmac_update(phydev, i);
305 +       }
306 +}
307 +
308 +static int ltq_eth_send(struct eth_device *dev, void *packet, int length)
309 +{
310 +       struct ltq_eth_priv *priv = dev->priv;
311 +       struct ltq_dma_device *dma_dev = &priv->dma_dev;
312 +       int err;
313 +
314 +       err = ltq_dma_tx_map(dma_dev, priv->tx_num, packet, length, 10);
315 +       if (err) {
316 +               puts("NET: timeout on waiting for TX descriptor\n");
317 +               return -1;
318 +       }
319 +
320 +       priv->tx_num = (priv->tx_num + 1) % LTQ_ETH_TX_BUFFER_CNT;
321 +
322 +       return err;
323 +}
324 +
325 +static int ltq_eth_recv(struct eth_device *dev)
326 +{
327 +       struct ltq_eth_priv *priv = dev->priv;
328 +       struct ltq_dma_device *dma_dev = &priv->dma_dev;
329 +       u8 *packet;
330 +       int len;
331 +
332 +       if (!ltq_dma_rx_poll(dma_dev, priv->rx_num))
333 +               return 0;
334 +
335 +#if 0
336 +       printf("%s: rx_num %d\n", __func__, priv->rx_num);
337 +#endif
338 +
339 +       len = ltq_dma_rx_length(dma_dev, priv->rx_num);
340 +       packet = ltq_eth_rx_packet_align(priv->rx_num);
341 +
342 +#if 0
343 +       printf("%s: received: packet %p, len %u, rx_num %d\n",
344 +               __func__, packet, len, priv->rx_num);
345 +#endif
346 +
347 +       if (len)
348 +               NetReceive(packet, len);
349 +
350 +       ltq_dma_rx_map(dma_dev, priv->rx_num, packet,
351 +               LTQ_ETH_RX_DATA_SIZE);
352 +
353 +       priv->rx_num = (priv->rx_num + 1) % LTQ_ETH_RX_BUFFER_CNT;
354 +
355 +       return 0;
356 +}
357 +
358 +static void ltq_eth_pmac_init(void)
359 +{
360 +       /* Add CRC to packets from DMA to PMAC */
361 +       ltq_setbits(&switch_regs->pmac_hd_ctl, PMAC_HD_CTL_AC);
362 +
363 +       /* Force link up */
364 +       ltq_setbits(&switch_regs->p2_ctl, P0_CTL_FLP);
365 +}
366 +
367 +static void ltq_eth_hw_init(const struct ltq_eth_port_config *port)
368 +{
369 +       /* Power up ethernet subsystems */
370 +       ltq_pm_enable(LTQ_PM_ETH);
371 +
372 +       /* Enable switch core */
373 +       ltq_setbits(&switch_regs->sw_gctl0, SW_GCTL0_SE);
374 +
375 +       /* MII/MDIO */
376 +       gpio_set_altfunc(42, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
377 +       /* MII/MDC */
378 +       gpio_set_altfunc(43, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
379 +
380 +       ltq_eth_pmac_init();
381 +}
382 +
383 +static void ltq_eth_port_config(struct ltq_eth_priv *priv,
384 +                               const struct ltq_eth_port_config *port)
385 +{
386 +       struct phy_device *phydev;
387 +       struct switch_device *sw;
388 +       u32 rgmii_ctl;
389 +       unsigned int port_ctl, port_xmii = 0;
390 +
391 +       if (port->num > 1)
392 +               return;
393 +
394 +       rgmii_ctl = ltq_readl(&switch_regs->rgmii_ctl);
395 +
396 +       if (port->num == 1)
397 +               port_ctl = ltq_readl(&switch_regs->p1_ctl);
398 +       else
399 +               port_ctl = ltq_readl(&switch_regs->p0_ctl);
400 +
401 +       switch (port->phy_if) {
402 +       case PHY_INTERFACE_MODE_RGMII:
403 +               port_xmii = RGMII_CTL_P0IS_RGMII;
404 +
405 +               switch (port->rgmii_tx_delay) {
406 +               case 1:
407 +                       port_xmii |= RGMII_CTL_P0TDLY_1_5;
408 +                       break;
409 +               case 2:
410 +                       port_xmii |= RGMII_CTL_P0TDLY_1_75;
411 +                       break;
412 +               case 3:
413 +                       port_xmii |= RGMII_CTL_P0TDLY_2_0;
414 +                       break;
415 +               default:
416 +                       break;
417 +               }
418 +
419 +               switch (port->rgmii_rx_delay) {
420 +               case 1:
421 +                       port_xmii |= RGMII_CTL_P0RDLY_1_5;
422 +                       break;
423 +               case 2:
424 +                       port_xmii |= RGMII_CTL_P0RDLY_1_75;
425 +                       break;
426 +               case 3:
427 +                       port_xmii |= RGMII_CTL_P0RDLY_2_0;
428 +                       break;
429 +               default:
430 +                       break;
431 +               }
432 +
433 +               if (!(port->flags & LTQ_ETH_PORT_PHY)) {
434 +                       port_xmii |= (RGMII_CTL_P0SPD_1000 |
435 +                                       RGMII_CTL_P0DUP_FULL);
436 +                       port_ctl |= P0_CTL_FLP;
437 +               }
438 +
439 +               break;
440 +       case PHY_INTERFACE_MODE_MII:
441 +               port_xmii = RGMII_CTL_P0IS_MII;
442 +
443 +               if (!(port->flags & LTQ_ETH_PORT_PHY)) {
444 +                       port_xmii |= (RGMII_CTL_P0SPD_100 |
445 +                                       RGMII_CTL_P0DUP_FULL);
446 +                       port_ctl |= P0_CTL_FLP;
447 +               }
448 +
449 +               break;
450 +       default:
451 +               break;
452 +       }
453 +
454 +       if (port->num == 1) {
455 +               ltq_writel(&switch_regs->p1_ctl, port_ctl);
456 +
457 +               rgmii_ctl &= ~RGMII_CTL_P1_MASK;
458 +               rgmii_ctl |= (port_xmii << RGMII_CTL_P1_SHIFT);
459 +       } else {
460 +               ltq_writel(&switch_regs->p0_ctl, port_ctl);
461 +
462 +               rgmii_ctl &= ~RGMII_CTL_P0_MASK;
463 +               rgmii_ctl |= port_xmii;
464 +       }
465 +
466 +       ltq_writel(&switch_regs->rgmii_ctl, rgmii_ctl);
467 +
468 +       /* Connect to external switch */
469 +       if (port->flags & LTQ_ETH_PORT_SWITCH) {
470 +               sw = switch_connect(priv->bus);
471 +               if (sw)
472 +                       switch_setup(sw);
473 +       }
474 +
475 +       /* Connect to internal/external PHYs */
476 +       if (port->flags & LTQ_ETH_PORT_PHY) {
477 +               phydev = phy_connect(priv->bus, port->phy_addr, priv->dev,
478 +                                       port->phy_if);
479 +               if (phydev)
480 +                       phy_config(phydev);
481 +
482 +               priv->phymap[port->num] = phydev;
483 +       }
484 +}
485 +
486 +int ltq_eth_initialize(const struct ltq_eth_board_config *board_config)
487 +{
488 +       struct eth_device *dev;
489 +       struct mii_dev *bus;
490 +       struct ltq_eth_priv *priv;
491 +       struct ltq_dma_device *dma_dev;
492 +       const struct ltq_eth_port_config *port = &board_config->ports[0];
493 +       int i, ret;
494 +
495 +       build_check_ar9_registers();
496 +
497 +       ltq_dma_init();
498 +       ltq_eth_hw_init(port);
499 +
500 +       dev = calloc(1, sizeof(*dev));
501 +       if (!dev)
502 +               return -1;
503 +
504 +       priv = calloc(1, sizeof(*priv));
505 +       if (!priv)
506 +               return -1;
507 +
508 +       bus = mdio_alloc();
509 +       if (!bus)
510 +               return -1;
511 +
512 +       sprintf(dev->name, LTQ_ETH_DRV_NAME);
513 +       dev->priv = priv;
514 +       dev->init = ltq_eth_init;
515 +       dev->halt = ltq_eth_halt;
516 +       dev->recv = ltq_eth_recv;
517 +       dev->send = ltq_eth_send;
518 +
519 +       sprintf(bus->name, LTQ_MDIO_DRV_NAME);
520 +       bus->read = ltq_mdio_read;
521 +       bus->write = ltq_mdio_write;
522 +       bus->priv = priv;
523 +
524 +       dma_dev = &priv->dma_dev;
525 +       dma_dev->port = 0;
526 +       dma_dev->rx_chan.chan_no = 0;
527 +       dma_dev->rx_chan.class = 0;
528 +       dma_dev->rx_chan.num_desc = LTQ_ETH_RX_BUFFER_CNT;
529 +       dma_dev->rx_endian_swap = LTQ_DMA_ENDIANESS_B3_B2_B1_B0;
530 +       dma_dev->rx_burst_len = LTQ_DMA_BURST_2WORDS;
531 +       dma_dev->tx_chan.chan_no = 1;
532 +       dma_dev->tx_chan.class = 0;
533 +       dma_dev->tx_chan.num_desc = LTQ_ETH_TX_BUFFER_CNT;
534 +       dma_dev->tx_endian_swap = LTQ_DMA_ENDIANESS_B3_B2_B1_B0;
535 +       dma_dev->tx_burst_len = LTQ_DMA_BURST_2WORDS;
536 +
537 +       priv->bus = bus;
538 +       priv->dev = dev;
539 +
540 +       ret = ltq_dma_register(dma_dev);
541 +       if (ret)
542 +               return ret;
543 +
544 +       ret = mdio_register(bus);
545 +       if (ret)
546 +               return ret;
547 +
548 +       ret = eth_register(dev);
549 +       if (ret)
550 +               return ret;
551 +
552 +       for (i = 0; i < board_config->num_ports; i++)
553 +               ltq_eth_port_config(priv, &board_config->ports[i]);
554 +
555 +       return 0;
556 +}
557 -- 
558 1.8.3.2
559