blob: fc12ac0d9f2e55012d202a44acfca9e8d432c6bd [file] [log] [blame]
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001/*
Richard Röjforsa1aa8822010-04-21 16:33:29 -07002 * ks8842.c timberdale KS8842 ethernet driver
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00003 * Copyright (c) 2009 Intel Corporation
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19/* Supports:
20 * The Micrel KS8842 behind the timberdale FPGA
David J. Choi28bd6202010-07-13 10:09:19 -070021 * The genuine Micrel KS8841/42 device with ISA 16/32bit bus interface
Richard Ršöjforsb07878e2009-06-04 03:35:55 +000022 */
23
Joe Perches0dc7d2b2010-02-27 14:43:51 +000024#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25
Richard Ršöjforsb07878e2009-06-04 03:35:55 +000026#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/platform_device.h>
29#include <linux/netdevice.h>
30#include <linux/etherdevice.h>
31#include <linux/ethtool.h>
Richard Röjforsa1aa8822010-04-21 16:33:29 -070032#include <linux/ks8842.h>
Richard Röjfors94fe8c62010-07-27 12:57:01 +000033#include <linux/dmaengine.h>
34#include <linux/dma-mapping.h>
35#include <linux/scatterlist.h>
Richard Ršöjforsb07878e2009-06-04 03:35:55 +000036
37#define DRV_NAME "ks8842"
38
39/* Timberdale specific Registers */
Richard Röjforsdb5824d2010-07-25 22:51:05 +000040#define REG_TIMB_RST 0x1c
41#define REG_TIMB_FIFO 0x20
42#define REG_TIMB_ISR 0x24
43#define REG_TIMB_IER 0x28
44#define REG_TIMB_IAR 0x2C
45#define REQ_TIMB_DMA_RESUME 0x30
Richard Ršöjforsb07878e2009-06-04 03:35:55 +000046
47/* KS8842 registers */
48
49#define REG_SELECT_BANK 0x0e
50
51/* bank 0 registers */
52#define REG_QRFCR 0x04
53
54/* bank 2 registers */
55#define REG_MARL 0x00
56#define REG_MARM 0x02
57#define REG_MARH 0x04
58
59/* bank 3 registers */
60#define REG_GRR 0x06
61
62/* bank 16 registers */
63#define REG_TXCR 0x00
64#define REG_TXSR 0x02
65#define REG_RXCR 0x04
66#define REG_TXMIR 0x08
67#define REG_RXMIR 0x0A
68
69/* bank 17 registers */
70#define REG_TXQCR 0x00
71#define REG_RXQCR 0x02
72#define REG_TXFDPR 0x04
73#define REG_RXFDPR 0x06
74#define REG_QMU_DATA_LO 0x08
75#define REG_QMU_DATA_HI 0x0A
76
77/* bank 18 registers */
78#define REG_IER 0x00
79#define IRQ_LINK_CHANGE 0x8000
80#define IRQ_TX 0x4000
81#define IRQ_RX 0x2000
82#define IRQ_RX_OVERRUN 0x0800
83#define IRQ_TX_STOPPED 0x0200
84#define IRQ_RX_STOPPED 0x0100
85#define IRQ_RX_ERROR 0x0080
86#define ENABLED_IRQS (IRQ_LINK_CHANGE | IRQ_TX | IRQ_RX | IRQ_RX_STOPPED | \
87 IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR)
Richard Röjfors94fe8c62010-07-27 12:57:01 +000088/* When running via timberdale in DMA mode, the RX interrupt should be
89 enabled in the KS8842, but not in the FPGA IP, since the IP handles
90 RX DMA internally.
91 TX interrupts are not needed it is handled by the FPGA the driver is
92 notified via DMA callbacks.
93*/
94#define ENABLED_IRQS_DMA_IP (IRQ_LINK_CHANGE | IRQ_RX_STOPPED | \
95 IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR)
96#define ENABLED_IRQS_DMA (ENABLED_IRQS_DMA_IP | IRQ_RX)
Richard Ršöjforsb07878e2009-06-04 03:35:55 +000097#define REG_ISR 0x02
98#define REG_RXSR 0x04
99#define RXSR_VALID 0x8000
100#define RXSR_BROADCAST 0x80
101#define RXSR_MULTICAST 0x40
102#define RXSR_UNICAST 0x20
103#define RXSR_FRAMETYPE 0x08
104#define RXSR_TOO_LONG 0x04
105#define RXSR_RUNT 0x02
106#define RXSR_CRC_ERROR 0x01
107#define RXSR_ERROR (RXSR_TOO_LONG | RXSR_RUNT | RXSR_CRC_ERROR)
108
109/* bank 32 registers */
110#define REG_SW_ID_AND_ENABLE 0x00
111#define REG_SGCR1 0x02
112#define REG_SGCR2 0x04
113#define REG_SGCR3 0x06
114
115/* bank 39 registers */
116#define REG_MACAR1 0x00
117#define REG_MACAR2 0x02
118#define REG_MACAR3 0x04
119
120/* bank 45 registers */
121#define REG_P1MBCR 0x00
122#define REG_P1MBSR 0x02
123
124/* bank 46 registers */
125#define REG_P2MBCR 0x00
126#define REG_P2MBSR 0x02
127
128/* bank 48 registers */
129#define REG_P1CR2 0x02
130
131/* bank 49 registers */
132#define REG_P1CR4 0x02
133#define REG_P1SR 0x04
134
David J. Choi28bd6202010-07-13 10:09:19 -0700135/* flags passed by platform_device for configuration */
136#define MICREL_KS884X 0x01 /* 0=Timeberdale(FPGA), 1=Micrel */
137#define KS884X_16BIT 0x02 /* 1=16bit, 0=32bit */
138
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000139#define DMA_BUFFER_SIZE 2048
140
141struct ks8842_tx_dma_ctl {
142 struct dma_chan *chan;
143 struct dma_async_tx_descriptor *adesc;
144 void *buf;
145 struct scatterlist sg;
146 int channel;
147};
148
149struct ks8842_rx_dma_ctl {
150 struct dma_chan *chan;
151 struct dma_async_tx_descriptor *adesc;
152 struct sk_buff *skb;
153 struct scatterlist sg;
154 struct tasklet_struct tasklet;
155 int channel;
156};
157
158#define KS8842_USE_DMA(adapter) (((adapter)->dma_tx.channel != -1) && \
159 ((adapter)->dma_rx.channel != -1))
160
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000161struct ks8842_adapter {
162 void __iomem *hw_addr;
163 int irq;
David J. Choi28bd6202010-07-13 10:09:19 -0700164 unsigned long conf_flags; /* copy of platform_device config */
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000165 struct tasklet_struct tasklet;
166 spinlock_t lock; /* spinlock to be interrupt safe */
Richard Röjforscc88e452010-07-08 23:36:30 -0700167 struct work_struct timeout_work;
168 struct net_device *netdev;
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000169 struct device *dev;
170 struct ks8842_tx_dma_ctl dma_tx;
171 struct ks8842_rx_dma_ctl dma_rx;
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000172};
173
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000174static void ks8842_dma_rx_cb(void *data);
175static void ks8842_dma_tx_cb(void *data);
176
177static inline void ks8842_resume_dma(struct ks8842_adapter *adapter)
178{
179 iowrite32(1, adapter->hw_addr + REQ_TIMB_DMA_RESUME);
180}
181
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000182static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank)
183{
184 iowrite16(bank, adapter->hw_addr + REG_SELECT_BANK);
185}
186
187static inline void ks8842_write8(struct ks8842_adapter *adapter, u16 bank,
188 u8 value, int offset)
189{
190 ks8842_select_bank(adapter, bank);
191 iowrite8(value, adapter->hw_addr + offset);
192}
193
194static inline void ks8842_write16(struct ks8842_adapter *adapter, u16 bank,
195 u16 value, int offset)
196{
197 ks8842_select_bank(adapter, bank);
198 iowrite16(value, adapter->hw_addr + offset);
199}
200
201static inline void ks8842_enable_bits(struct ks8842_adapter *adapter, u16 bank,
202 u16 bits, int offset)
203{
204 u16 reg;
205 ks8842_select_bank(adapter, bank);
206 reg = ioread16(adapter->hw_addr + offset);
207 reg |= bits;
208 iowrite16(reg, adapter->hw_addr + offset);
209}
210
211static inline void ks8842_clear_bits(struct ks8842_adapter *adapter, u16 bank,
212 u16 bits, int offset)
213{
214 u16 reg;
215 ks8842_select_bank(adapter, bank);
216 reg = ioread16(adapter->hw_addr + offset);
217 reg &= ~bits;
218 iowrite16(reg, adapter->hw_addr + offset);
219}
220
221static inline void ks8842_write32(struct ks8842_adapter *adapter, u16 bank,
222 u32 value, int offset)
223{
224 ks8842_select_bank(adapter, bank);
225 iowrite32(value, adapter->hw_addr + offset);
226}
227
228static inline u8 ks8842_read8(struct ks8842_adapter *adapter, u16 bank,
229 int offset)
230{
231 ks8842_select_bank(adapter, bank);
232 return ioread8(adapter->hw_addr + offset);
233}
234
235static inline u16 ks8842_read16(struct ks8842_adapter *adapter, u16 bank,
236 int offset)
237{
238 ks8842_select_bank(adapter, bank);
239 return ioread16(adapter->hw_addr + offset);
240}
241
242static inline u32 ks8842_read32(struct ks8842_adapter *adapter, u16 bank,
243 int offset)
244{
245 ks8842_select_bank(adapter, bank);
246 return ioread32(adapter->hw_addr + offset);
247}
248
249static void ks8842_reset(struct ks8842_adapter *adapter)
250{
David J. Choi28bd6202010-07-13 10:09:19 -0700251 if (adapter->conf_flags & MICREL_KS884X) {
252 ks8842_write16(adapter, 3, 1, REG_GRR);
253 msleep(10);
254 iowrite16(0, adapter->hw_addr + REG_GRR);
255 } else {
256 /* The KS8842 goes haywire when doing softare reset
257 * a work around in the timberdale IP is implemented to
258 * do a hardware reset instead
259 ks8842_write16(adapter, 3, 1, REG_GRR);
260 msleep(10);
261 iowrite16(0, adapter->hw_addr + REG_GRR);
262 */
263 iowrite32(0x1, adapter->hw_addr + REG_TIMB_RST);
264 msleep(20);
265 }
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000266}
267
268static void ks8842_update_link_status(struct net_device *netdev,
269 struct ks8842_adapter *adapter)
270{
271 /* check the status of the link */
272 if (ks8842_read16(adapter, 45, REG_P1MBSR) & 0x4) {
273 netif_carrier_on(netdev);
274 netif_wake_queue(netdev);
275 } else {
276 netif_stop_queue(netdev);
277 netif_carrier_off(netdev);
278 }
279}
280
281static void ks8842_enable_tx(struct ks8842_adapter *adapter)
282{
283 ks8842_enable_bits(adapter, 16, 0x01, REG_TXCR);
284}
285
286static void ks8842_disable_tx(struct ks8842_adapter *adapter)
287{
288 ks8842_clear_bits(adapter, 16, 0x01, REG_TXCR);
289}
290
291static void ks8842_enable_rx(struct ks8842_adapter *adapter)
292{
293 ks8842_enable_bits(adapter, 16, 0x01, REG_RXCR);
294}
295
296static void ks8842_disable_rx(struct ks8842_adapter *adapter)
297{
298 ks8842_clear_bits(adapter, 16, 0x01, REG_RXCR);
299}
300
301static void ks8842_reset_hw(struct ks8842_adapter *adapter)
302{
303 /* reset the HW */
304 ks8842_reset(adapter);
305
306 /* Enable QMU Transmit flow control / transmit padding / Transmit CRC */
307 ks8842_write16(adapter, 16, 0x000E, REG_TXCR);
308
309 /* enable the receiver, uni + multi + broadcast + flow ctrl
310 + crc strip */
311 ks8842_write16(adapter, 16, 0x8 | 0x20 | 0x40 | 0x80 | 0x400,
312 REG_RXCR);
313
314 /* TX frame pointer autoincrement */
315 ks8842_write16(adapter, 17, 0x4000, REG_TXFDPR);
316
317 /* RX frame pointer autoincrement */
318 ks8842_write16(adapter, 17, 0x4000, REG_RXFDPR);
319
320 /* RX 2 kb high watermark */
321 ks8842_write16(adapter, 0, 0x1000, REG_QRFCR);
322
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300323 /* aggressive back off in half duplex */
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000324 ks8842_enable_bits(adapter, 32, 1 << 8, REG_SGCR1);
325
326 /* enable no excessive collison drop */
327 ks8842_enable_bits(adapter, 32, 1 << 3, REG_SGCR2);
328
329 /* Enable port 1 force flow control / back pressure / transmit / recv */
330 ks8842_write16(adapter, 48, 0x1E07, REG_P1CR2);
331
332 /* restart port auto-negotiation */
333 ks8842_enable_bits(adapter, 49, 1 << 13, REG_P1CR4);
David J. Choi28bd6202010-07-13 10:09:19 -0700334
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000335 /* Enable the transmitter */
336 ks8842_enable_tx(adapter);
337
338 /* Enable the receiver */
339 ks8842_enable_rx(adapter);
340
341 /* clear all interrupts */
342 ks8842_write16(adapter, 18, 0xffff, REG_ISR);
343
344 /* enable interrupts */
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000345 if (KS8842_USE_DMA(adapter)) {
346 /* When running in DMA Mode the RX interrupt is not enabled in
347 timberdale because RX data is received by DMA callbacks
348 it must still be enabled in the KS8842 because it indicates
349 to timberdale when there is RX data for it's DMA FIFOs */
350 iowrite16(ENABLED_IRQS_DMA_IP, adapter->hw_addr + REG_TIMB_IER);
351 ks8842_write16(adapter, 18, ENABLED_IRQS_DMA, REG_IER);
352 } else {
353 if (!(adapter->conf_flags & MICREL_KS884X))
354 iowrite16(ENABLED_IRQS,
355 adapter->hw_addr + REG_TIMB_IER);
356 ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER);
357 }
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000358 /* enable the switch */
359 ks8842_write16(adapter, 32, 0x1, REG_SW_ID_AND_ENABLE);
360}
361
362static void ks8842_read_mac_addr(struct ks8842_adapter *adapter, u8 *dest)
363{
364 int i;
365 u16 mac;
366
367 for (i = 0; i < ETH_ALEN; i++)
368 dest[ETH_ALEN - i - 1] = ks8842_read8(adapter, 2, REG_MARL + i);
369
David J. Choi28bd6202010-07-13 10:09:19 -0700370 if (adapter->conf_flags & MICREL_KS884X) {
371 /*
372 the sequence of saving mac addr between MAC and Switch is
373 different.
374 */
375
376 mac = ks8842_read16(adapter, 2, REG_MARL);
377 ks8842_write16(adapter, 39, mac, REG_MACAR3);
378 mac = ks8842_read16(adapter, 2, REG_MARM);
379 ks8842_write16(adapter, 39, mac, REG_MACAR2);
380 mac = ks8842_read16(adapter, 2, REG_MARH);
381 ks8842_write16(adapter, 39, mac, REG_MACAR1);
382 } else {
383
384 /* make sure the switch port uses the same MAC as the QMU */
385 mac = ks8842_read16(adapter, 2, REG_MARL);
386 ks8842_write16(adapter, 39, mac, REG_MACAR1);
387 mac = ks8842_read16(adapter, 2, REG_MARM);
388 ks8842_write16(adapter, 39, mac, REG_MACAR2);
389 mac = ks8842_read16(adapter, 2, REG_MARH);
390 ks8842_write16(adapter, 39, mac, REG_MACAR3);
391 }
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000392}
393
Richard Röjforsa1aa8822010-04-21 16:33:29 -0700394static void ks8842_write_mac_addr(struct ks8842_adapter *adapter, u8 *mac)
395{
396 unsigned long flags;
397 unsigned i;
398
399 spin_lock_irqsave(&adapter->lock, flags);
400 for (i = 0; i < ETH_ALEN; i++) {
401 ks8842_write8(adapter, 2, mac[ETH_ALEN - i - 1], REG_MARL + i);
David J. Choi28bd6202010-07-13 10:09:19 -0700402 if (!(adapter->conf_flags & MICREL_KS884X))
403 ks8842_write8(adapter, 39, mac[ETH_ALEN - i - 1],
404 REG_MACAR1 + i);
405 }
406
407 if (adapter->conf_flags & MICREL_KS884X) {
408 /*
409 the sequence of saving mac addr between MAC and Switch is
410 different.
411 */
412
413 u16 mac;
414
415 mac = ks8842_read16(adapter, 2, REG_MARL);
416 ks8842_write16(adapter, 39, mac, REG_MACAR3);
417 mac = ks8842_read16(adapter, 2, REG_MARM);
418 ks8842_write16(adapter, 39, mac, REG_MACAR2);
419 mac = ks8842_read16(adapter, 2, REG_MARH);
420 ks8842_write16(adapter, 39, mac, REG_MACAR1);
Richard Röjforsa1aa8822010-04-21 16:33:29 -0700421 }
422 spin_unlock_irqrestore(&adapter->lock, flags);
423}
424
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000425static inline u16 ks8842_tx_fifo_space(struct ks8842_adapter *adapter)
426{
427 return ks8842_read16(adapter, 16, REG_TXMIR) & 0x1fff;
428}
429
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000430static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev)
431{
432 struct ks8842_adapter *adapter = netdev_priv(netdev);
433 struct ks8842_tx_dma_ctl *ctl = &adapter->dma_tx;
434 u8 *buf = ctl->buf;
435
436 if (ctl->adesc) {
437 netdev_dbg(netdev, "%s: TX ongoing\n", __func__);
438 /* transfer ongoing */
439 return NETDEV_TX_BUSY;
440 }
441
442 sg_dma_len(&ctl->sg) = skb->len + sizeof(u32);
443
444 /* copy data to the TX buffer */
445 /* the control word, enable IRQ, port 1 and the length */
446 *buf++ = 0x00;
447 *buf++ = 0x01; /* Port 1 */
448 *buf++ = skb->len & 0xff;
449 *buf++ = (skb->len >> 8) & 0xff;
450 skb_copy_from_linear_data(skb, buf, skb->len);
451
452 dma_sync_single_range_for_device(adapter->dev,
453 sg_dma_address(&ctl->sg), 0, sg_dma_len(&ctl->sg),
454 DMA_TO_DEVICE);
455
456 /* make sure the length is a multiple of 4 */
457 if (sg_dma_len(&ctl->sg) % 4)
458 sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4;
459
460 ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan,
461 &ctl->sg, 1, DMA_TO_DEVICE,
462 DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
463 if (!ctl->adesc)
464 return NETDEV_TX_BUSY;
465
466 ctl->adesc->callback_param = netdev;
467 ctl->adesc->callback = ks8842_dma_tx_cb;
468 ctl->adesc->tx_submit(ctl->adesc);
469
470 netdev->stats.tx_bytes += skb->len;
471
472 dev_kfree_skb(skb);
473
474 return NETDEV_TX_OK;
475}
476
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000477static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
478{
479 struct ks8842_adapter *adapter = netdev_priv(netdev);
480 int len = skb->len;
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000481
Richard Röjforsa99db192010-07-04 13:26:39 +0000482 netdev_dbg(netdev, "%s: len %u head %p data %p tail %p end %p\n",
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000483 __func__, skb->len, skb->head, skb->data,
484 skb_tail_pointer(skb), skb_end_pointer(skb));
485
486 /* check FIFO buffer space, we need space for CRC and command bits */
487 if (ks8842_tx_fifo_space(adapter) < len + 8)
488 return NETDEV_TX_BUSY;
489
David J. Choi28bd6202010-07-13 10:09:19 -0700490 if (adapter->conf_flags & KS884X_16BIT) {
491 u16 *ptr16 = (u16 *)skb->data;
492 ks8842_write16(adapter, 17, 0x8000 | 0x100, REG_QMU_DATA_LO);
493 ks8842_write16(adapter, 17, (u16)len, REG_QMU_DATA_HI);
494 netdev->stats.tx_bytes += len;
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000495
David J. Choi28bd6202010-07-13 10:09:19 -0700496 /* copy buffer */
497 while (len > 0) {
498 iowrite16(*ptr16++, adapter->hw_addr + REG_QMU_DATA_LO);
499 iowrite16(*ptr16++, adapter->hw_addr + REG_QMU_DATA_HI);
500 len -= sizeof(u32);
501 }
502 } else {
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000503
David J. Choi28bd6202010-07-13 10:09:19 -0700504 u32 *ptr = (u32 *)skb->data;
505 u32 ctrl;
506 /* the control word, enable IRQ, port 1 and the length */
507 ctrl = 0x8000 | 0x100 | (len << 16);
508 ks8842_write32(adapter, 17, ctrl, REG_QMU_DATA_LO);
509
510 netdev->stats.tx_bytes += len;
511
512 /* copy buffer */
513 while (len > 0) {
514 iowrite32(*ptr, adapter->hw_addr + REG_QMU_DATA_LO);
515 len -= sizeof(u32);
516 ptr++;
517 }
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000518 }
519
520 /* enqueue packet */
521 ks8842_write16(adapter, 17, 1, REG_TXQCR);
522
523 dev_kfree_skb(skb);
524
525 return NETDEV_TX_OK;
526}
527
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000528static void ks8842_update_rx_err_counters(struct net_device *netdev, u32 status)
529{
530 netdev_dbg(netdev, "RX error, status: %x\n", status);
531
532 netdev->stats.rx_errors++;
533 if (status & RXSR_TOO_LONG)
534 netdev->stats.rx_length_errors++;
535 if (status & RXSR_CRC_ERROR)
536 netdev->stats.rx_crc_errors++;
537 if (status & RXSR_RUNT)
538 netdev->stats.rx_frame_errors++;
539}
540
541static void ks8842_update_rx_counters(struct net_device *netdev, u32 status,
542 int len)
543{
544 netdev_dbg(netdev, "RX packet, len: %d\n", len);
545
546 netdev->stats.rx_packets++;
547 netdev->stats.rx_bytes += len;
548 if (status & RXSR_MULTICAST)
549 netdev->stats.multicast++;
550}
551
552static int __ks8842_start_new_rx_dma(struct net_device *netdev)
553{
554 struct ks8842_adapter *adapter = netdev_priv(netdev);
555 struct ks8842_rx_dma_ctl *ctl = &adapter->dma_rx;
556 struct scatterlist *sg = &ctl->sg;
557 int err;
558
559 ctl->skb = netdev_alloc_skb(netdev, DMA_BUFFER_SIZE);
560 if (ctl->skb) {
561 sg_init_table(sg, 1);
562 sg_dma_address(sg) = dma_map_single(adapter->dev,
563 ctl->skb->data, DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
564 err = dma_mapping_error(adapter->dev, sg_dma_address(sg));
565 if (unlikely(err)) {
566 sg_dma_address(sg) = 0;
567 goto out;
568 }
569
570 sg_dma_len(sg) = DMA_BUFFER_SIZE;
571
572 ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan,
573 sg, 1, DMA_FROM_DEVICE,
574 DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
575
576 if (!ctl->adesc)
577 goto out;
578
579 ctl->adesc->callback_param = netdev;
580 ctl->adesc->callback = ks8842_dma_rx_cb;
581 ctl->adesc->tx_submit(ctl->adesc);
582 } else {
583 err = -ENOMEM;
584 sg_dma_address(sg) = 0;
585 goto out;
586 }
587
588 return err;
589out:
590 if (sg_dma_address(sg))
591 dma_unmap_single(adapter->dev, sg_dma_address(sg),
592 DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
593 sg_dma_address(sg) = 0;
594 if (ctl->skb)
595 dev_kfree_skb(ctl->skb);
596
597 ctl->skb = NULL;
598
599 printk(KERN_ERR DRV_NAME": Failed to start RX DMA: %d\n", err);
600 return err;
601}
602
603static void ks8842_rx_frame_dma_tasklet(unsigned long arg)
604{
605 struct net_device *netdev = (struct net_device *)arg;
606 struct ks8842_adapter *adapter = netdev_priv(netdev);
607 struct ks8842_rx_dma_ctl *ctl = &adapter->dma_rx;
608 struct sk_buff *skb = ctl->skb;
609 dma_addr_t addr = sg_dma_address(&ctl->sg);
610 u32 status;
611
612 ctl->adesc = NULL;
613
614 /* kick next transfer going */
615 __ks8842_start_new_rx_dma(netdev);
616
617 /* now handle the data we got */
618 dma_unmap_single(adapter->dev, addr, DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
619
620 status = *((u32 *)skb->data);
621
622 netdev_dbg(netdev, "%s - rx_data: status: %x\n",
623 __func__, status & 0xffff);
624
625 /* check the status */
626 if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) {
627 int len = (status >> 16) & 0x7ff;
628
629 ks8842_update_rx_counters(netdev, status, len);
630
631 /* reserve 4 bytes which is the status word */
632 skb_reserve(skb, 4);
633 skb_put(skb, len);
634
635 skb->protocol = eth_type_trans(skb, netdev);
636 netif_rx(skb);
637 } else {
638 ks8842_update_rx_err_counters(netdev, status);
639 dev_kfree_skb(skb);
640 }
641}
642
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000643static void ks8842_rx_frame(struct net_device *netdev,
644 struct ks8842_adapter *adapter)
645{
David J. Choi28bd6202010-07-13 10:09:19 -0700646 u32 status;
647 int len;
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000648
David J. Choi28bd6202010-07-13 10:09:19 -0700649 if (adapter->conf_flags & KS884X_16BIT) {
David S. Millere2df8b72010-07-19 15:25:04 -0700650 status = ks8842_read16(adapter, 17, REG_QMU_DATA_LO);
651 len = ks8842_read16(adapter, 17, REG_QMU_DATA_HI);
David J. Choi28bd6202010-07-13 10:09:19 -0700652 netdev_dbg(netdev, "%s - rx_data: status: %x\n",
David S. Millere2df8b72010-07-19 15:25:04 -0700653 __func__, status);
David J. Choi28bd6202010-07-13 10:09:19 -0700654 } else {
655 status = ks8842_read32(adapter, 17, REG_QMU_DATA_LO);
656 len = (status >> 16) & 0x7ff;
657 status &= 0xffff;
658 netdev_dbg(netdev, "%s - rx_data: status: %x\n",
659 __func__, status);
660 }
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000661
662 /* check the status */
663 if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) {
Dennis Aberillab10cec82011-05-29 11:46:54 +0000664 struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev, len + 3);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000665
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000666 if (skb) {
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000667
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000668 ks8842_update_rx_counters(netdev, status, len);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000669
David J. Choi28bd6202010-07-13 10:09:19 -0700670 if (adapter->conf_flags & KS884X_16BIT) {
671 u16 *data16 = (u16 *)skb_put(skb, len);
672 ks8842_select_bank(adapter, 17);
673 while (len > 0) {
674 *data16++ = ioread16(adapter->hw_addr +
675 REG_QMU_DATA_LO);
676 *data16++ = ioread16(adapter->hw_addr +
677 REG_QMU_DATA_HI);
678 len -= sizeof(u32);
679 }
680 } else {
681 u32 *data = (u32 *)skb_put(skb, len);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000682
David J. Choi28bd6202010-07-13 10:09:19 -0700683 ks8842_select_bank(adapter, 17);
684 while (len > 0) {
685 *data++ = ioread32(adapter->hw_addr +
686 REG_QMU_DATA_LO);
687 len -= sizeof(u32);
688 }
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000689 }
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000690 skb->protocol = eth_type_trans(skb, netdev);
691 netif_rx(skb);
692 } else
693 netdev->stats.rx_dropped++;
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000694 } else
695 ks8842_update_rx_err_counters(netdev, status);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000696
697 /* set high watermark to 3K */
698 ks8842_clear_bits(adapter, 0, 1 << 12, REG_QRFCR);
699
700 /* release the frame */
701 ks8842_write16(adapter, 17, 0x01, REG_RXQCR);
702
703 /* set high watermark to 2K */
704 ks8842_enable_bits(adapter, 0, 1 << 12, REG_QRFCR);
705}
706
707void ks8842_handle_rx(struct net_device *netdev, struct ks8842_adapter *adapter)
708{
709 u16 rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff;
Richard Röjforsa99db192010-07-04 13:26:39 +0000710 netdev_dbg(netdev, "%s Entry - rx_data: %d\n", __func__, rx_data);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000711 while (rx_data) {
712 ks8842_rx_frame(netdev, adapter);
713 rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff;
714 }
715}
716
717void ks8842_handle_tx(struct net_device *netdev, struct ks8842_adapter *adapter)
718{
719 u16 sr = ks8842_read16(adapter, 16, REG_TXSR);
Richard Röjforsa99db192010-07-04 13:26:39 +0000720 netdev_dbg(netdev, "%s - entry, sr: %x\n", __func__, sr);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000721 netdev->stats.tx_packets++;
722 if (netif_queue_stopped(netdev))
723 netif_wake_queue(netdev);
724}
725
726void ks8842_handle_rx_overrun(struct net_device *netdev,
727 struct ks8842_adapter *adapter)
728{
Richard Röjforsa99db192010-07-04 13:26:39 +0000729 netdev_dbg(netdev, "%s: entry\n", __func__);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000730 netdev->stats.rx_errors++;
731 netdev->stats.rx_fifo_errors++;
732}
733
734void ks8842_tasklet(unsigned long arg)
735{
736 struct net_device *netdev = (struct net_device *)arg;
737 struct ks8842_adapter *adapter = netdev_priv(netdev);
738 u16 isr;
739 unsigned long flags;
740 u16 entry_bank;
741
742 /* read current bank to be able to set it back */
743 spin_lock_irqsave(&adapter->lock, flags);
744 entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK);
745 spin_unlock_irqrestore(&adapter->lock, flags);
746
747 isr = ks8842_read16(adapter, 18, REG_ISR);
Richard Röjforsa99db192010-07-04 13:26:39 +0000748 netdev_dbg(netdev, "%s - ISR: 0x%x\n", __func__, isr);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000749
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000750 /* when running in DMA mode, do not ack RX interrupts, it is handled
751 internally by timberdale, otherwise it's DMA FIFO:s would stop
752 */
753 if (KS8842_USE_DMA(adapter))
754 isr &= ~IRQ_RX;
755
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000756 /* Ack */
757 ks8842_write16(adapter, 18, isr, REG_ISR);
758
Richard Röjforsdb5824d2010-07-25 22:51:05 +0000759 if (!(adapter->conf_flags & MICREL_KS884X))
760 /* Ack in the timberdale IP as well */
761 iowrite32(0x1, adapter->hw_addr + REG_TIMB_IAR);
762
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000763 if (!netif_running(netdev))
764 return;
765
766 if (isr & IRQ_LINK_CHANGE)
767 ks8842_update_link_status(netdev, adapter);
768
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000769 /* should not get IRQ_RX when running DMA mode */
770 if (isr & (IRQ_RX | IRQ_RX_ERROR) && !KS8842_USE_DMA(adapter))
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000771 ks8842_handle_rx(netdev, adapter);
772
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000773 /* should only happen when in PIO mode */
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000774 if (isr & IRQ_TX)
775 ks8842_handle_tx(netdev, adapter);
776
777 if (isr & IRQ_RX_OVERRUN)
778 ks8842_handle_rx_overrun(netdev, adapter);
779
780 if (isr & IRQ_TX_STOPPED) {
781 ks8842_disable_tx(adapter);
782 ks8842_enable_tx(adapter);
783 }
784
785 if (isr & IRQ_RX_STOPPED) {
786 ks8842_disable_rx(adapter);
787 ks8842_enable_rx(adapter);
788 }
789
790 /* re-enable interrupts, put back the bank selection register */
791 spin_lock_irqsave(&adapter->lock, flags);
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000792 if (KS8842_USE_DMA(adapter))
793 ks8842_write16(adapter, 18, ENABLED_IRQS_DMA, REG_IER);
794 else
795 ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000796 iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK);
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000797
798 /* Make sure timberdale continues DMA operations, they are stopped while
799 we are handling the ks8842 because we might change bank */
800 if (KS8842_USE_DMA(adapter))
801 ks8842_resume_dma(adapter);
802
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000803 spin_unlock_irqrestore(&adapter->lock, flags);
804}
805
806static irqreturn_t ks8842_irq(int irq, void *devid)
807{
Richard Röjforsa99db192010-07-04 13:26:39 +0000808 struct net_device *netdev = devid;
809 struct ks8842_adapter *adapter = netdev_priv(netdev);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000810 u16 isr;
811 u16 entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK);
812 irqreturn_t ret = IRQ_NONE;
813
814 isr = ks8842_read16(adapter, 18, REG_ISR);
Richard Röjforsa99db192010-07-04 13:26:39 +0000815 netdev_dbg(netdev, "%s - ISR: 0x%x\n", __func__, isr);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000816
817 if (isr) {
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000818 if (KS8842_USE_DMA(adapter))
819 /* disable all but RX IRQ, since the FPGA relies on it*/
820 ks8842_write16(adapter, 18, IRQ_RX, REG_IER);
821 else
822 /* disable IRQ */
823 ks8842_write16(adapter, 18, 0x00, REG_IER);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000824
825 /* schedule tasklet */
826 tasklet_schedule(&adapter->tasklet);
827
828 ret = IRQ_HANDLED;
829 }
830
831 iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK);
832
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000833 /* After an interrupt, tell timberdale to continue DMA operations.
834 DMA is disabled while we are handling the ks8842 because we might
835 change bank */
836 ks8842_resume_dma(adapter);
837
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000838 return ret;
839}
840
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000841static void ks8842_dma_rx_cb(void *data)
842{
843 struct net_device *netdev = data;
844 struct ks8842_adapter *adapter = netdev_priv(netdev);
845
846 netdev_dbg(netdev, "RX DMA finished\n");
847 /* schedule tasklet */
848 if (adapter->dma_rx.adesc)
849 tasklet_schedule(&adapter->dma_rx.tasklet);
850}
851
852static void ks8842_dma_tx_cb(void *data)
853{
854 struct net_device *netdev = data;
855 struct ks8842_adapter *adapter = netdev_priv(netdev);
856 struct ks8842_tx_dma_ctl *ctl = &adapter->dma_tx;
857
858 netdev_dbg(netdev, "TX DMA finished\n");
859
860 if (!ctl->adesc)
861 return;
862
863 netdev->stats.tx_packets++;
864 ctl->adesc = NULL;
865
866 if (netif_queue_stopped(netdev))
867 netif_wake_queue(netdev);
868}
869
870static void ks8842_stop_dma(struct ks8842_adapter *adapter)
871{
872 struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx;
873 struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx;
874
875 tx_ctl->adesc = NULL;
876 if (tx_ctl->chan)
877 tx_ctl->chan->device->device_control(tx_ctl->chan,
878 DMA_TERMINATE_ALL, 0);
879
880 rx_ctl->adesc = NULL;
881 if (rx_ctl->chan)
882 rx_ctl->chan->device->device_control(rx_ctl->chan,
883 DMA_TERMINATE_ALL, 0);
884
885 if (sg_dma_address(&rx_ctl->sg))
886 dma_unmap_single(adapter->dev, sg_dma_address(&rx_ctl->sg),
887 DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
888 sg_dma_address(&rx_ctl->sg) = 0;
889
890 dev_kfree_skb(rx_ctl->skb);
891 rx_ctl->skb = NULL;
892}
893
894static void ks8842_dealloc_dma_bufs(struct ks8842_adapter *adapter)
895{
896 struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx;
897 struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx;
898
899 ks8842_stop_dma(adapter);
900
901 if (tx_ctl->chan)
902 dma_release_channel(tx_ctl->chan);
903 tx_ctl->chan = NULL;
904
905 if (rx_ctl->chan)
906 dma_release_channel(rx_ctl->chan);
907 rx_ctl->chan = NULL;
908
909 tasklet_kill(&rx_ctl->tasklet);
910
911 if (sg_dma_address(&tx_ctl->sg))
912 dma_unmap_single(adapter->dev, sg_dma_address(&tx_ctl->sg),
913 DMA_BUFFER_SIZE, DMA_TO_DEVICE);
914 sg_dma_address(&tx_ctl->sg) = 0;
915
916 kfree(tx_ctl->buf);
917 tx_ctl->buf = NULL;
918}
919
920static bool ks8842_dma_filter_fn(struct dma_chan *chan, void *filter_param)
921{
David S. Millerbd280632010-07-27 22:24:37 -0700922 return chan->chan_id == (long)filter_param;
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000923}
924
925static int ks8842_alloc_dma_bufs(struct net_device *netdev)
926{
927 struct ks8842_adapter *adapter = netdev_priv(netdev);
928 struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx;
929 struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx;
930 int err;
931
932 dma_cap_mask_t mask;
933
934 dma_cap_zero(mask);
935 dma_cap_set(DMA_SLAVE, mask);
936 dma_cap_set(DMA_PRIVATE, mask);
937
938 sg_init_table(&tx_ctl->sg, 1);
939
940 tx_ctl->chan = dma_request_channel(mask, ks8842_dma_filter_fn,
David S. Millerbd280632010-07-27 22:24:37 -0700941 (void *)(long)tx_ctl->channel);
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000942 if (!tx_ctl->chan) {
943 err = -ENODEV;
944 goto err;
945 }
946
947 /* allocate DMA buffer */
948 tx_ctl->buf = kmalloc(DMA_BUFFER_SIZE, GFP_KERNEL);
949 if (!tx_ctl->buf) {
950 err = -ENOMEM;
951 goto err;
952 }
953
954 sg_dma_address(&tx_ctl->sg) = dma_map_single(adapter->dev,
955 tx_ctl->buf, DMA_BUFFER_SIZE, DMA_TO_DEVICE);
956 err = dma_mapping_error(adapter->dev,
957 sg_dma_address(&tx_ctl->sg));
958 if (err) {
959 sg_dma_address(&tx_ctl->sg) = 0;
960 goto err;
961 }
962
963 rx_ctl->chan = dma_request_channel(mask, ks8842_dma_filter_fn,
David S. Millerbd280632010-07-27 22:24:37 -0700964 (void *)(long)rx_ctl->channel);
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000965 if (!rx_ctl->chan) {
966 err = -ENODEV;
967 goto err;
968 }
969
970 tasklet_init(&rx_ctl->tasklet, ks8842_rx_frame_dma_tasklet,
971 (unsigned long)netdev);
972
973 return 0;
974err:
975 ks8842_dealloc_dma_bufs(adapter);
976 return err;
977}
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000978
979/* Netdevice operations */
980
981static int ks8842_open(struct net_device *netdev)
982{
983 struct ks8842_adapter *adapter = netdev_priv(netdev);
984 int err;
985
Richard Röjforsa99db192010-07-04 13:26:39 +0000986 netdev_dbg(netdev, "%s - entry\n", __func__);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +0000987
Richard Röjfors94fe8c62010-07-27 12:57:01 +0000988 if (KS8842_USE_DMA(adapter)) {
989 err = ks8842_alloc_dma_bufs(netdev);
990
991 if (!err) {
992 /* start RX dma */
993 err = __ks8842_start_new_rx_dma(netdev);
994 if (err)
995 ks8842_dealloc_dma_bufs(adapter);
996 }
997
998 if (err) {
999 printk(KERN_WARNING DRV_NAME
1000 ": Failed to initiate DMA, running PIO\n");
1001 ks8842_dealloc_dma_bufs(adapter);
1002 adapter->dma_rx.channel = -1;
1003 adapter->dma_tx.channel = -1;
1004 }
1005 }
1006
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001007 /* reset the HW */
1008 ks8842_reset_hw(adapter);
1009
Richard Röjforsa1aa8822010-04-21 16:33:29 -07001010 ks8842_write_mac_addr(adapter, netdev->dev_addr);
1011
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001012 ks8842_update_link_status(netdev, adapter);
1013
1014 err = request_irq(adapter->irq, ks8842_irq, IRQF_SHARED, DRV_NAME,
Richard Röjforsa99db192010-07-04 13:26:39 +00001015 netdev);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001016 if (err) {
Joe Perches0dc7d2b2010-02-27 14:43:51 +00001017 pr_err("Failed to request IRQ: %d: %d\n", adapter->irq, err);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001018 return err;
1019 }
1020
1021 return 0;
1022}
1023
1024static int ks8842_close(struct net_device *netdev)
1025{
1026 struct ks8842_adapter *adapter = netdev_priv(netdev);
1027
Richard Röjforsa99db192010-07-04 13:26:39 +00001028 netdev_dbg(netdev, "%s - entry\n", __func__);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001029
Richard Röjforscc88e452010-07-08 23:36:30 -07001030 cancel_work_sync(&adapter->timeout_work);
1031
Richard Röjfors94fe8c62010-07-27 12:57:01 +00001032 if (KS8842_USE_DMA(adapter))
1033 ks8842_dealloc_dma_bufs(adapter);
1034
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001035 /* free the irq */
Richard Röjforsa99db192010-07-04 13:26:39 +00001036 free_irq(adapter->irq, netdev);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001037
1038 /* disable the switch */
1039 ks8842_write16(adapter, 32, 0x0, REG_SW_ID_AND_ENABLE);
1040
1041 return 0;
1042}
1043
Stephen Hemminger613573252009-08-31 19:50:58 +00001044static netdev_tx_t ks8842_xmit_frame(struct sk_buff *skb,
1045 struct net_device *netdev)
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001046{
1047 int ret;
1048 struct ks8842_adapter *adapter = netdev_priv(netdev);
1049
Richard Röjforsa99db192010-07-04 13:26:39 +00001050 netdev_dbg(netdev, "%s: entry\n", __func__);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001051
Richard Röjfors94fe8c62010-07-27 12:57:01 +00001052 if (KS8842_USE_DMA(adapter)) {
1053 unsigned long flags;
1054 ret = ks8842_tx_frame_dma(skb, netdev);
1055 /* for now only allow one transfer at the time */
1056 spin_lock_irqsave(&adapter->lock, flags);
1057 if (adapter->dma_tx.adesc)
1058 netif_stop_queue(netdev);
1059 spin_unlock_irqrestore(&adapter->lock, flags);
1060 return ret;
1061 }
1062
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001063 ret = ks8842_tx_frame(skb, netdev);
1064
1065 if (ks8842_tx_fifo_space(adapter) < netdev->mtu + 8)
1066 netif_stop_queue(netdev);
1067
1068 return ret;
1069}
1070
1071static int ks8842_set_mac(struct net_device *netdev, void *p)
1072{
1073 struct ks8842_adapter *adapter = netdev_priv(netdev);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001074 struct sockaddr *addr = p;
1075 char *mac = (u8 *)addr->sa_data;
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001076
Richard Röjforsa99db192010-07-04 13:26:39 +00001077 netdev_dbg(netdev, "%s: entry\n", __func__);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001078
1079 if (!is_valid_ether_addr(addr->sa_data))
1080 return -EADDRNOTAVAIL;
1081
1082 memcpy(netdev->dev_addr, mac, netdev->addr_len);
1083
Richard Röjforsa1aa8822010-04-21 16:33:29 -07001084 ks8842_write_mac_addr(adapter, mac);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001085 return 0;
1086}
1087
Richard Röjforscc88e452010-07-08 23:36:30 -07001088static void ks8842_tx_timeout_work(struct work_struct *work)
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001089{
Richard Röjforscc88e452010-07-08 23:36:30 -07001090 struct ks8842_adapter *adapter =
1091 container_of(work, struct ks8842_adapter, timeout_work);
1092 struct net_device *netdev = adapter->netdev;
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001093 unsigned long flags;
1094
Richard Röjforsa99db192010-07-04 13:26:39 +00001095 netdev_dbg(netdev, "%s: entry\n", __func__);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001096
1097 spin_lock_irqsave(&adapter->lock, flags);
Richard Röjfors94fe8c62010-07-27 12:57:01 +00001098
1099 if (KS8842_USE_DMA(adapter))
1100 ks8842_stop_dma(adapter);
1101
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001102 /* disable interrupts */
1103 ks8842_write16(adapter, 18, 0, REG_IER);
1104 ks8842_write16(adapter, 18, 0xFFFF, REG_ISR);
Richard Röjforscc88e452010-07-08 23:36:30 -07001105
1106 netif_stop_queue(netdev);
1107
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001108 spin_unlock_irqrestore(&adapter->lock, flags);
1109
1110 ks8842_reset_hw(adapter);
1111
Richard Röjforsa1aa8822010-04-21 16:33:29 -07001112 ks8842_write_mac_addr(adapter, netdev->dev_addr);
1113
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001114 ks8842_update_link_status(netdev, adapter);
Richard Röjfors94fe8c62010-07-27 12:57:01 +00001115
1116 if (KS8842_USE_DMA(adapter))
1117 __ks8842_start_new_rx_dma(netdev);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001118}
1119
Richard Röjforscc88e452010-07-08 23:36:30 -07001120static void ks8842_tx_timeout(struct net_device *netdev)
1121{
1122 struct ks8842_adapter *adapter = netdev_priv(netdev);
1123
1124 netdev_dbg(netdev, "%s: entry\n", __func__);
1125
1126 schedule_work(&adapter->timeout_work);
1127}
1128
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001129static const struct net_device_ops ks8842_netdev_ops = {
1130 .ndo_open = ks8842_open,
1131 .ndo_stop = ks8842_close,
1132 .ndo_start_xmit = ks8842_xmit_frame,
1133 .ndo_set_mac_address = ks8842_set_mac,
1134 .ndo_tx_timeout = ks8842_tx_timeout,
1135 .ndo_validate_addr = eth_validate_addr
1136};
1137
Stephen Hemminger0fc0b732009-09-02 01:03:33 -07001138static const struct ethtool_ops ks8842_ethtool_ops = {
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001139 .get_link = ethtool_op_get_link,
1140};
1141
1142static int __devinit ks8842_probe(struct platform_device *pdev)
1143{
1144 int err = -ENOMEM;
1145 struct resource *iomem;
1146 struct net_device *netdev;
1147 struct ks8842_adapter *adapter;
Samuel Ortiz3271d382011-04-08 01:23:57 +02001148 struct ks8842_platform_data *pdata = pdev->dev.platform_data;
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001149 u16 id;
Richard Röjforsa1aa8822010-04-21 16:33:29 -07001150 unsigned i;
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001151
1152 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1153 if (!request_mem_region(iomem->start, resource_size(iomem), DRV_NAME))
1154 goto err_mem_region;
1155
1156 netdev = alloc_etherdev(sizeof(struct ks8842_adapter));
1157 if (!netdev)
1158 goto err_alloc_etherdev;
1159
1160 SET_NETDEV_DEV(netdev, &pdev->dev);
1161
1162 adapter = netdev_priv(netdev);
Richard Röjforscc88e452010-07-08 23:36:30 -07001163 adapter->netdev = netdev;
1164 INIT_WORK(&adapter->timeout_work, ks8842_tx_timeout_work);
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001165 adapter->hw_addr = ioremap(iomem->start, resource_size(iomem));
David J. Choi28bd6202010-07-13 10:09:19 -07001166 adapter->conf_flags = iomem->flags;
1167
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001168 if (!adapter->hw_addr)
1169 goto err_ioremap;
1170
1171 adapter->irq = platform_get_irq(pdev, 0);
1172 if (adapter->irq < 0) {
1173 err = adapter->irq;
1174 goto err_get_irq;
1175 }
1176
Richard Röjfors94fe8c62010-07-27 12:57:01 +00001177 adapter->dev = (pdev->dev.parent) ? pdev->dev.parent : &pdev->dev;
1178
1179 /* DMA is only supported when accessed via timberdale */
1180 if (!(adapter->conf_flags & MICREL_KS884X) && pdata &&
1181 (pdata->tx_dma_channel != -1) &&
1182 (pdata->rx_dma_channel != -1)) {
1183 adapter->dma_rx.channel = pdata->rx_dma_channel;
1184 adapter->dma_tx.channel = pdata->tx_dma_channel;
1185 } else {
1186 adapter->dma_rx.channel = -1;
1187 adapter->dma_tx.channel = -1;
1188 }
1189
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001190 tasklet_init(&adapter->tasklet, ks8842_tasklet, (unsigned long)netdev);
1191 spin_lock_init(&adapter->lock);
1192
1193 netdev->netdev_ops = &ks8842_netdev_ops;
1194 netdev->ethtool_ops = &ks8842_ethtool_ops;
1195
Richard Röjforsa1aa8822010-04-21 16:33:29 -07001196 /* Check if a mac address was given */
1197 i = netdev->addr_len;
1198 if (pdata) {
1199 for (i = 0; i < netdev->addr_len; i++)
1200 if (pdata->macaddr[i] != 0)
1201 break;
1202
1203 if (i < netdev->addr_len)
1204 /* an address was passed, use it */
1205 memcpy(netdev->dev_addr, pdata->macaddr,
1206 netdev->addr_len);
1207 }
1208
1209 if (i == netdev->addr_len) {
1210 ks8842_read_mac_addr(adapter, netdev->dev_addr);
1211
1212 if (!is_valid_ether_addr(netdev->dev_addr))
1213 random_ether_addr(netdev->dev_addr);
1214 }
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001215
1216 id = ks8842_read16(adapter, 32, REG_SW_ID_AND_ENABLE);
1217
1218 strcpy(netdev->name, "eth%d");
1219 err = register_netdev(netdev);
1220 if (err)
1221 goto err_register;
1222
1223 platform_set_drvdata(pdev, netdev);
1224
Joe Perches0dc7d2b2010-02-27 14:43:51 +00001225 pr_info("Found chip, family: 0x%x, id: 0x%x, rev: 0x%x\n",
Richard Ršöjforsb07878e2009-06-04 03:35:55 +00001226 (id >> 8) & 0xff, (id >> 4) & 0xf, (id >> 1) & 0x7);
1227
1228 return 0;
1229
1230err_register:
1231err_get_irq:
1232 iounmap(adapter->hw_addr);
1233err_ioremap:
1234 free_netdev(netdev);
1235err_alloc_etherdev:
1236 release_mem_region(iomem->start, resource_size(iomem));
1237err_mem_region:
1238 return err;
1239}
1240
1241static int __devexit ks8842_remove(struct platform_device *pdev)
1242{
1243 struct net_device *netdev = platform_get_drvdata(pdev);
1244 struct ks8842_adapter *adapter = netdev_priv(netdev);
1245 struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1246
1247 unregister_netdev(netdev);
1248 tasklet_kill(&adapter->tasklet);
1249 iounmap(adapter->hw_addr);
1250 free_netdev(netdev);
1251 release_mem_region(iomem->start, resource_size(iomem));
1252 platform_set_drvdata(pdev, NULL);
1253 return 0;
1254}
1255
1256
1257static struct platform_driver ks8842_platform_driver = {
1258 .driver = {
1259 .name = DRV_NAME,
1260 .owner = THIS_MODULE,
1261 },
1262 .probe = ks8842_probe,
1263 .remove = ks8842_remove,
1264};
1265
1266static int __init ks8842_init(void)
1267{
1268 return platform_driver_register(&ks8842_platform_driver);
1269}
1270
1271static void __exit ks8842_exit(void)
1272{
1273 platform_driver_unregister(&ks8842_platform_driver);
1274}
1275
1276module_init(ks8842_init);
1277module_exit(ks8842_exit);
1278
1279MODULE_DESCRIPTION("Timberdale KS8842 ethernet driver");
1280MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
1281MODULE_LICENSE("GPL v2");
1282MODULE_ALIAS("platform:ks8842");
1283