2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
16 * Copyright (C) 2005 Wu Qi Ming <Qi-Ming.Wu@infineon.com>
17 * Copyright (C) 2008 John Crispin <blogic@openwrt.org>
20 #include <linux/kernel.h>
21 #include <linux/slab.h>
22 #include <linux/errno.h>
23 #include <linux/types.h>
24 #include <linux/interrupt.h>
25 #include <linux/uaccess.h>
27 #include <linux/netdevice.h>
28 #include <linux/etherdevice.h>
30 #include <linux/tcp.h>
31 #include <linux/skbuff.h>
33 #include <linux/platform_device.h>
34 #include <linux/ethtool.h>
35 #include <linux/init.h>
36 #include <linux/delay.h>
38 #include <asm/checksum.h>
41 #include <ifxmips_dma.h>
42 #include <ifxmips_pmu.h>
44 struct ifxmips_mii_priv
{
45 struct net_device_stats stats
;
46 struct dma_device_info
*dma_device
;
50 static struct net_device
*ifxmips_mii0_dev
;
51 static unsigned char mac_addr
[MAX_ADDR_LEN
];
53 void ifxmips_write_mdio(u32 phy_addr
, u32 phy_reg
, u16 phy_data
)
55 u32 val
= MDIO_ACC_REQUEST
|
56 ((phy_addr
& MDIO_ACC_ADDR_MASK
) << MDIO_ACC_ADDR_OFFSET
) |
57 ((phy_reg
& MDIO_ACC_REG_MASK
) << MDIO_ACC_REG_OFFSET
) |
60 while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC
) & MDIO_ACC_REQUEST
)
62 ifxmips_w32(val
, IFXMIPS_PPE32_MDIO_ACC
);
64 EXPORT_SYMBOL(ifxmips_write_mdio
);
66 unsigned short ifxmips_read_mdio(u32 phy_addr
, u32 phy_reg
)
68 u32 val
= MDIO_ACC_REQUEST
| MDIO_ACC_READ
|
69 ((phy_addr
& MDIO_ACC_ADDR_MASK
) << MDIO_ACC_ADDR_OFFSET
) |
70 ((phy_reg
& MDIO_ACC_REG_MASK
) << MDIO_ACC_REG_OFFSET
);
72 while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC
) & MDIO_ACC_REQUEST
)
74 ifxmips_w32(val
, IFXMIPS_PPE32_MDIO_ACC
);
75 while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC
) & MDIO_ACC_REQUEST
)
77 val
= ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC
) & MDIO_ACC_VAL_MASK
;
80 EXPORT_SYMBOL(ifxmips_read_mdio
);
82 int ifxmips_ifxmips_mii_open(struct net_device
*dev
)
84 struct ifxmips_mii_priv
*priv
= (struct ifxmips_mii_priv
*)netdev_priv(dev
);
85 struct dma_device_info
*dma_dev
= priv
->dma_device
;
88 for (i
= 0; i
< dma_dev
->max_rx_chan_num
; i
++) {
89 if ((dma_dev
->rx_chan
[i
])->control
== IFXMIPS_DMA_CH_ON
)
90 (dma_dev
->rx_chan
[i
])->open(dma_dev
->rx_chan
[i
]);
92 netif_start_queue(dev
);
96 int ifxmips_mii_release(struct net_device
*dev
)
98 struct ifxmips_mii_priv
*priv
= (struct ifxmips_mii_priv
*)netdev_priv(dev
);
99 struct dma_device_info
*dma_dev
= priv
->dma_device
;
102 for (i
= 0; i
< dma_dev
->max_rx_chan_num
; i
++)
103 dma_dev
->rx_chan
[i
]->close(dma_dev
->rx_chan
[i
]);
104 netif_stop_queue(dev
);
108 int ifxmips_mii_hw_receive(struct net_device
*dev
, struct dma_device_info
*dma_dev
)
110 struct ifxmips_mii_priv
*priv
= (struct ifxmips_mii_priv
*)netdev_priv(dev
);
111 unsigned char *buf
= NULL
;
112 struct sk_buff
*skb
= NULL
;
115 len
= dma_device_read(dma_dev
, &buf
, (void **)&skb
);
117 if (len
>= ETHERNET_PACKET_DMA_BUFFER_SIZE
) {
118 printk(KERN_INFO
"ifxmips_mii0: packet too large %d\n", len
);
119 goto ifxmips_mii_hw_receive_err_exit
;
125 printk(KERN_INFO
"ifxmips_mii0: cannot restore pointer\n");
126 goto ifxmips_mii_hw_receive_err_exit
;
129 if (len
> (skb
->end
- skb
->tail
)) {
130 printk(KERN_INFO
"ifxmips_mii0: BUG, len:%d end:%p tail:%p\n",
131 (len
+4), skb
->end
, skb
->tail
);
132 goto ifxmips_mii_hw_receive_err_exit
;
137 skb
->protocol
= eth_type_trans(skb
, dev
);
140 priv
->stats
.rx_packets
++;
141 priv
->stats
.rx_bytes
+= len
;
144 ifxmips_mii_hw_receive_err_exit
:
147 dev_kfree_skb_any(skb
);
148 priv
->stats
.rx_errors
++;
149 priv
->stats
.rx_dropped
++;
156 int ifxmips_mii_hw_tx(char *buf
, int len
, struct net_device
*dev
)
159 struct ifxmips_mii_priv
*priv
= netdev_priv(dev
);
160 struct dma_device_info
*dma_dev
= priv
->dma_device
;
161 ret
= dma_device_write(dma_dev
, buf
, len
, priv
->skb
);
165 int ifxmips_mii_tx(struct sk_buff
*skb
, struct net_device
*dev
)
169 struct ifxmips_mii_priv
*priv
= netdev_priv(dev
);
170 struct dma_device_info
*dma_dev
= priv
->dma_device
;
172 len
= skb
->len
< ETH_ZLEN
? ETH_ZLEN
: skb
->len
;
175 dev
->trans_start
= jiffies
;
176 /* TODO: we got more than 1 dma channel,
177 so we should do something intelligent here to select one */
178 dma_dev
->current_tx_chan
= 0;
182 if (ifxmips_mii_hw_tx(data
, len
, dev
) != len
) {
183 dev_kfree_skb_any(skb
);
184 priv
->stats
.tx_errors
++;
185 priv
->stats
.tx_dropped
++;
187 priv
->stats
.tx_packets
++;
188 priv
->stats
.tx_bytes
+= len
;
194 void ifxmips_mii_tx_timeout(struct net_device
*dev
)
197 struct ifxmips_mii_priv
*priv
= (struct ifxmips_mii_priv
*)netdev_priv(dev
);
199 priv
->stats
.tx_errors
++;
200 for (i
= 0; i
< priv
->dma_device
->max_tx_chan_num
; i
++)
201 priv
->dma_device
->tx_chan
[i
]->disable_irq(priv
->dma_device
->tx_chan
[i
]);
202 netif_wake_queue(dev
);
206 int dma_intr_handler(struct dma_device_info
*dma_dev
, int status
)
212 ifxmips_mii_hw_receive(ifxmips_mii0_dev
, dma_dev
);
215 case TX_BUF_FULL_INT
:
216 printk(KERN_INFO
"ifxmips_mii0: tx buffer full\n");
217 netif_stop_queue(ifxmips_mii0_dev
);
218 for (i
= 0; i
< dma_dev
->max_tx_chan_num
; i
++) {
219 if ((dma_dev
->tx_chan
[i
])->control
== IFXMIPS_DMA_CH_ON
)
220 dma_dev
->tx_chan
[i
]->enable_irq(dma_dev
->tx_chan
[i
]);
224 case TRANSMIT_CPT_INT
:
225 for (i
= 0; i
< dma_dev
->max_tx_chan_num
; i
++)
226 dma_dev
->tx_chan
[i
]->disable_irq(dma_dev
->tx_chan
[i
]);
228 netif_wake_queue(ifxmips_mii0_dev
);
235 unsigned char *ifxmips_etop_dma_buffer_alloc(int len
, int *byte_offset
, void **opt
)
237 unsigned char *buffer
= NULL
;
238 struct sk_buff
*skb
= NULL
;
240 skb
= dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE
);
244 buffer
= (unsigned char *)(skb
->data
);
246 *(int *)opt
= (int)skb
;
252 void ifxmips_etop_dma_buffer_free(unsigned char *dataptr
, void *opt
)
254 struct sk_buff
*skb
= NULL
;
259 skb
= (struct sk_buff
*)opt
;
260 dev_kfree_skb_any(skb
);
264 static struct net_device_stats
*ifxmips_get_stats(struct net_device
*dev
)
266 return &((struct ifxmips_mii_priv
*)netdev_priv(dev
))->stats
;
269 static int ifxmips_mii_dev_init(struct net_device
*dev
)
272 struct ifxmips_mii_priv
*priv
= (struct ifxmips_mii_priv
*)netdev_priv(dev
);
274 printk(KERN_INFO
"ifxmips_mii0: %s is up\n", dev
->name
);
275 dev
->open
= ifxmips_ifxmips_mii_open
;
276 dev
->stop
= ifxmips_mii_release
;
277 dev
->hard_start_xmit
= ifxmips_mii_tx
;
278 dev
->get_stats
= ifxmips_get_stats
;
279 dev
->tx_timeout
= ifxmips_mii_tx_timeout
;
280 dev
->watchdog_timeo
= 10 * HZ
;
281 memset(priv
, 0, sizeof(struct ifxmips_mii_priv
));
282 priv
->dma_device
= dma_device_reserve("PPE");
283 if (!priv
->dma_device
) {
287 priv
->dma_device
->buffer_alloc
= &ifxmips_etop_dma_buffer_alloc
;
288 priv
->dma_device
->buffer_free
= &ifxmips_etop_dma_buffer_free
;
289 priv
->dma_device
->intr_handler
= &dma_intr_handler
;
290 priv
->dma_device
->max_rx_chan_num
= 4;
292 for (i
= 0; i
< priv
->dma_device
->max_rx_chan_num
; i
++) {
293 priv
->dma_device
->rx_chan
[i
]->packet_size
= ETHERNET_PACKET_DMA_BUFFER_SIZE
;
294 priv
->dma_device
->rx_chan
[i
]->control
= IFXMIPS_DMA_CH_ON
;
297 for (i
= 0; i
< priv
->dma_device
->max_tx_chan_num
; i
++)
299 priv
->dma_device
->tx_chan
[i
]->control
= IFXMIPS_DMA_CH_ON
;
301 priv
->dma_device
->tx_chan
[i
]->control
= IFXMIPS_DMA_CH_OFF
;
303 dma_device_register(priv
->dma_device
);
305 printk(KERN_INFO
"ifxmips_mii0: using mac=");
306 for (i
= 0; i
< 6; i
++) {
307 dev
->dev_addr
[i
] = mac_addr
[i
];
308 printk("%02X%c", dev
->dev_addr
[i
], (i
== 5) ? ('\n') : (':'));
313 static void ifxmips_mii_chip_init(int mode
)
315 ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_DMA
);
316 ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_PPE
);
318 if (mode
== REV_MII_MODE
)
319 ifxmips_w32_mask(PPE32_MII_MASK
, PPE32_MII_REVERSE
, IFXMIPS_PPE32_CFG
);
320 else if (mode
== MII_MODE
)
321 ifxmips_w32_mask(PPE32_MII_MASK
, PPE32_MII_NORMAL
, IFXMIPS_PPE32_CFG
);
322 ifxmips_w32(PPE32_PLEN_UNDER
| PPE32_PLEN_OVER
, IFXMIPS_PPE32_IG_PLEN_CTRL
);
323 ifxmips_w32(PPE32_CGEN
, IFXMIPS_PPE32_ENET_MAC_CFG
);
327 static int ifxmips_mii_probe(struct platform_device
*dev
)
330 unsigned char *mac
= (unsigned char *)dev
->dev
.platform_data
;
331 ifxmips_mii0_dev
= alloc_etherdev(sizeof(struct ifxmips_mii_priv
));
332 ifxmips_mii0_dev
->init
= ifxmips_mii_dev_init
;
333 memcpy(mac_addr
, mac
, 6);
334 strcpy(ifxmips_mii0_dev
->name
, "eth%d");
335 ifxmips_mii_chip_init(REV_MII_MODE
);
336 result
= register_netdev(ifxmips_mii0_dev
);
338 printk(KERN_INFO
"ifxmips_mii0: error %i registering device \"%s\"\n", result
, ifxmips_mii0_dev
->name
);
342 printk(KERN_INFO
"ifxmips_mii0: driver loaded!\n");
348 static int ifxmips_mii_remove(struct platform_device
*dev
)
350 struct ifxmips_mii_priv
*priv
= (struct ifxmips_mii_priv
*)netdev_priv(ifxmips_mii0_dev
);
352 printk(KERN_INFO
"ifxmips_mii0: ifxmips_mii0 cleanup\n");
354 dma_device_unregister(priv
->dma_device
);
355 dma_device_release(priv
->dma_device
);
356 kfree(priv
->dma_device
);
357 unregister_netdev(ifxmips_mii0_dev
);
361 static struct platform_driver ifxmips_mii_driver
= {
362 .probe
= ifxmips_mii_probe
,
363 .remove
= ifxmips_mii_remove
,
365 .name
= "ifxmips_mii0",
366 .owner
= THIS_MODULE
,
370 int __init
ifxmips_mii_init(void)
372 int ret
= platform_driver_register(&ifxmips_mii_driver
);
374 printk(KERN_INFO
"ifxmips_mii0: Error registering platfom driver!");
378 static void __exit
ifxmips_mii_cleanup(void)
380 platform_driver_unregister(&ifxmips_mii_driver
);
383 module_init(ifxmips_mii_init
);
384 module_exit(ifxmips_mii_cleanup
);
386 MODULE_LICENSE("GPL");
387 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
388 MODULE_DESCRIPTION("ethernet driver for IFXMIPS boards");