1 From 7591c5702cfe842f415e42f387532fe71ea3640f Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Fri, 9 Mar 2012 19:03:40 +0100
4 Subject: [PATCH 43/70] NET: adds driver for lantiq vr9 ethernet
7 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 2 +-
8 arch/mips/lantiq/xway/devices.c | 20 +
9 arch/mips/lantiq/xway/devices.h | 1 +
10 drivers/net/ethernet/Kconfig | 6 +
11 drivers/net/ethernet/Makefile | 1 +
12 drivers/net/ethernet/lantiq_vrx200.c | 1358 ++++++++++++++++++++
13 6 files changed, 1387 insertions(+), 1 deletions(-)
14 create mode 100644 drivers/net/ethernet/lantiq_vrx200.c
16 diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
17 index ab2d236..d1b8cc8 100644
18 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
19 +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
22 /* GBIT - gigabit switch */
23 #define LTQ_GBIT_BASE_ADDR 0x1E108000
24 -#define LTQ_GBIT_SIZE 0x200
25 +#define LTQ_GBIT_SIZE 0x4000
28 #define LTQ_DMA_BASE_ADDR 0x1E104100
29 diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
30 index eab4644d..5efa4f3 100644
31 --- a/arch/mips/lantiq/xway/devices.c
32 +++ b/arch/mips/lantiq/xway/devices.c
33 @@ -83,6 +83,7 @@ static struct platform_device ltq_etop = {
35 .resource = ltq_etop_resources,
41 @@ -96,3 +97,22 @@ ltq_register_etop(struct ltq_eth_data *eth)
42 platform_device_register(<q_etop);
47 +static struct resource ltq_vrx200_resources[] = {
48 + MEM_RES("gbit", LTQ_GBIT_BASE_ADDR, LTQ_GBIT_SIZE),
51 +static struct platform_device ltq_vrx200 = {
52 + .name = "ltq_vrx200",
53 + .resource = ltq_vrx200_resources,
59 +ltq_register_vrx200(struct ltq_eth_data *eth)
61 + ltq_vrx200.dev.platform_data = eth;
62 + platform_device_register(<q_vrx200);
64 diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
65 index d825cbd..08befd9 100644
66 --- a/arch/mips/lantiq/xway/devices.h
67 +++ b/arch/mips/lantiq/xway/devices.h
68 @@ -17,5 +17,6 @@ extern void ltq_register_gpio_stp(void);
69 extern void ltq_register_ase_asc(void);
70 extern void ltq_register_etop(struct ltq_eth_data *eth);
71 extern void xway_register_nand(struct mtd_partition *parts, int count);
72 +extern void ltq_register_vrx200(struct ltq_eth_data *eth);
75 diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
76 index 597f4d4..2035cab 100644
77 --- a/drivers/net/ethernet/Kconfig
78 +++ b/drivers/net/ethernet/Kconfig
79 @@ -84,6 +84,12 @@ config LANTIQ_ETOP
81 Support for the MII0 inside the Lantiq SoC
84 + tristate "Lantiq SoC vrx200 driver"
85 + depends on SOC_TYPE_XWAY
87 + Support for the MII0 inside the Lantiq SoC
89 source "drivers/net/ethernet/marvell/Kconfig"
90 source "drivers/net/ethernet/mellanox/Kconfig"
91 source "drivers/net/ethernet/micrel/Kconfig"
92 diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
93 index be5dde0..4fde2be 100644
94 --- a/drivers/net/ethernet/Makefile
95 +++ b/drivers/net/ethernet/Makefile
96 @@ -35,6 +35,7 @@ obj-$(CONFIG_IP1000) += icplus/
97 obj-$(CONFIG_JME) += jme.o
98 obj-$(CONFIG_KORINA) += korina.o
99 obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
100 +obj-$(CONFIG_LANTIQ_VRX200) += lantiq_vrx200.o
101 obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/
102 obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/
103 obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/
104 diff --git a/drivers/net/ethernet/lantiq_vrx200.c b/drivers/net/ethernet/lantiq_vrx200.c
106 index 0000000..d79d380
108 +++ b/drivers/net/ethernet/lantiq_vrx200.c
111 + * This program is free software; you can redistribute it and/or modify it
112 + * under the terms of the GNU General Public License version 2 as published
113 + * by the Free Software Foundation.
115 + * This program is distributed in the hope that it will be useful,
116 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
117 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
118 + * GNU General Public License for more details.
120 + * You should have received a copy of the GNU General Public License
121 + * along with this program; if not, write to the Free Software
122 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
124 + * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
127 +#include <linux/kernel.h>
128 +#include <linux/slab.h>
129 +#include <linux/errno.h>
130 +#include <linux/types.h>
131 +#include <linux/interrupt.h>
132 +#include <linux/uaccess.h>
133 +#include <linux/in.h>
134 +#include <linux/netdevice.h>
135 +#include <linux/etherdevice.h>
136 +#include <linux/phy.h>
137 +#include <linux/ip.h>
138 +#include <linux/tcp.h>
139 +#include <linux/skbuff.h>
140 +#include <linux/mm.h>
141 +#include <linux/platform_device.h>
142 +#include <linux/ethtool.h>
143 +#include <linux/init.h>
144 +#include <linux/delay.h>
145 +#include <linux/io.h>
146 +#include <linux/dma-mapping.h>
147 +#include <linux/module.h>
148 +#include <linux/clk.h>
150 +#include <asm/checksum.h>
152 +#include <lantiq_soc.h>
153 +#include <xway_dma.h>
154 +#include <lantiq_platform.h>
156 +#define LTQ_SWITCH_BASE 0x1E108000
157 +#define LTQ_SWITCH_CORE_BASE LTQ_SWITCH_BASE
158 +#define LTQ_SWITCH_TOP_PDI_BASE LTQ_SWITCH_CORE_BASE
159 +#define LTQ_SWITCH_BM_PDI_BASE (LTQ_SWITCH_CORE_BASE + 4 * 0x40)
160 +#define LTQ_SWITCH_MAC_PDI_0_BASE (LTQ_SWITCH_CORE_BASE + 4 * 0x900)
161 +#define LTQ_SWITCH_MAC_PDI_X_BASE(x) (LTQ_SWITCH_MAC_PDI_0_BASE + x * 0x30)
162 +#define LTQ_SWITCH_TOPLEVEL_BASE (LTQ_SWITCH_BASE + 4 * 0xC40)
163 +#define LTQ_SWITCH_MDIO_PDI_BASE (LTQ_SWITCH_TOPLEVEL_BASE)
164 +#define LTQ_SWITCH_MII_PDI_BASE (LTQ_SWITCH_TOPLEVEL_BASE + 4 * 0x36)
165 +#define LTQ_SWITCH_PMAC_PDI_BASE (LTQ_SWITCH_TOPLEVEL_BASE + 4 * 0x82)
167 +#define LTQ_ETHSW_MAC_CTRL0_PADEN (1 << 8)
168 +#define LTQ_ETHSW_MAC_CTRL0_FCS (1 << 7)
169 +#define LTQ_ETHSW_MAC_CTRL1_SHORTPRE (1 << 8)
170 +#define LTQ_ETHSW_MAC_CTRL2_MLEN (1 << 3)
171 +#define LTQ_ETHSW_MAC_CTRL2_LCHKL (1 << 2)
172 +#define LTQ_ETHSW_MAC_CTRL2_LCHKS_DIS 0
173 +#define LTQ_ETHSW_MAC_CTRL2_LCHKS_UNTAG 1
174 +#define LTQ_ETHSW_MAC_CTRL2_LCHKS_TAG 2
175 +#define LTQ_ETHSW_MAC_CTRL6_RBUF_DLY_WP_SHIFT 9
176 +#define LTQ_ETHSW_MAC_CTRL6_RXBUF_BYPASS (1 << 6)
177 +#define LTQ_ETHSW_GLOB_CTRL_SE (1 << 15)
178 +#define LTQ_ETHSW_MDC_CFG1_MCEN (1 << 8)
179 +#define LTQ_ETHSW_PMAC_HD_CTL_FC (1 << 10)
180 +#define LTQ_ETHSW_PMAC_HD_CTL_RC (1 << 4)
181 +#define LTQ_ETHSW_PMAC_HD_CTL_AC (1 << 2)
182 +#define ADVERTIZE_MPD (1 << 10)
184 +#define MDIO_DEVAD_NONE (-1)
186 +#define LTQ_ETH_RX_BUFFER_CNT PKTBUFSRX
188 +#define LTQ_MDIO_DRV_NAME "ltq-mdio"
189 +#define LTQ_ETH_DRV_NAME "ltq-eth"
191 +#define LTQ_ETHSW_MAX_GMAC 1
192 +#define LTQ_ETHSW_PMAC 1
194 +#define ltq_setbits(a, set) \
195 + ltq_w32(ltq_r32(a) | (set), a)
197 +enum ltq_reset_modules {
207 +dbg_ltq_writel(void *a, unsigned int b)
212 +int ltq_reset_once(enum ltq_reset_modules module, ulong usec);
214 +struct ltq_ethsw_mac_pdi_x_regs {
215 + u32 pstat; /* Port status */
216 + u32 pisr; /* Interrupt status */
217 + u32 pier; /* Interrupt enable */
218 + u32 ctrl_0; /* Control 0 */
219 + u32 ctrl_1; /* Control 1 */
220 + u32 ctrl_2; /* Control 2 */
221 + u32 ctrl_3; /* Control 3 */
222 + u32 ctrl_4; /* Control 4 */
223 + u32 ctrl_5; /* Control 5 */
224 + u32 ctrl_6; /* Control 6 */
225 + u32 bufst; /* TX/RX buffer control */
226 + u32 testen; /* Test enable */
229 +struct ltq_ethsw_mac_pdi_regs {
230 + struct ltq_ethsw_mac_pdi_x_regs mac[12];
233 +struct ltq_ethsw_mdio_pdi_regs {
234 + u32 glob_ctrl; /* Global control 0 */
236 + u32 mdio_ctrl; /* MDIO control */
237 + u32 mdio_read; /* MDIO read data */
238 + u32 mdio_write; /* MDIO write data */
239 + u32 mdc_cfg_0; /* MDC clock configuration 0 */
240 + u32 mdc_cfg_1; /* MDC clock configuration 1 */
242 + u32 phy_addr_5; /* PHY address port 5 */
243 + u32 phy_addr_4; /* PHY address port 4 */
244 + u32 phy_addr_3; /* PHY address port 3 */
245 + u32 phy_addr_2; /* PHY address port 2 */
246 + u32 phy_addr_1; /* PHY address port 1 */
247 + u32 phy_addr_0; /* PHY address port 0 */
248 + u32 mdio_stat_0; /* MDIO PHY polling status port 0 */
249 + u32 mdio_stat_1; /* MDIO PHY polling status port 1 */
250 + u32 mdio_stat_2; /* MDIO PHY polling status port 2 */
251 + u32 mdio_stat_3; /* MDIO PHY polling status port 3 */
252 + u32 mdio_stat_4; /* MDIO PHY polling status port 4 */
253 + u32 mdio_stat_5; /* MDIO PHY polling status port 5 */
256 +struct ltq_ethsw_mii_pdi_regs {
257 + u32 mii_cfg0; /* xMII port 0 configuration */
258 + u32 pcdu0; /* Port 0 clock delay configuration */
259 + u32 mii_cfg1; /* xMII port 1 configuration */
260 + u32 pcdu1; /* Port 1 clock delay configuration */
261 + u32 mii_cfg2; /* xMII port 2 configuration */
263 + u32 mii_cfg3; /* xMII port 3 configuration */
265 + u32 mii_cfg4; /* xMII port 4 configuration */
267 + u32 mii_cfg5; /* xMII port 5 configuration */
268 + u32 pcdu5; /* Port 5 clock delay configuration */
271 +struct ltq_ethsw_pmac_pdi_regs {
272 + u32 hd_ctl; /* PMAC header control */
273 + u32 tl; /* PMAC type/length */
274 + u32 sa1; /* PMAC source address 1 */
275 + u32 sa2; /* PMAC source address 2 */
276 + u32 sa3; /* PMAC source address 3 */
277 + u32 da1; /* PMAC destination address 1 */
278 + u32 da2; /* PMAC destination address 2 */
279 + u32 da3; /* PMAC destination address 3 */
280 + u32 vlan; /* PMAC VLAN */
281 + u32 rx_ipg; /* PMAC interpacket gap in RX direction */
282 + u32 st_etype; /* PMAC special tag ethertype */
283 + u32 ewan; /* PMAC ethernet WAN group */
286 +struct ltq_mdio_phy_addr_reg {
290 + unsigned lnkst:2; /* Link status control */
291 + unsigned speed:2; /* Speed control */
292 + unsigned fdup:2; /* Full duplex control */
293 + unsigned fcontx:2; /* Flow control mode TX */
294 + unsigned fconrx:2; /* Flow control mode RX */
295 + unsigned addr:5; /* PHY address */
301 +enum ltq_mdio_phy_addr_lnkst {
302 + LTQ_MDIO_PHY_ADDR_LNKST_AUTO = 0,
303 + LTQ_MDIO_PHY_ADDR_LNKST_UP = 1,
304 + LTQ_MDIO_PHY_ADDR_LNKST_DOWN = 2,
307 +enum ltq_mdio_phy_addr_speed {
308 + LTQ_MDIO_PHY_ADDR_SPEED_M10 = 0,
309 + LTQ_MDIO_PHY_ADDR_SPEED_M100 = 1,
310 + LTQ_MDIO_PHY_ADDR_SPEED_G1 = 2,
311 + LTQ_MDIO_PHY_ADDR_SPEED_AUTO = 3,
314 +enum ltq_mdio_phy_addr_fdup {
315 + LTQ_MDIO_PHY_ADDR_FDUP_AUTO = 0,
316 + LTQ_MDIO_PHY_ADDR_FDUP_ENABLE = 1,
317 + LTQ_MDIO_PHY_ADDR_FDUP_DISABLE = 3,
320 +enum ltq_mdio_phy_addr_fcon {
321 + LTQ_MDIO_PHY_ADDR_FCON_AUTO = 0,
322 + LTQ_MDIO_PHY_ADDR_FCON_ENABLE = 1,
323 + LTQ_MDIO_PHY_ADDR_FCON_DISABLE = 3,
326 +struct ltq_mii_mii_cfg_reg {
329 + unsigned res:1; /* Hardware reset */
330 + unsigned en:1; /* xMII interface enable */
331 + unsigned isol:1; /* xMII interface isolate */
332 + unsigned ldclkdis:1; /* Link down clock disable */
334 + unsigned crs:2; /* CRS sensitivity config */
335 + unsigned rgmii_ibs:1; /* RGMII In Band status */
336 + unsigned rmii:1; /* RMII ref clock direction */
337 + unsigned miirate:3; /* xMII interface clock rate */
338 + unsigned miimode:4; /* xMII interface mode */
344 +enum ltq_mii_mii_cfg_miirate {
345 + LTQ_MII_MII_CFG_MIIRATE_M2P5 = 0,
346 + LTQ_MII_MII_CFG_MIIRATE_M25 = 1,
347 + LTQ_MII_MII_CFG_MIIRATE_M125 = 2,
348 + LTQ_MII_MII_CFG_MIIRATE_M50 = 3,
349 + LTQ_MII_MII_CFG_MIIRATE_AUTO = 4,
352 +enum ltq_mii_mii_cfg_miimode {
353 + LTQ_MII_MII_CFG_MIIMODE_MIIP = 0,
354 + LTQ_MII_MII_CFG_MIIMODE_MIIM = 1,
355 + LTQ_MII_MII_CFG_MIIMODE_RMIIP = 2,
356 + LTQ_MII_MII_CFG_MIIMODE_RMIIM = 3,
357 + LTQ_MII_MII_CFG_MIIMODE_RGMII = 4,
360 +struct ltq_eth_priv {
361 + struct ltq_dma_device *dma_dev;
362 + struct mii_dev *bus;
363 + struct eth_device *dev;
364 + struct phy_device *phymap[LTQ_ETHSW_MAX_GMAC];
368 +enum ltq_mdio_mbusy {
369 + LTQ_MDIO_MBUSY_IDLE = 0,
370 + LTQ_MDIO_MBUSY_BUSY = 1,
374 + LTQ_MDIO_OP_WRITE = 1,
375 + LTQ_MDIO_OP_READ = 2,
378 +struct ltq_mdio_access {
391 +enum LTQ_ETH_PORT_FLAGS {
392 + LTQ_ETH_PORT_NONE = 0,
393 + LTQ_ETH_PORT_PHY = 1,
394 + LTQ_ETH_PORT_SWITCH = (1 << 1),
395 + LTQ_ETH_PORT_MAC = (1 << 2),
398 +struct ltq_eth_port_config {
402 + phy_interface_t phy_if;
405 +struct ltq_eth_board_config {
406 + const struct ltq_eth_port_config *ports;
410 +static const struct ltq_eth_port_config eth_port_config[] = {
411 + /* GMAC0: external Lantiq PEF7071 10/100/1000 PHY for LAN port 0 */
412 + { 0, 0x0, LTQ_ETH_PORT_PHY, PHY_INTERFACE_MODE_RGMII },
413 + /* GMAC1: external Lantiq PEF7071 10/100/1000 PHY for LAN port 1 */
414 + { 1, 0x1, LTQ_ETH_PORT_PHY, PHY_INTERFACE_MODE_RGMII },
417 +static const struct ltq_eth_board_config board_config = {
418 + .ports = eth_port_config,
419 + .num_ports = ARRAY_SIZE(eth_port_config),
422 +static struct ltq_ethsw_mac_pdi_regs *ltq_ethsw_mac_pdi_regs =
423 + (struct ltq_ethsw_mac_pdi_regs *) CKSEG1ADDR(LTQ_SWITCH_MAC_PDI_0_BASE);
425 +static struct ltq_ethsw_mdio_pdi_regs *ltq_ethsw_mdio_pdi_regs =
426 + (struct ltq_ethsw_mdio_pdi_regs *) CKSEG1ADDR(LTQ_SWITCH_MDIO_PDI_BASE);
428 +static struct ltq_ethsw_mii_pdi_regs *ltq_ethsw_mii_pdi_regs =
429 + (struct ltq_ethsw_mii_pdi_regs *) CKSEG1ADDR(LTQ_SWITCH_MII_PDI_BASE);
431 +static struct ltq_ethsw_pmac_pdi_regs *ltq_ethsw_pmac_pdi_regs =
432 + (struct ltq_ethsw_pmac_pdi_regs *) CKSEG1ADDR(LTQ_SWITCH_PMAC_PDI_BASE);
435 +#define MAX_DMA_CHAN 0x8
436 +#define MAX_DMA_CRC_LEN 0x4
437 +#define MAX_DMA_DATA_LEN 0x600
439 +/* use 2 static channels for TX/RX
440 + depending on the SoC we need to use different DMA channels for ethernet */
441 +#define LTQ_ETOP_TX_CHANNEL 1
442 +#define LTQ_ETOP_RX_CHANNEL 0
444 +#define IS_TX(x) (x == LTQ_ETOP_TX_CHANNEL)
445 +#define IS_RX(x) (x == LTQ_ETOP_RX_CHANNEL)
447 +#define DRV_VERSION "1.0"
449 +static void __iomem *ltq_vrx200_membase;
451 +struct ltq_vrx200_chan {
454 + struct net_device *netdev;
455 + struct napi_struct napi;
456 + struct ltq_dma_channel dma;
457 + struct sk_buff *skb[LTQ_DESC_NUM];
460 +struct ltq_vrx200_priv {
461 + struct net_device *netdev;
462 + struct ltq_eth_data *pldata;
463 + struct resource *res;
465 + struct mii_bus *mii_bus;
466 + struct phy_device *phydev;
468 + struct ltq_vrx200_chan ch[MAX_DMA_CHAN];
469 + int tx_free[MAX_DMA_CHAN >> 1];
473 + struct clk *clk_ppe;
476 +static int ltq_vrx200_mdio_wr(struct mii_bus *bus, int phy_addr,
477 + int phy_reg, u16 phy_data);
480 +ltq_vrx200_alloc_skb(struct ltq_vrx200_chan *ch)
482 + ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN);
483 + if (!ch->skb[ch->dma.desc])
485 + ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
486 + ch->skb[ch->dma.desc]->data, MAX_DMA_DATA_LEN,
488 + ch->dma.desc_base[ch->dma.desc].addr =
489 + CPHYSADDR(ch->skb[ch->dma.desc]->data);
490 + ch->dma.desc_base[ch->dma.desc].ctl =
491 + LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
493 + skb_reserve(ch->skb[ch->dma.desc], NET_IP_ALIGN);
498 +ltq_vrx200_hw_receive(struct ltq_vrx200_chan *ch)
500 + struct ltq_vrx200_priv *priv = netdev_priv(ch->netdev);
501 + struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
502 + struct sk_buff *skb = ch->skb[ch->dma.desc];
503 + int len = (desc->ctl & LTQ_DMA_SIZE_MASK) - MAX_DMA_CRC_LEN;
504 + unsigned long flags;
506 + spin_lock_irqsave(&priv->lock, flags);
507 + if (ltq_vrx200_alloc_skb(ch)) {
508 + netdev_err(ch->netdev,
509 + "failed to allocate new rx buffer, stopping DMA\n");
510 + ltq_dma_close(&ch->dma);
513 + ch->dma.desc %= LTQ_DESC_NUM;
514 + spin_unlock_irqrestore(&priv->lock, flags);
517 + skb->dev = ch->netdev;
518 + skb->protocol = eth_type_trans(skb, ch->netdev);
519 + netif_receive_skb(skb);
523 +ltq_vrx200_poll_rx(struct napi_struct *napi, int budget)
525 + struct ltq_vrx200_chan *ch = container_of(napi,
526 + struct ltq_vrx200_chan, napi);
527 + struct ltq_vrx200_priv *priv = netdev_priv(ch->netdev);
530 + unsigned long flags;
532 + while ((rx < budget) && !complete) {
533 + struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
535 + if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
536 + ltq_vrx200_hw_receive(ch);
542 + if (complete || !rx) {
543 + napi_complete(&ch->napi);
544 + spin_lock_irqsave(&priv->lock, flags);
545 + ltq_dma_ack_irq(&ch->dma);
546 + spin_unlock_irqrestore(&priv->lock, flags);
552 +ltq_vrx200_poll_tx(struct napi_struct *napi, int budget)
554 + struct ltq_vrx200_chan *ch =
555 + container_of(napi, struct ltq_vrx200_chan, napi);
556 + struct ltq_vrx200_priv *priv = netdev_priv(ch->netdev);
557 + struct netdev_queue *txq =
558 + netdev_get_tx_queue(ch->netdev, ch->idx >> 1);
559 + unsigned long flags;
561 + spin_lock_irqsave(&priv->lock, flags);
562 + while ((ch->dma.desc_base[ch->tx_free].ctl &
563 + (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
564 + dev_kfree_skb_any(ch->skb[ch->tx_free]);
565 + ch->skb[ch->tx_free] = NULL;
566 + memset(&ch->dma.desc_base[ch->tx_free], 0,
567 + sizeof(struct ltq_dma_desc));
569 + ch->tx_free %= LTQ_DESC_NUM;
571 + spin_unlock_irqrestore(&priv->lock, flags);
573 + if (netif_tx_queue_stopped(txq))
574 + netif_tx_start_queue(txq);
575 + napi_complete(&ch->napi);
576 + spin_lock_irqsave(&priv->lock, flags);
577 + ltq_dma_ack_irq(&ch->dma);
578 + spin_unlock_irqrestore(&priv->lock, flags);
583 +ltq_vrx200_dma_irq(int irq, void *_priv)
585 + struct ltq_vrx200_priv *priv = _priv;
586 + int ch = irq - LTQ_DMA_ETOP;
588 + napi_schedule(&priv->ch[ch].napi);
589 + return IRQ_HANDLED;
593 +ltq_vrx200_free_channel(struct net_device *dev, struct ltq_vrx200_chan *ch)
595 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
597 + ltq_dma_free(&ch->dma);
599 + free_irq(ch->dma.irq, priv);
600 + if (IS_RX(ch->idx)) {
602 + for (desc = 0; desc < LTQ_DESC_NUM; desc++)
603 + dev_kfree_skb_any(ch->skb[ch->dma.desc]);
608 +ltq_vrx200_hw_exit(struct net_device *dev)
610 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
613 + clk_disable(priv->clk_ppe);
615 + for (i = 0; i < MAX_DMA_CHAN; i++)
616 + if (IS_TX(i) || IS_RX(i))
617 + ltq_vrx200_free_channel(dev, &priv->ch[i]);
620 +static void *ltq_eth_phy_addr_reg(int num)
624 + return <q_ethsw_mdio_pdi_regs->phy_addr_0;
626 + return <q_ethsw_mdio_pdi_regs->phy_addr_1;
628 + return <q_ethsw_mdio_pdi_regs->phy_addr_2;
630 + return <q_ethsw_mdio_pdi_regs->phy_addr_3;
632 + return <q_ethsw_mdio_pdi_regs->phy_addr_4;
634 + return <q_ethsw_mdio_pdi_regs->phy_addr_5;
640 +static void *ltq_eth_mii_cfg_reg(int num)
644 + return <q_ethsw_mii_pdi_regs->mii_cfg0;
646 + return <q_ethsw_mii_pdi_regs->mii_cfg1;
648 + return <q_ethsw_mii_pdi_regs->mii_cfg2;
650 + return <q_ethsw_mii_pdi_regs->mii_cfg3;
652 + return <q_ethsw_mii_pdi_regs->mii_cfg4;
654 + return <q_ethsw_mii_pdi_regs->mii_cfg5;
660 +static void ltq_eth_gmac_update(struct phy_device *phydev, int num)
662 + struct ltq_mdio_phy_addr_reg phy_addr_reg;
663 + struct ltq_mii_mii_cfg_reg mii_cfg_reg;
664 + void *phy_addr = ltq_eth_phy_addr_reg(num);
665 + void *mii_cfg = ltq_eth_mii_cfg_reg(num);
667 + phy_addr_reg.val = ltq_r32(phy_addr);
668 + mii_cfg_reg.val = ltq_r32(mii_cfg);
670 + phy_addr_reg.bits.addr = phydev->addr;
673 + phy_addr_reg.bits.lnkst = LTQ_MDIO_PHY_ADDR_LNKST_UP;
675 + phy_addr_reg.bits.lnkst = LTQ_MDIO_PHY_ADDR_LNKST_DOWN;
677 + switch (phydev->speed) {
679 + phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_G1;
680 + mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M125;
683 + phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_M100;
684 + switch (mii_cfg_reg.bits.miimode) {
685 + case LTQ_MII_MII_CFG_MIIMODE_RMIIM:
686 + case LTQ_MII_MII_CFG_MIIMODE_RMIIP:
687 + mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M50;
690 + mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M25;
695 + phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_M10;
696 + mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M2P5;
700 + if (phydev->duplex == DUPLEX_FULL)
701 + phy_addr_reg.bits.fdup = LTQ_MDIO_PHY_ADDR_FDUP_ENABLE;
703 + phy_addr_reg.bits.fdup = LTQ_MDIO_PHY_ADDR_FDUP_DISABLE;
705 + dbg_ltq_writel(phy_addr, phy_addr_reg.val);
706 + dbg_ltq_writel(mii_cfg, mii_cfg_reg.val);
711 +static void ltq_eth_port_config(struct ltq_vrx200_priv *priv,
712 + const struct ltq_eth_port_config *port)
714 + struct ltq_mii_mii_cfg_reg mii_cfg_reg;
715 + void *mii_cfg = ltq_eth_mii_cfg_reg(port->num);
716 + int setup_gpio = 0;
718 + mii_cfg_reg.val = ltq_r32(mii_cfg);
721 + switch (port->num) {
722 + case 0: /* xMII0 */
723 + case 1: /* xMII1 */
724 + switch (port->phy_if) {
725 + case PHY_INTERFACE_MODE_MII:
726 + if (port->flags & LTQ_ETH_PORT_PHY)
727 + /* MII MAC mode, connected to external PHY */
728 + mii_cfg_reg.bits.miimode =
729 + LTQ_MII_MII_CFG_MIIMODE_MIIM;
731 + /* MII PHY mode, connected to external MAC */
732 + mii_cfg_reg.bits.miimode =
733 + LTQ_MII_MII_CFG_MIIMODE_MIIP;
736 + case PHY_INTERFACE_MODE_RMII:
737 + if (port->flags & LTQ_ETH_PORT_PHY)
738 + /* RMII MAC mode, connected to external PHY */
739 + mii_cfg_reg.bits.miimode =
740 + LTQ_MII_MII_CFG_MIIMODE_RMIIM;
742 + /* RMII PHY mode, connected to external MAC */
743 + mii_cfg_reg.bits.miimode =
744 + LTQ_MII_MII_CFG_MIIMODE_RMIIP;
747 + case PHY_INTERFACE_MODE_RGMII:
748 + /* RGMII MAC mode, connected to external PHY */
749 + mii_cfg_reg.bits.miimode =
750 + LTQ_MII_MII_CFG_MIIMODE_RGMII;
757 + case 2: /* internal GPHY0 */
758 + case 3: /* internal GPHY0 */
759 + case 4: /* internal GPHY1 */
760 + switch (port->phy_if) {
761 + case PHY_INTERFACE_MODE_MII:
762 + case PHY_INTERFACE_MODE_GMII:
763 + /* MII MAC mode, connected to internal GPHY */
764 + mii_cfg_reg.bits.miimode =
765 + LTQ_MII_MII_CFG_MIIMODE_MIIM;
772 + case 5: /* internal GPHY1 or xMII2 */
773 + switch (port->phy_if) {
774 + case PHY_INTERFACE_MODE_MII:
775 + /* MII MAC mode, connected to internal GPHY */
776 + mii_cfg_reg.bits.miimode =
777 + LTQ_MII_MII_CFG_MIIMODE_MIIM;
780 + case PHY_INTERFACE_MODE_RGMII:
781 + /* RGMII MAC mode, connected to external PHY */
782 + mii_cfg_reg.bits.miimode =
783 + LTQ_MII_MII_CFG_MIIMODE_RGMII;
794 + /* Enable MII interface */
795 + mii_cfg_reg.bits.en = port->flags ? 1 : 0;
796 + dbg_ltq_writel(mii_cfg, mii_cfg_reg.val);
800 +static void ltq_eth_gmac_init(int num)
802 + struct ltq_mdio_phy_addr_reg phy_addr_reg;
803 + struct ltq_mii_mii_cfg_reg mii_cfg_reg;
804 + void *phy_addr = ltq_eth_phy_addr_reg(num);
805 + void *mii_cfg = ltq_eth_mii_cfg_reg(num);
806 + struct ltq_ethsw_mac_pdi_x_regs *mac_pdi_regs;
808 + mac_pdi_regs = <q_ethsw_mac_pdi_regs->mac[num];
810 + /* Reset PHY status to link down */
811 + phy_addr_reg.val = ltq_r32(phy_addr);
812 + phy_addr_reg.bits.addr = num;
813 + phy_addr_reg.bits.lnkst = LTQ_MDIO_PHY_ADDR_LNKST_DOWN;
814 + phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_M10;
815 + phy_addr_reg.bits.fdup = LTQ_MDIO_PHY_ADDR_FDUP_DISABLE;
816 + dbg_ltq_writel(phy_addr, phy_addr_reg.val);
818 + /* Reset and disable MII interface */
819 + mii_cfg_reg.val = ltq_r32(mii_cfg);
820 + mii_cfg_reg.bits.en = 0;
821 + mii_cfg_reg.bits.res = 1;
822 + mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M2P5;
823 + dbg_ltq_writel(mii_cfg, mii_cfg_reg.val);
826 + * Enable padding of short frames, enable frame checksum generation
827 + * in transmit direction
829 + dbg_ltq_writel(&mac_pdi_regs->ctrl_0, LTQ_ETHSW_MAC_CTRL0_PADEN |
830 + LTQ_ETHSW_MAC_CTRL0_FCS);
832 + /* Set inter packet gap size to 12 bytes */
833 + dbg_ltq_writel(&mac_pdi_regs->ctrl_1, 12);
836 + * Configure frame length checks:
837 + * - allow jumbo frames
838 + * - enable long length check
839 + * - enable short length without VLAN tags
841 + dbg_ltq_writel(&mac_pdi_regs->ctrl_2, LTQ_ETHSW_MAC_CTRL2_MLEN |
842 + LTQ_ETHSW_MAC_CTRL2_LCHKL |
843 + LTQ_ETHSW_MAC_CTRL2_LCHKS_UNTAG);
847 +static void ltq_eth_pmac_init(void)
849 + struct ltq_ethsw_mac_pdi_x_regs *mac_pdi_regs;
851 + mac_pdi_regs = <q_ethsw_mac_pdi_regs->mac[LTQ_ETHSW_PMAC];
854 + * Enable padding of short frames, enable frame checksum generation
855 + * in transmit direction
857 + dbg_ltq_writel(&mac_pdi_regs->ctrl_0, LTQ_ETHSW_MAC_CTRL0_PADEN |
858 + LTQ_ETHSW_MAC_CTRL0_FCS);
861 + * Configure frame length checks:
862 + * - allow jumbo frames
863 + * - enable long length check
864 + * - enable short length without VLAN tags
866 + dbg_ltq_writel(&mac_pdi_regs->ctrl_2, LTQ_ETHSW_MAC_CTRL2_MLEN |
867 + LTQ_ETHSW_MAC_CTRL2_LCHKL |
868 + LTQ_ETHSW_MAC_CTRL2_LCHKS_UNTAG);
871 + * Apply workaround for buffer congestion:
872 + * - shorten preambel to 1 byte
873 + * - set minimum inter packet gap size to 7 bytes
874 + * - enable receive buffer bypass mode
876 + dbg_ltq_writel(&mac_pdi_regs->ctrl_1, LTQ_ETHSW_MAC_CTRL1_SHORTPRE | 7);
877 + dbg_ltq_writel(&mac_pdi_regs->ctrl_6,
878 + (6 << LTQ_ETHSW_MAC_CTRL6_RBUF_DLY_WP_SHIFT) |
879 + LTQ_ETHSW_MAC_CTRL6_RXBUF_BYPASS);
881 + /* Set request assertion threshold to 8, IPG counter to 11 */
882 + dbg_ltq_writel(<q_ethsw_pmac_pdi_regs->rx_ipg, 0x8B);
885 + * Configure frame header control:
886 + * - enable reaction on pause frames (flow control)
887 + * - remove CRC for packets from PMAC to DMA
888 + * - add CRC for packets from DMA to PMAC
890 + dbg_ltq_writel(<q_ethsw_pmac_pdi_regs->hd_ctl, LTQ_ETHSW_PMAC_HD_CTL_FC |
891 + /*LTQ_ETHSW_PMAC_HD_CTL_RC | */LTQ_ETHSW_PMAC_HD_CTL_AC);
895 +ltq_vrx200_hw_init(struct net_device *dev)
897 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
901 + netdev_info(dev, "setting up dma\n");
902 + ltq_dma_init_port(DMA_PORT_ETOP);
904 + netdev_info(dev, "setting up pmu\n");
905 + clk_enable(priv->clk_ppe);
907 + /* Reset ethernet and switch subsystems */
908 + netdev_info(dev, "reset core\n");
909 + ltq_reset_once(BIT(8), 10);
911 + /* Enable switch macro */
912 + ltq_setbits(<q_ethsw_mdio_pdi_regs->glob_ctrl,
913 + LTQ_ETHSW_GLOB_CTRL_SE);
915 + /* Disable MDIO auto-polling for all ports */
916 + dbg_ltq_writel(<q_ethsw_mdio_pdi_regs->mdc_cfg_0, 0);
919 + * Enable and set MDIO management clock to 2.5 MHz. This is the
920 + * maximum clock for FE PHYs.
921 + * Formula for clock is:
924 + * x = ----------- - 1
927 + dbg_ltq_writel(<q_ethsw_mdio_pdi_regs->mdc_cfg_1,
928 + LTQ_ETHSW_MDC_CFG1_MCEN | 9);
930 + /* Init MAC connected to CPU */
931 + ltq_eth_pmac_init();
933 + /* Init MACs connected to external MII interfaces */
934 + for (i = 0; i < LTQ_ETHSW_MAX_GMAC; i++)
935 + ltq_eth_gmac_init(i);
937 + for (i = 0; i < MAX_DMA_CHAN && !err; i++) {
938 + int irq = LTQ_DMA_ETOP + i;
939 + struct ltq_vrx200_chan *ch = &priv->ch[i];
941 + ch->idx = ch->dma.nr = i;
944 + ltq_dma_alloc_tx(&ch->dma);
945 + err = request_irq(irq, ltq_vrx200_dma_irq, IRQF_DISABLED,
946 + "vrx200_tx", priv);
947 + } else if (IS_RX(i)) {
948 + ltq_dma_alloc_rx(&ch->dma);
949 + for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
951 + if (ltq_vrx200_alloc_skb(ch))
954 + err = request_irq(irq, ltq_vrx200_dma_irq, IRQF_DISABLED,
955 + "vrx200_rx", priv);
960 + for (i = 0; i < board_config.num_ports; i++)
961 + ltq_eth_port_config(priv, &board_config.ports[i]);
966 +ltq_vrx200_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
968 + strcpy(info->driver, "Lantiq ETOP");
969 + strcpy(info->bus_info, "internal");
970 + strcpy(info->version, DRV_VERSION);
974 +ltq_vrx200_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
976 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
978 + return phy_ethtool_gset(priv->phydev, cmd);
982 +ltq_vrx200_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
984 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
986 + return phy_ethtool_sset(priv->phydev, cmd);
990 +ltq_vrx200_nway_reset(struct net_device *dev)
992 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
994 + return phy_start_aneg(priv->phydev);
997 +static const struct ethtool_ops ltq_vrx200_ethtool_ops = {
998 + .get_drvinfo = ltq_vrx200_get_drvinfo,
999 + .get_settings = ltq_vrx200_get_settings,
1000 + .set_settings = ltq_vrx200_set_settings,
1001 + .nway_reset = ltq_vrx200_nway_reset,
1004 +static inline int ltq_mdio_poll(struct mii_bus *bus)
1006 + struct ltq_mdio_access acc;
1007 + unsigned cnt = 10000;
1009 + while (likely(cnt--)) {
1010 + acc.val = ltq_r32(<q_ethsw_mdio_pdi_regs->mdio_ctrl);
1011 + if (!acc.bits.mbusy)
1019 +ltq_vrx200_mdio_wr(struct mii_bus *bus, int addr, int regnum, u16 val)
1021 + struct ltq_mdio_access acc;
1025 + acc.bits.mbusy = LTQ_MDIO_MBUSY_BUSY;
1026 + acc.bits.op = LTQ_MDIO_OP_WRITE;
1027 + acc.bits.phyad = addr;
1028 + acc.bits.regad = regnum;
1030 + ret = ltq_mdio_poll(bus);
1034 + dbg_ltq_writel(<q_ethsw_mdio_pdi_regs->mdio_write, val);
1035 + dbg_ltq_writel(<q_ethsw_mdio_pdi_regs->mdio_ctrl, acc.val);
1041 +ltq_vrx200_mdio_rd(struct mii_bus *bus, int addr, int regnum)
1043 + struct ltq_mdio_access acc;
1047 + acc.bits.mbusy = LTQ_MDIO_MBUSY_BUSY;
1048 + acc.bits.op = LTQ_MDIO_OP_READ;
1049 + acc.bits.phyad = addr;
1050 + acc.bits.regad = regnum;
1052 + ret = ltq_mdio_poll(bus);
1056 + dbg_ltq_writel(<q_ethsw_mdio_pdi_regs->mdio_ctrl, acc.val);
1058 + ret = ltq_mdio_poll(bus);
1062 + ret = ltq_r32(<q_ethsw_mdio_pdi_regs->mdio_read);
1070 +ltq_vrx200_mdio_link(struct net_device *dev)
1072 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
1073 + ltq_eth_gmac_update(priv->phydev, 0);
1077 +ltq_vrx200_mdio_probe(struct net_device *dev)
1079 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
1080 + struct phy_device *phydev = NULL;
1083 + phydev = priv->mii_bus->phy_map[0];
1086 + netdev_err(dev, "no PHY found\n");
1090 + phydev = phy_connect(dev, dev_name(&phydev->dev), <q_vrx200_mdio_link,
1093 + if (IS_ERR(phydev)) {
1094 + netdev_err(dev, "Could not attach to PHY\n");
1095 + return PTR_ERR(phydev);
1098 + phydev->supported &= (SUPPORTED_10baseT_Half
1099 + | SUPPORTED_10baseT_Full
1100 + | SUPPORTED_100baseT_Half
1101 + | SUPPORTED_100baseT_Full
1102 + | SUPPORTED_1000baseT_Half
1103 + | SUPPORTED_1000baseT_Full
1104 + | SUPPORTED_Autoneg
1107 + phydev->advertising = phydev->supported;
1108 + priv->phydev = phydev;
1110 + pr_info("%s: attached PHY [%s] (phy_addr=%s, irq=%d)\n",
1111 + dev->name, phydev->drv->name,
1112 + dev_name(&phydev->dev), phydev->irq);
1114 + val = ltq_vrx200_mdio_rd(priv->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000);
1115 + val |= ADVERTIZE_MPD;
1116 + ltq_vrx200_mdio_wr(priv->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000, val);
1117 + ltq_vrx200_mdio_wr(priv->mii_bus, 0, 0, 0x1040);
1119 + phy_start_aneg(phydev);
1125 +ltq_vrx200_mdio_init(struct net_device *dev)
1127 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
1131 + priv->mii_bus = mdiobus_alloc();
1132 + if (!priv->mii_bus) {
1133 + netdev_err(dev, "failed to allocate mii bus\n");
1138 + priv->mii_bus->priv = dev;
1139 + priv->mii_bus->read = ltq_vrx200_mdio_rd;
1140 + priv->mii_bus->write = ltq_vrx200_mdio_wr;
1141 + priv->mii_bus->name = "ltq_mii";
1142 + snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
1143 + priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
1144 + if (!priv->mii_bus->irq) {
1146 + goto err_out_free_mdiobus;
1149 + for (i = 0; i < PHY_MAX_ADDR; ++i)
1150 + priv->mii_bus->irq[i] = PHY_POLL;
1152 + if (mdiobus_register(priv->mii_bus)) {
1154 + goto err_out_free_mdio_irq;
1157 + if (ltq_vrx200_mdio_probe(dev)) {
1159 + goto err_out_unregister_bus;
1163 +err_out_unregister_bus:
1164 + mdiobus_unregister(priv->mii_bus);
1165 +err_out_free_mdio_irq:
1166 + kfree(priv->mii_bus->irq);
1167 +err_out_free_mdiobus:
1168 + mdiobus_free(priv->mii_bus);
1174 +ltq_vrx200_mdio_cleanup(struct net_device *dev)
1176 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
1178 + phy_disconnect(priv->phydev);
1179 + mdiobus_unregister(priv->mii_bus);
1180 + kfree(priv->mii_bus->irq);
1181 + mdiobus_free(priv->mii_bus);
1184 +void phy_dump(struct net_device *dev)
1186 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
1188 + for (i = 0; i < 0x1F; i++) {
1189 + unsigned int val = ltq_vrx200_mdio_rd(priv->mii_bus, 0, i);
1190 + printk("%d %4X\n", i, val);
1195 +ltq_vrx200_open(struct net_device *dev)
1197 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
1199 + unsigned long flags;
1201 + for (i = 0; i < MAX_DMA_CHAN; i++) {
1202 + struct ltq_vrx200_chan *ch = &priv->ch[i];
1204 + if (!IS_TX(i) && (!IS_RX(i)))
1206 + napi_enable(&ch->napi);
1207 + spin_lock_irqsave(&priv->lock, flags);
1208 + ltq_dma_open(&ch->dma);
1209 + spin_unlock_irqrestore(&priv->lock, flags);
1211 + if (priv->phydev) {
1212 + phy_start(priv->phydev);
1215 + netif_tx_start_all_queues(dev);
1220 +ltq_vrx200_stop(struct net_device *dev)
1222 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
1224 + unsigned long flags;
1226 + netif_tx_stop_all_queues(dev);
1228 + phy_stop(priv->phydev);
1229 + for (i = 0; i < MAX_DMA_CHAN; i++) {
1230 + struct ltq_vrx200_chan *ch = &priv->ch[i];
1232 + if (!IS_RX(i) && !IS_TX(i))
1234 + napi_disable(&ch->napi);
1235 + spin_lock_irqsave(&priv->lock, flags);
1236 + ltq_dma_close(&ch->dma);
1237 + spin_unlock_irqrestore(&priv->lock, flags);
1243 +ltq_vrx200_tx(struct sk_buff *skb, struct net_device *dev)
1245 + int queue = skb_get_queue_mapping(skb);
1246 + struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
1247 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
1248 + struct ltq_vrx200_chan *ch = &priv->ch[(queue << 1) | 1];
1249 + struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
1250 + unsigned long flags;
1254 + len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
1256 + if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
1257 + netdev_err(dev, "tx ring full\n");
1258 + netif_tx_stop_queue(txq);
1259 + return NETDEV_TX_BUSY;
1262 + /* dma needs to start on a 16 byte aligned address */
1263 + byte_offset = CPHYSADDR(skb->data) % 16;
1264 + ch->skb[ch->dma.desc] = skb;
1266 + dev->trans_start = jiffies;
1268 + spin_lock_irqsave(&priv->lock, flags);
1269 + desc->addr = ((unsigned int) dma_map_single(NULL, skb->data, len,
1270 + DMA_TO_DEVICE)) - byte_offset;
1272 + desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
1273 + LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
1275 + ch->dma.desc %= LTQ_DESC_NUM;
1276 + spin_unlock_irqrestore(&priv->lock, flags);
1278 + if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
1279 + netif_tx_stop_queue(txq);
1281 + return NETDEV_TX_OK;
1285 +ltq_vrx200_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1287 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
1289 + /* TODO: mii-toll reports "No MII transceiver present!." ?!*/
1290 + return phy_mii_ioctl(priv->phydev, rq, cmd);
1294 +ltq_vrx200_select_queue(struct net_device *dev, struct sk_buff *skb)
1296 + /* we are currently only using the first queue */
1301 +ltq_vrx200_init(struct net_device *dev)
1303 + struct ltq_vrx200_priv *priv = netdev_priv(dev);
1304 + struct sockaddr mac;
1308 + dev->watchdog_timeo = 10 * HZ;
1310 + err = ltq_vrx200_hw_init(dev);
1314 + memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr));
1315 + if (!is_valid_ether_addr(mac.sa_data)) {
1316 + pr_warn("vrx200: invalid MAC, using random\n");
1317 + random_ether_addr(mac.sa_data);
1319 + eth_mac_addr(dev, &mac);
1321 + if (!ltq_vrx200_mdio_init(dev))
1322 + dev->ethtool_ops = <q_vrx200_ethtool_ops;
1324 + pr_warn("vrx200: mdio probe failed\n");;
1328 + ltq_vrx200_hw_exit(dev);
1333 +ltq_vrx200_tx_timeout(struct net_device *dev)
1337 + ltq_vrx200_hw_exit(dev);
1338 + err = ltq_vrx200_hw_init(dev);
1341 + dev->trans_start = jiffies;
1342 + netif_wake_queue(dev);
1346 + ltq_vrx200_hw_exit(dev);
1347 + netdev_err(dev, "failed to restart vrx200 after TX timeout\n");
1350 +static const struct net_device_ops ltq_eth_netdev_ops = {
1351 + .ndo_open = ltq_vrx200_open,
1352 + .ndo_stop = ltq_vrx200_stop,
1353 + .ndo_start_xmit = ltq_vrx200_tx,
1354 + .ndo_change_mtu = eth_change_mtu,
1355 + .ndo_do_ioctl = ltq_vrx200_ioctl,
1356 + .ndo_set_mac_address = eth_mac_addr,
1357 + .ndo_validate_addr = eth_validate_addr,
1358 + .ndo_select_queue = ltq_vrx200_select_queue,
1359 + .ndo_init = ltq_vrx200_init,
1360 + .ndo_tx_timeout = ltq_vrx200_tx_timeout,
1363 +static int __devinit
1364 +ltq_vrx200_probe(struct platform_device *pdev)
1366 + struct net_device *dev;
1367 + struct ltq_vrx200_priv *priv;
1368 + struct resource *res;
1372 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1374 + dev_err(&pdev->dev, "failed to get vrx200 resource\n");
1379 + res = devm_request_mem_region(&pdev->dev, res->start,
1380 + resource_size(res), dev_name(&pdev->dev));
1382 + dev_err(&pdev->dev, "failed to request vrx200 resource\n");
1387 + ltq_vrx200_membase = devm_ioremap_nocache(&pdev->dev,
1388 + res->start, resource_size(res));
1389 + if (!ltq_vrx200_membase) {
1390 + dev_err(&pdev->dev, "failed to remap vrx200 engine %d\n",
1396 + if (ltq_gpio_request(&pdev->dev, 42, 2, 1, "MDIO") ||
1397 + ltq_gpio_request(&pdev->dev, 43, 2, 1, "MDC")) {
1398 + dev_err(&pdev->dev, "failed to request MDIO gpios\n");
1403 + dev = alloc_etherdev_mq(sizeof(struct ltq_vrx200_priv), 4);
1404 + strcpy(dev->name, "eth%d");
1405 + dev->netdev_ops = <q_eth_netdev_ops;
1406 + priv = netdev_priv(dev);
1408 + priv->pldata = dev_get_platdata(&pdev->dev);
1409 + priv->netdev = dev;
1411 + priv->clk_ppe = clk_get(&pdev->dev, NULL);
1412 + if (IS_ERR(priv->clk_ppe))
1413 + return PTR_ERR(priv->clk_ppe);
1415 + spin_lock_init(&priv->lock);
1417 + for (i = 0; i < MAX_DMA_CHAN; i++) {
1419 + netif_napi_add(dev, &priv->ch[i].napi,
1420 + ltq_vrx200_poll_tx, 8);
1421 + else if (IS_RX(i))
1422 + netif_napi_add(dev, &priv->ch[i].napi,
1423 + ltq_vrx200_poll_rx, 32);
1424 + priv->ch[i].netdev = dev;
1427 + err = register_netdev(dev);
1431 + platform_set_drvdata(pdev, dev);
1440 +static int __devexit
1441 +ltq_vrx200_remove(struct platform_device *pdev)
1443 + struct net_device *dev = platform_get_drvdata(pdev);
1446 + netif_tx_stop_all_queues(dev);
1447 + ltq_vrx200_hw_exit(dev);
1448 + ltq_vrx200_mdio_cleanup(dev);
1449 + unregister_netdev(dev);
1454 +static struct platform_driver ltq_mii_driver = {
1455 + .probe = ltq_vrx200_probe,
1456 + .remove = __devexit_p(ltq_vrx200_remove),
1458 + .name = "ltq_vrx200",
1459 + .owner = THIS_MODULE,
1463 +module_platform_driver(ltq_mii_driver);
1465 +MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
1466 +MODULE_DESCRIPTION("Lantiq SoC ETOP");
1467 +MODULE_LICENSE("GPL");