182c29810SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2bcc9736cSJeff Kirsher /*
3bcc9736cSJeff Kirsher * ks8842.c timberdale KS8842 ethernet driver
4bcc9736cSJeff Kirsher * Copyright (c) 2009 Intel Corporation
5bcc9736cSJeff Kirsher */
6bcc9736cSJeff Kirsher
7bcc9736cSJeff Kirsher /* Supports:
8bcc9736cSJeff Kirsher * The Micrel KS8842 behind the timberdale FPGA
9bcc9736cSJeff Kirsher * The genuine Micrel KS8841/42 device with ISA 16/32bit bus interface
10bcc9736cSJeff Kirsher */
11bcc9736cSJeff Kirsher
12bcc9736cSJeff Kirsher #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13bcc9736cSJeff Kirsher
14bcc9736cSJeff Kirsher #include <linux/interrupt.h>
15bcc9736cSJeff Kirsher #include <linux/kernel.h>
16bcc9736cSJeff Kirsher #include <linux/module.h>
17bcc9736cSJeff Kirsher #include <linux/platform_device.h>
18bcc9736cSJeff Kirsher #include <linux/netdevice.h>
19bcc9736cSJeff Kirsher #include <linux/etherdevice.h>
20bcc9736cSJeff Kirsher #include <linux/ethtool.h>
21bcc9736cSJeff Kirsher #include <linux/ks8842.h>
22bcc9736cSJeff Kirsher #include <linux/dmaengine.h>
23bcc9736cSJeff Kirsher #include <linux/dma-mapping.h>
24bcc9736cSJeff Kirsher #include <linux/scatterlist.h>
25bcc9736cSJeff Kirsher
26bcc9736cSJeff Kirsher #define DRV_NAME "ks8842"
27bcc9736cSJeff Kirsher
28bcc9736cSJeff Kirsher /* Timberdale specific Registers */
29bcc9736cSJeff Kirsher #define REG_TIMB_RST 0x1c
30bcc9736cSJeff Kirsher #define REG_TIMB_FIFO 0x20
31bcc9736cSJeff Kirsher #define REG_TIMB_ISR 0x24
32bcc9736cSJeff Kirsher #define REG_TIMB_IER 0x28
33bcc9736cSJeff Kirsher #define REG_TIMB_IAR 0x2C
34bcc9736cSJeff Kirsher #define REQ_TIMB_DMA_RESUME 0x30
35bcc9736cSJeff Kirsher
36bcc9736cSJeff Kirsher /* KS8842 registers */
37bcc9736cSJeff Kirsher
38bcc9736cSJeff Kirsher #define REG_SELECT_BANK 0x0e
39bcc9736cSJeff Kirsher
40bcc9736cSJeff Kirsher /* bank 0 registers */
41bcc9736cSJeff Kirsher #define REG_QRFCR 0x04
42bcc9736cSJeff Kirsher
43bcc9736cSJeff Kirsher /* bank 2 registers */
44bcc9736cSJeff Kirsher #define REG_MARL 0x00
45bcc9736cSJeff Kirsher #define REG_MARM 0x02
46bcc9736cSJeff Kirsher #define REG_MARH 0x04
47bcc9736cSJeff Kirsher
48bcc9736cSJeff Kirsher /* bank 3 registers */
49bcc9736cSJeff Kirsher #define REG_GRR 0x06
50bcc9736cSJeff Kirsher
51bcc9736cSJeff Kirsher /* bank 16 registers */
52bcc9736cSJeff Kirsher #define REG_TXCR 0x00
53bcc9736cSJeff Kirsher #define REG_TXSR 0x02
54bcc9736cSJeff Kirsher #define REG_RXCR 0x04
55bcc9736cSJeff Kirsher #define REG_TXMIR 0x08
56bcc9736cSJeff Kirsher #define REG_RXMIR 0x0A
57bcc9736cSJeff Kirsher
58bcc9736cSJeff Kirsher /* bank 17 registers */
59bcc9736cSJeff Kirsher #define REG_TXQCR 0x00
60bcc9736cSJeff Kirsher #define REG_RXQCR 0x02
61bcc9736cSJeff Kirsher #define REG_TXFDPR 0x04
62bcc9736cSJeff Kirsher #define REG_RXFDPR 0x06
63bcc9736cSJeff Kirsher #define REG_QMU_DATA_LO 0x08
64bcc9736cSJeff Kirsher #define REG_QMU_DATA_HI 0x0A
65bcc9736cSJeff Kirsher
66bcc9736cSJeff Kirsher /* bank 18 registers */
67bcc9736cSJeff Kirsher #define REG_IER 0x00
68bcc9736cSJeff Kirsher #define IRQ_LINK_CHANGE 0x8000
69bcc9736cSJeff Kirsher #define IRQ_TX 0x4000
70bcc9736cSJeff Kirsher #define IRQ_RX 0x2000
71bcc9736cSJeff Kirsher #define IRQ_RX_OVERRUN 0x0800
72bcc9736cSJeff Kirsher #define IRQ_TX_STOPPED 0x0200
73bcc9736cSJeff Kirsher #define IRQ_RX_STOPPED 0x0100
74bcc9736cSJeff Kirsher #define IRQ_RX_ERROR 0x0080
75bcc9736cSJeff Kirsher #define ENABLED_IRQS (IRQ_LINK_CHANGE | IRQ_TX | IRQ_RX | IRQ_RX_STOPPED | \
76bcc9736cSJeff Kirsher IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR)
77bcc9736cSJeff Kirsher /* When running via timberdale in DMA mode, the RX interrupt should be
78bcc9736cSJeff Kirsher enabled in the KS8842, but not in the FPGA IP, since the IP handles
79bcc9736cSJeff Kirsher RX DMA internally.
80bcc9736cSJeff Kirsher TX interrupts are not needed it is handled by the FPGA the driver is
81bcc9736cSJeff Kirsher notified via DMA callbacks.
82bcc9736cSJeff Kirsher */
83bcc9736cSJeff Kirsher #define ENABLED_IRQS_DMA_IP (IRQ_LINK_CHANGE | IRQ_RX_STOPPED | \
84bcc9736cSJeff Kirsher IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR)
85bcc9736cSJeff Kirsher #define ENABLED_IRQS_DMA (ENABLED_IRQS_DMA_IP | IRQ_RX)
86bcc9736cSJeff Kirsher #define REG_ISR 0x02
87bcc9736cSJeff Kirsher #define REG_RXSR 0x04
88bcc9736cSJeff Kirsher #define RXSR_VALID 0x8000
89bcc9736cSJeff Kirsher #define RXSR_BROADCAST 0x80
90bcc9736cSJeff Kirsher #define RXSR_MULTICAST 0x40
91bcc9736cSJeff Kirsher #define RXSR_UNICAST 0x20
92bcc9736cSJeff Kirsher #define RXSR_FRAMETYPE 0x08
93bcc9736cSJeff Kirsher #define RXSR_TOO_LONG 0x04
94bcc9736cSJeff Kirsher #define RXSR_RUNT 0x02
95bcc9736cSJeff Kirsher #define RXSR_CRC_ERROR 0x01
96bcc9736cSJeff Kirsher #define RXSR_ERROR (RXSR_TOO_LONG | RXSR_RUNT | RXSR_CRC_ERROR)
97bcc9736cSJeff Kirsher
98bcc9736cSJeff Kirsher /* bank 32 registers */
99bcc9736cSJeff Kirsher #define REG_SW_ID_AND_ENABLE 0x00
100bcc9736cSJeff Kirsher #define REG_SGCR1 0x02
101bcc9736cSJeff Kirsher #define REG_SGCR2 0x04
102bcc9736cSJeff Kirsher #define REG_SGCR3 0x06
103bcc9736cSJeff Kirsher
104bcc9736cSJeff Kirsher /* bank 39 registers */
105bcc9736cSJeff Kirsher #define REG_MACAR1 0x00
106bcc9736cSJeff Kirsher #define REG_MACAR2 0x02
107bcc9736cSJeff Kirsher #define REG_MACAR3 0x04
108bcc9736cSJeff Kirsher
109bcc9736cSJeff Kirsher /* bank 45 registers */
110bcc9736cSJeff Kirsher #define REG_P1MBCR 0x00
111bcc9736cSJeff Kirsher #define REG_P1MBSR 0x02
112bcc9736cSJeff Kirsher
113bcc9736cSJeff Kirsher /* bank 46 registers */
114bcc9736cSJeff Kirsher #define REG_P2MBCR 0x00
115bcc9736cSJeff Kirsher #define REG_P2MBSR 0x02
116bcc9736cSJeff Kirsher
117bcc9736cSJeff Kirsher /* bank 48 registers */
118bcc9736cSJeff Kirsher #define REG_P1CR2 0x02
119bcc9736cSJeff Kirsher
120bcc9736cSJeff Kirsher /* bank 49 registers */
121bcc9736cSJeff Kirsher #define REG_P1CR4 0x02
122bcc9736cSJeff Kirsher #define REG_P1SR 0x04
123bcc9736cSJeff Kirsher
124bcc9736cSJeff Kirsher /* flags passed by platform_device for configuration */
125bcc9736cSJeff Kirsher #define MICREL_KS884X 0x01 /* 0=Timeberdale(FPGA), 1=Micrel */
126bcc9736cSJeff Kirsher #define KS884X_16BIT 0x02 /* 1=16bit, 0=32bit */
127bcc9736cSJeff Kirsher
128bcc9736cSJeff Kirsher #define DMA_BUFFER_SIZE 2048
129bcc9736cSJeff Kirsher
130bcc9736cSJeff Kirsher struct ks8842_tx_dma_ctl {
131bcc9736cSJeff Kirsher struct dma_chan *chan;
132bcc9736cSJeff Kirsher struct dma_async_tx_descriptor *adesc;
133bcc9736cSJeff Kirsher void *buf;
134bcc9736cSJeff Kirsher struct scatterlist sg;
135bcc9736cSJeff Kirsher int channel;
136bcc9736cSJeff Kirsher };
137bcc9736cSJeff Kirsher
138bcc9736cSJeff Kirsher struct ks8842_rx_dma_ctl {
139bcc9736cSJeff Kirsher struct dma_chan *chan;
140bcc9736cSJeff Kirsher struct dma_async_tx_descriptor *adesc;
141bcc9736cSJeff Kirsher struct sk_buff *skb;
142bcc9736cSJeff Kirsher struct scatterlist sg;
143bcc9736cSJeff Kirsher struct tasklet_struct tasklet;
144bcc9736cSJeff Kirsher int channel;
145bcc9736cSJeff Kirsher };
146bcc9736cSJeff Kirsher
147bcc9736cSJeff Kirsher #define KS8842_USE_DMA(adapter) (((adapter)->dma_tx.channel != -1) && \
148bcc9736cSJeff Kirsher ((adapter)->dma_rx.channel != -1))
149bcc9736cSJeff Kirsher
150bcc9736cSJeff Kirsher struct ks8842_adapter {
151bcc9736cSJeff Kirsher void __iomem *hw_addr;
152bcc9736cSJeff Kirsher int irq;
153bcc9736cSJeff Kirsher unsigned long conf_flags; /* copy of platform_device config */
154bcc9736cSJeff Kirsher struct tasklet_struct tasklet;
155bcc9736cSJeff Kirsher spinlock_t lock; /* spinlock to be interrupt safe */
156bcc9736cSJeff Kirsher struct work_struct timeout_work;
157bcc9736cSJeff Kirsher struct net_device *netdev;
158bcc9736cSJeff Kirsher struct device *dev;
159bcc9736cSJeff Kirsher struct ks8842_tx_dma_ctl dma_tx;
160bcc9736cSJeff Kirsher struct ks8842_rx_dma_ctl dma_rx;
161bcc9736cSJeff Kirsher };
162bcc9736cSJeff Kirsher
163bcc9736cSJeff Kirsher static void ks8842_dma_rx_cb(void *data);
164bcc9736cSJeff Kirsher static void ks8842_dma_tx_cb(void *data);
165bcc9736cSJeff Kirsher
ks8842_resume_dma(struct ks8842_adapter * adapter)166bcc9736cSJeff Kirsher static inline void ks8842_resume_dma(struct ks8842_adapter *adapter)
167bcc9736cSJeff Kirsher {
168bcc9736cSJeff Kirsher iowrite32(1, adapter->hw_addr + REQ_TIMB_DMA_RESUME);
169bcc9736cSJeff Kirsher }
170bcc9736cSJeff Kirsher
ks8842_select_bank(struct ks8842_adapter * adapter,u16 bank)171bcc9736cSJeff Kirsher static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank)
172bcc9736cSJeff Kirsher {
173bcc9736cSJeff Kirsher iowrite16(bank, adapter->hw_addr + REG_SELECT_BANK);
174bcc9736cSJeff Kirsher }
175bcc9736cSJeff Kirsher
ks8842_write8(struct ks8842_adapter * adapter,u16 bank,u8 value,int offset)176bcc9736cSJeff Kirsher static inline void ks8842_write8(struct ks8842_adapter *adapter, u16 bank,
177bcc9736cSJeff Kirsher u8 value, int offset)
178bcc9736cSJeff Kirsher {
179bcc9736cSJeff Kirsher ks8842_select_bank(adapter, bank);
180bcc9736cSJeff Kirsher iowrite8(value, adapter->hw_addr + offset);
181bcc9736cSJeff Kirsher }
182bcc9736cSJeff Kirsher
ks8842_write16(struct ks8842_adapter * adapter,u16 bank,u16 value,int offset)183bcc9736cSJeff Kirsher static inline void ks8842_write16(struct ks8842_adapter *adapter, u16 bank,
184bcc9736cSJeff Kirsher u16 value, int offset)
185bcc9736cSJeff Kirsher {
186bcc9736cSJeff Kirsher ks8842_select_bank(adapter, bank);
187bcc9736cSJeff Kirsher iowrite16(value, adapter->hw_addr + offset);
188bcc9736cSJeff Kirsher }
189bcc9736cSJeff Kirsher
ks8842_enable_bits(struct ks8842_adapter * adapter,u16 bank,u16 bits,int offset)190bcc9736cSJeff Kirsher static inline void ks8842_enable_bits(struct ks8842_adapter *adapter, u16 bank,
191bcc9736cSJeff Kirsher u16 bits, int offset)
192bcc9736cSJeff Kirsher {
193bcc9736cSJeff Kirsher u16 reg;
194bcc9736cSJeff Kirsher ks8842_select_bank(adapter, bank);
195bcc9736cSJeff Kirsher reg = ioread16(adapter->hw_addr + offset);
196bcc9736cSJeff Kirsher reg |= bits;
197bcc9736cSJeff Kirsher iowrite16(reg, adapter->hw_addr + offset);
198bcc9736cSJeff Kirsher }
199bcc9736cSJeff Kirsher
ks8842_clear_bits(struct ks8842_adapter * adapter,u16 bank,u16 bits,int offset)200bcc9736cSJeff Kirsher static inline void ks8842_clear_bits(struct ks8842_adapter *adapter, u16 bank,
201bcc9736cSJeff Kirsher u16 bits, int offset)
202bcc9736cSJeff Kirsher {
203bcc9736cSJeff Kirsher u16 reg;
204bcc9736cSJeff Kirsher ks8842_select_bank(adapter, bank);
205bcc9736cSJeff Kirsher reg = ioread16(adapter->hw_addr + offset);
206bcc9736cSJeff Kirsher reg &= ~bits;
207bcc9736cSJeff Kirsher iowrite16(reg, adapter->hw_addr + offset);
208bcc9736cSJeff Kirsher }
209bcc9736cSJeff Kirsher
ks8842_write32(struct ks8842_adapter * adapter,u16 bank,u32 value,int offset)210bcc9736cSJeff Kirsher static inline void ks8842_write32(struct ks8842_adapter *adapter, u16 bank,
211bcc9736cSJeff Kirsher u32 value, int offset)
212bcc9736cSJeff Kirsher {
213bcc9736cSJeff Kirsher ks8842_select_bank(adapter, bank);
214bcc9736cSJeff Kirsher iowrite32(value, adapter->hw_addr + offset);
215bcc9736cSJeff Kirsher }
216bcc9736cSJeff Kirsher
ks8842_read8(struct ks8842_adapter * adapter,u16 bank,int offset)217bcc9736cSJeff Kirsher static inline u8 ks8842_read8(struct ks8842_adapter *adapter, u16 bank,
218bcc9736cSJeff Kirsher int offset)
219bcc9736cSJeff Kirsher {
220bcc9736cSJeff Kirsher ks8842_select_bank(adapter, bank);
221bcc9736cSJeff Kirsher return ioread8(adapter->hw_addr + offset);
222bcc9736cSJeff Kirsher }
223bcc9736cSJeff Kirsher
ks8842_read16(struct ks8842_adapter * adapter,u16 bank,int offset)224bcc9736cSJeff Kirsher static inline u16 ks8842_read16(struct ks8842_adapter *adapter, u16 bank,
225bcc9736cSJeff Kirsher int offset)
226bcc9736cSJeff Kirsher {
227bcc9736cSJeff Kirsher ks8842_select_bank(adapter, bank);
228bcc9736cSJeff Kirsher return ioread16(adapter->hw_addr + offset);
229bcc9736cSJeff Kirsher }
230bcc9736cSJeff Kirsher
ks8842_read32(struct ks8842_adapter * adapter,u16 bank,int offset)231bcc9736cSJeff Kirsher static inline u32 ks8842_read32(struct ks8842_adapter *adapter, u16 bank,
232bcc9736cSJeff Kirsher int offset)
233bcc9736cSJeff Kirsher {
234bcc9736cSJeff Kirsher ks8842_select_bank(adapter, bank);
235bcc9736cSJeff Kirsher return ioread32(adapter->hw_addr + offset);
236bcc9736cSJeff Kirsher }
237bcc9736cSJeff Kirsher
ks8842_reset(struct ks8842_adapter * adapter)238bcc9736cSJeff Kirsher static void ks8842_reset(struct ks8842_adapter *adapter)
239bcc9736cSJeff Kirsher {
240bcc9736cSJeff Kirsher if (adapter->conf_flags & MICREL_KS884X) {
241bcc9736cSJeff Kirsher ks8842_write16(adapter, 3, 1, REG_GRR);
242bcc9736cSJeff Kirsher msleep(10);
243bcc9736cSJeff Kirsher iowrite16(0, adapter->hw_addr + REG_GRR);
244bcc9736cSJeff Kirsher } else {
245bcc9736cSJeff Kirsher /* The KS8842 goes haywire when doing softare reset
246bcc9736cSJeff Kirsher * a work around in the timberdale IP is implemented to
247bcc9736cSJeff Kirsher * do a hardware reset instead
248bcc9736cSJeff Kirsher ks8842_write16(adapter, 3, 1, REG_GRR);
249bcc9736cSJeff Kirsher msleep(10);
250bcc9736cSJeff Kirsher iowrite16(0, adapter->hw_addr + REG_GRR);
251bcc9736cSJeff Kirsher */
252bcc9736cSJeff Kirsher iowrite32(0x1, adapter->hw_addr + REG_TIMB_RST);
253bcc9736cSJeff Kirsher msleep(20);
254bcc9736cSJeff Kirsher }
255bcc9736cSJeff Kirsher }
256bcc9736cSJeff Kirsher
ks8842_update_link_status(struct net_device * netdev,struct ks8842_adapter * adapter)257bcc9736cSJeff Kirsher static void ks8842_update_link_status(struct net_device *netdev,
258bcc9736cSJeff Kirsher struct ks8842_adapter *adapter)
259bcc9736cSJeff Kirsher {
260bcc9736cSJeff Kirsher /* check the status of the link */
261bcc9736cSJeff Kirsher if (ks8842_read16(adapter, 45, REG_P1MBSR) & 0x4) {
262bcc9736cSJeff Kirsher netif_carrier_on(netdev);
263bcc9736cSJeff Kirsher netif_wake_queue(netdev);
264bcc9736cSJeff Kirsher } else {
265bcc9736cSJeff Kirsher netif_stop_queue(netdev);
266bcc9736cSJeff Kirsher netif_carrier_off(netdev);
267bcc9736cSJeff Kirsher }
268bcc9736cSJeff Kirsher }
269bcc9736cSJeff Kirsher
ks8842_enable_tx(struct ks8842_adapter * adapter)270bcc9736cSJeff Kirsher static void ks8842_enable_tx(struct ks8842_adapter *adapter)
271bcc9736cSJeff Kirsher {
272bcc9736cSJeff Kirsher ks8842_enable_bits(adapter, 16, 0x01, REG_TXCR);
273bcc9736cSJeff Kirsher }
274bcc9736cSJeff Kirsher
ks8842_disable_tx(struct ks8842_adapter * adapter)275bcc9736cSJeff Kirsher static void ks8842_disable_tx(struct ks8842_adapter *adapter)
276bcc9736cSJeff Kirsher {
277bcc9736cSJeff Kirsher ks8842_clear_bits(adapter, 16, 0x01, REG_TXCR);
278bcc9736cSJeff Kirsher }
279bcc9736cSJeff Kirsher
ks8842_enable_rx(struct ks8842_adapter * adapter)280bcc9736cSJeff Kirsher static void ks8842_enable_rx(struct ks8842_adapter *adapter)
281bcc9736cSJeff Kirsher {
282bcc9736cSJeff Kirsher ks8842_enable_bits(adapter, 16, 0x01, REG_RXCR);
283bcc9736cSJeff Kirsher }
284bcc9736cSJeff Kirsher
ks8842_disable_rx(struct ks8842_adapter * adapter)285bcc9736cSJeff Kirsher static void ks8842_disable_rx(struct ks8842_adapter *adapter)
286bcc9736cSJeff Kirsher {
287bcc9736cSJeff Kirsher ks8842_clear_bits(adapter, 16, 0x01, REG_RXCR);
288bcc9736cSJeff Kirsher }
289bcc9736cSJeff Kirsher
ks8842_reset_hw(struct ks8842_adapter * adapter)290bcc9736cSJeff Kirsher static void ks8842_reset_hw(struct ks8842_adapter *adapter)
291bcc9736cSJeff Kirsher {
292bcc9736cSJeff Kirsher /* reset the HW */
293bcc9736cSJeff Kirsher ks8842_reset(adapter);
294bcc9736cSJeff Kirsher
295bcc9736cSJeff Kirsher /* Enable QMU Transmit flow control / transmit padding / Transmit CRC */
296bcc9736cSJeff Kirsher ks8842_write16(adapter, 16, 0x000E, REG_TXCR);
297bcc9736cSJeff Kirsher
298bcc9736cSJeff Kirsher /* enable the receiver, uni + multi + broadcast + flow ctrl
299bcc9736cSJeff Kirsher + crc strip */
300bcc9736cSJeff Kirsher ks8842_write16(adapter, 16, 0x8 | 0x20 | 0x40 | 0x80 | 0x400,
301bcc9736cSJeff Kirsher REG_RXCR);
302bcc9736cSJeff Kirsher
303bcc9736cSJeff Kirsher /* TX frame pointer autoincrement */
304bcc9736cSJeff Kirsher ks8842_write16(adapter, 17, 0x4000, REG_TXFDPR);
305bcc9736cSJeff Kirsher
306bcc9736cSJeff Kirsher /* RX frame pointer autoincrement */
307bcc9736cSJeff Kirsher ks8842_write16(adapter, 17, 0x4000, REG_RXFDPR);
308bcc9736cSJeff Kirsher
309bcc9736cSJeff Kirsher /* RX 2 kb high watermark */
310bcc9736cSJeff Kirsher ks8842_write16(adapter, 0, 0x1000, REG_QRFCR);
311bcc9736cSJeff Kirsher
312bcc9736cSJeff Kirsher /* aggressive back off in half duplex */
313bcc9736cSJeff Kirsher ks8842_enable_bits(adapter, 32, 1 << 8, REG_SGCR1);
314bcc9736cSJeff Kirsher
315bcc9736cSJeff Kirsher /* enable no excessive collison drop */
316bcc9736cSJeff Kirsher ks8842_enable_bits(adapter, 32, 1 << 3, REG_SGCR2);
317bcc9736cSJeff Kirsher
318bcc9736cSJeff Kirsher /* Enable port 1 force flow control / back pressure / transmit / recv */
319bcc9736cSJeff Kirsher ks8842_write16(adapter, 48, 0x1E07, REG_P1CR2);
320bcc9736cSJeff Kirsher
321bcc9736cSJeff Kirsher /* restart port auto-negotiation */
322bcc9736cSJeff Kirsher ks8842_enable_bits(adapter, 49, 1 << 13, REG_P1CR4);
323bcc9736cSJeff Kirsher
324bcc9736cSJeff Kirsher /* Enable the transmitter */
325bcc9736cSJeff Kirsher ks8842_enable_tx(adapter);
326bcc9736cSJeff Kirsher
327bcc9736cSJeff Kirsher /* Enable the receiver */
328bcc9736cSJeff Kirsher ks8842_enable_rx(adapter);
329bcc9736cSJeff Kirsher
330bcc9736cSJeff Kirsher /* clear all interrupts */
331bcc9736cSJeff Kirsher ks8842_write16(adapter, 18, 0xffff, REG_ISR);
332bcc9736cSJeff Kirsher
333bcc9736cSJeff Kirsher /* enable interrupts */
334bcc9736cSJeff Kirsher if (KS8842_USE_DMA(adapter)) {
335bcc9736cSJeff Kirsher /* When running in DMA Mode the RX interrupt is not enabled in
336bcc9736cSJeff Kirsher timberdale because RX data is received by DMA callbacks
337bcc9736cSJeff Kirsher it must still be enabled in the KS8842 because it indicates
338bcc9736cSJeff Kirsher to timberdale when there is RX data for it's DMA FIFOs */
339bcc9736cSJeff Kirsher iowrite16(ENABLED_IRQS_DMA_IP, adapter->hw_addr + REG_TIMB_IER);
340bcc9736cSJeff Kirsher ks8842_write16(adapter, 18, ENABLED_IRQS_DMA, REG_IER);
341bcc9736cSJeff Kirsher } else {
342bcc9736cSJeff Kirsher if (!(adapter->conf_flags & MICREL_KS884X))
343bcc9736cSJeff Kirsher iowrite16(ENABLED_IRQS,
344bcc9736cSJeff Kirsher adapter->hw_addr + REG_TIMB_IER);
345bcc9736cSJeff Kirsher ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER);
346bcc9736cSJeff Kirsher }
347bcc9736cSJeff Kirsher /* enable the switch */
348bcc9736cSJeff Kirsher ks8842_write16(adapter, 32, 0x1, REG_SW_ID_AND_ENABLE);
349bcc9736cSJeff Kirsher }
350bcc9736cSJeff Kirsher
ks8842_init_mac_addr(struct ks8842_adapter * adapter)351*4abd7cffSJakub Kicinski static void ks8842_init_mac_addr(struct ks8842_adapter *adapter)
352bcc9736cSJeff Kirsher {
353*4abd7cffSJakub Kicinski u8 addr[ETH_ALEN];
354bcc9736cSJeff Kirsher int i;
355bcc9736cSJeff Kirsher u16 mac;
356bcc9736cSJeff Kirsher
357bcc9736cSJeff Kirsher for (i = 0; i < ETH_ALEN; i++)
358*4abd7cffSJakub Kicinski addr[ETH_ALEN - i - 1] = ks8842_read8(adapter, 2, REG_MARL + i);
359*4abd7cffSJakub Kicinski eth_hw_addr_set(adapter->netdev, addr);
360bcc9736cSJeff Kirsher
361bcc9736cSJeff Kirsher if (adapter->conf_flags & MICREL_KS884X) {
362bcc9736cSJeff Kirsher /*
363bcc9736cSJeff Kirsher the sequence of saving mac addr between MAC and Switch is
364bcc9736cSJeff Kirsher different.
365bcc9736cSJeff Kirsher */
366bcc9736cSJeff Kirsher
367bcc9736cSJeff Kirsher mac = ks8842_read16(adapter, 2, REG_MARL);
368bcc9736cSJeff Kirsher ks8842_write16(adapter, 39, mac, REG_MACAR3);
369bcc9736cSJeff Kirsher mac = ks8842_read16(adapter, 2, REG_MARM);
370bcc9736cSJeff Kirsher ks8842_write16(adapter, 39, mac, REG_MACAR2);
371bcc9736cSJeff Kirsher mac = ks8842_read16(adapter, 2, REG_MARH);
372bcc9736cSJeff Kirsher ks8842_write16(adapter, 39, mac, REG_MACAR1);
373bcc9736cSJeff Kirsher } else {
374bcc9736cSJeff Kirsher
375bcc9736cSJeff Kirsher /* make sure the switch port uses the same MAC as the QMU */
376bcc9736cSJeff Kirsher mac = ks8842_read16(adapter, 2, REG_MARL);
377bcc9736cSJeff Kirsher ks8842_write16(adapter, 39, mac, REG_MACAR1);
378bcc9736cSJeff Kirsher mac = ks8842_read16(adapter, 2, REG_MARM);
379bcc9736cSJeff Kirsher ks8842_write16(adapter, 39, mac, REG_MACAR2);
380bcc9736cSJeff Kirsher mac = ks8842_read16(adapter, 2, REG_MARH);
381bcc9736cSJeff Kirsher ks8842_write16(adapter, 39, mac, REG_MACAR3);
382bcc9736cSJeff Kirsher }
383bcc9736cSJeff Kirsher }
384bcc9736cSJeff Kirsher
ks8842_write_mac_addr(struct ks8842_adapter * adapter,const u8 * mac)38576660757SJakub Kicinski static void ks8842_write_mac_addr(struct ks8842_adapter *adapter, const u8 *mac)
386bcc9736cSJeff Kirsher {
387bcc9736cSJeff Kirsher unsigned long flags;
388bcc9736cSJeff Kirsher unsigned i;
389bcc9736cSJeff Kirsher
390bcc9736cSJeff Kirsher spin_lock_irqsave(&adapter->lock, flags);
391bcc9736cSJeff Kirsher for (i = 0; i < ETH_ALEN; i++) {
392bcc9736cSJeff Kirsher ks8842_write8(adapter, 2, mac[ETH_ALEN - i - 1], REG_MARL + i);
393bcc9736cSJeff Kirsher if (!(adapter->conf_flags & MICREL_KS884X))
394bcc9736cSJeff Kirsher ks8842_write8(adapter, 39, mac[ETH_ALEN - i - 1],
395bcc9736cSJeff Kirsher REG_MACAR1 + i);
396bcc9736cSJeff Kirsher }
397bcc9736cSJeff Kirsher
398bcc9736cSJeff Kirsher if (adapter->conf_flags & MICREL_KS884X) {
399bcc9736cSJeff Kirsher /*
400bcc9736cSJeff Kirsher the sequence of saving mac addr between MAC and Switch is
401bcc9736cSJeff Kirsher different.
402bcc9736cSJeff Kirsher */
403bcc9736cSJeff Kirsher
404bcc9736cSJeff Kirsher u16 mac;
405bcc9736cSJeff Kirsher
406bcc9736cSJeff Kirsher mac = ks8842_read16(adapter, 2, REG_MARL);
407bcc9736cSJeff Kirsher ks8842_write16(adapter, 39, mac, REG_MACAR3);
408bcc9736cSJeff Kirsher mac = ks8842_read16(adapter, 2, REG_MARM);
409bcc9736cSJeff Kirsher ks8842_write16(adapter, 39, mac, REG_MACAR2);
410bcc9736cSJeff Kirsher mac = ks8842_read16(adapter, 2, REG_MARH);
411bcc9736cSJeff Kirsher ks8842_write16(adapter, 39, mac, REG_MACAR1);
412bcc9736cSJeff Kirsher }
413bcc9736cSJeff Kirsher spin_unlock_irqrestore(&adapter->lock, flags);
414bcc9736cSJeff Kirsher }
415bcc9736cSJeff Kirsher
ks8842_tx_fifo_space(struct ks8842_adapter * adapter)416bcc9736cSJeff Kirsher static inline u16 ks8842_tx_fifo_space(struct ks8842_adapter *adapter)
417bcc9736cSJeff Kirsher {
418bcc9736cSJeff Kirsher return ks8842_read16(adapter, 16, REG_TXMIR) & 0x1fff;
419bcc9736cSJeff Kirsher }
420bcc9736cSJeff Kirsher
ks8842_tx_frame_dma(struct sk_buff * skb,struct net_device * netdev)421bcc9736cSJeff Kirsher static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev)
422bcc9736cSJeff Kirsher {
423bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
424bcc9736cSJeff Kirsher struct ks8842_tx_dma_ctl *ctl = &adapter->dma_tx;
425bcc9736cSJeff Kirsher u8 *buf = ctl->buf;
426bcc9736cSJeff Kirsher
427bcc9736cSJeff Kirsher if (ctl->adesc) {
428bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s: TX ongoing\n", __func__);
429bcc9736cSJeff Kirsher /* transfer ongoing */
430bcc9736cSJeff Kirsher return NETDEV_TX_BUSY;
431bcc9736cSJeff Kirsher }
432bcc9736cSJeff Kirsher
433bcc9736cSJeff Kirsher sg_dma_len(&ctl->sg) = skb->len + sizeof(u32);
434bcc9736cSJeff Kirsher
435bcc9736cSJeff Kirsher /* copy data to the TX buffer */
436bcc9736cSJeff Kirsher /* the control word, enable IRQ, port 1 and the length */
437bcc9736cSJeff Kirsher *buf++ = 0x00;
438bcc9736cSJeff Kirsher *buf++ = 0x01; /* Port 1 */
439bcc9736cSJeff Kirsher *buf++ = skb->len & 0xff;
440bcc9736cSJeff Kirsher *buf++ = (skb->len >> 8) & 0xff;
441bcc9736cSJeff Kirsher skb_copy_from_linear_data(skb, buf, skb->len);
442bcc9736cSJeff Kirsher
443bcc9736cSJeff Kirsher dma_sync_single_range_for_device(adapter->dev,
444bcc9736cSJeff Kirsher sg_dma_address(&ctl->sg), 0, sg_dma_len(&ctl->sg),
445bcc9736cSJeff Kirsher DMA_TO_DEVICE);
446bcc9736cSJeff Kirsher
447bcc9736cSJeff Kirsher /* make sure the length is a multiple of 4 */
448bcc9736cSJeff Kirsher if (sg_dma_len(&ctl->sg) % 4)
449bcc9736cSJeff Kirsher sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4;
450bcc9736cSJeff Kirsher
45116052827SAlexandre Bounine ctl->adesc = dmaengine_prep_slave_sg(ctl->chan,
4520776ae7bSBartlomiej Zolnierkiewicz &ctl->sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
453bcc9736cSJeff Kirsher if (!ctl->adesc)
454bcc9736cSJeff Kirsher return NETDEV_TX_BUSY;
455bcc9736cSJeff Kirsher
456bcc9736cSJeff Kirsher ctl->adesc->callback_param = netdev;
457bcc9736cSJeff Kirsher ctl->adesc->callback = ks8842_dma_tx_cb;
458bcc9736cSJeff Kirsher ctl->adesc->tx_submit(ctl->adesc);
459bcc9736cSJeff Kirsher
460bcc9736cSJeff Kirsher netdev->stats.tx_bytes += skb->len;
461bcc9736cSJeff Kirsher
462bcc9736cSJeff Kirsher dev_kfree_skb(skb);
463bcc9736cSJeff Kirsher
464bcc9736cSJeff Kirsher return NETDEV_TX_OK;
465bcc9736cSJeff Kirsher }
466bcc9736cSJeff Kirsher
ks8842_tx_frame(struct sk_buff * skb,struct net_device * netdev)467bcc9736cSJeff Kirsher static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
468bcc9736cSJeff Kirsher {
469bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
470bcc9736cSJeff Kirsher int len = skb->len;
471bcc9736cSJeff Kirsher
472bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s: len %u head %p data %p tail %p end %p\n",
473bcc9736cSJeff Kirsher __func__, skb->len, skb->head, skb->data,
474bcc9736cSJeff Kirsher skb_tail_pointer(skb), skb_end_pointer(skb));
475bcc9736cSJeff Kirsher
476bcc9736cSJeff Kirsher /* check FIFO buffer space, we need space for CRC and command bits */
477bcc9736cSJeff Kirsher if (ks8842_tx_fifo_space(adapter) < len + 8)
478bcc9736cSJeff Kirsher return NETDEV_TX_BUSY;
479bcc9736cSJeff Kirsher
480bcc9736cSJeff Kirsher if (adapter->conf_flags & KS884X_16BIT) {
481bcc9736cSJeff Kirsher u16 *ptr16 = (u16 *)skb->data;
482bcc9736cSJeff Kirsher ks8842_write16(adapter, 17, 0x8000 | 0x100, REG_QMU_DATA_LO);
483bcc9736cSJeff Kirsher ks8842_write16(adapter, 17, (u16)len, REG_QMU_DATA_HI);
484bcc9736cSJeff Kirsher netdev->stats.tx_bytes += len;
485bcc9736cSJeff Kirsher
486bcc9736cSJeff Kirsher /* copy buffer */
487bcc9736cSJeff Kirsher while (len > 0) {
488bcc9736cSJeff Kirsher iowrite16(*ptr16++, adapter->hw_addr + REG_QMU_DATA_LO);
489bcc9736cSJeff Kirsher iowrite16(*ptr16++, adapter->hw_addr + REG_QMU_DATA_HI);
490bcc9736cSJeff Kirsher len -= sizeof(u32);
491bcc9736cSJeff Kirsher }
492bcc9736cSJeff Kirsher } else {
493bcc9736cSJeff Kirsher
494bcc9736cSJeff Kirsher u32 *ptr = (u32 *)skb->data;
495bcc9736cSJeff Kirsher u32 ctrl;
496bcc9736cSJeff Kirsher /* the control word, enable IRQ, port 1 and the length */
497bcc9736cSJeff Kirsher ctrl = 0x8000 | 0x100 | (len << 16);
498bcc9736cSJeff Kirsher ks8842_write32(adapter, 17, ctrl, REG_QMU_DATA_LO);
499bcc9736cSJeff Kirsher
500bcc9736cSJeff Kirsher netdev->stats.tx_bytes += len;
501bcc9736cSJeff Kirsher
502bcc9736cSJeff Kirsher /* copy buffer */
503bcc9736cSJeff Kirsher while (len > 0) {
504bcc9736cSJeff Kirsher iowrite32(*ptr, adapter->hw_addr + REG_QMU_DATA_LO);
505bcc9736cSJeff Kirsher len -= sizeof(u32);
506bcc9736cSJeff Kirsher ptr++;
507bcc9736cSJeff Kirsher }
508bcc9736cSJeff Kirsher }
509bcc9736cSJeff Kirsher
510bcc9736cSJeff Kirsher /* enqueue packet */
511bcc9736cSJeff Kirsher ks8842_write16(adapter, 17, 1, REG_TXQCR);
512bcc9736cSJeff Kirsher
513bcc9736cSJeff Kirsher dev_kfree_skb(skb);
514bcc9736cSJeff Kirsher
515bcc9736cSJeff Kirsher return NETDEV_TX_OK;
516bcc9736cSJeff Kirsher }
517bcc9736cSJeff Kirsher
ks8842_update_rx_err_counters(struct net_device * netdev,u32 status)518bcc9736cSJeff Kirsher static void ks8842_update_rx_err_counters(struct net_device *netdev, u32 status)
519bcc9736cSJeff Kirsher {
520bcc9736cSJeff Kirsher netdev_dbg(netdev, "RX error, status: %x\n", status);
521bcc9736cSJeff Kirsher
522bcc9736cSJeff Kirsher netdev->stats.rx_errors++;
523bcc9736cSJeff Kirsher if (status & RXSR_TOO_LONG)
524bcc9736cSJeff Kirsher netdev->stats.rx_length_errors++;
525bcc9736cSJeff Kirsher if (status & RXSR_CRC_ERROR)
526bcc9736cSJeff Kirsher netdev->stats.rx_crc_errors++;
527bcc9736cSJeff Kirsher if (status & RXSR_RUNT)
528bcc9736cSJeff Kirsher netdev->stats.rx_frame_errors++;
529bcc9736cSJeff Kirsher }
530bcc9736cSJeff Kirsher
ks8842_update_rx_counters(struct net_device * netdev,u32 status,int len)531bcc9736cSJeff Kirsher static void ks8842_update_rx_counters(struct net_device *netdev, u32 status,
532bcc9736cSJeff Kirsher int len)
533bcc9736cSJeff Kirsher {
534bcc9736cSJeff Kirsher netdev_dbg(netdev, "RX packet, len: %d\n", len);
535bcc9736cSJeff Kirsher
536bcc9736cSJeff Kirsher netdev->stats.rx_packets++;
537bcc9736cSJeff Kirsher netdev->stats.rx_bytes += len;
538bcc9736cSJeff Kirsher if (status & RXSR_MULTICAST)
539bcc9736cSJeff Kirsher netdev->stats.multicast++;
540bcc9736cSJeff Kirsher }
541bcc9736cSJeff Kirsher
__ks8842_start_new_rx_dma(struct net_device * netdev)542bcc9736cSJeff Kirsher static int __ks8842_start_new_rx_dma(struct net_device *netdev)
543bcc9736cSJeff Kirsher {
544bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
545bcc9736cSJeff Kirsher struct ks8842_rx_dma_ctl *ctl = &adapter->dma_rx;
546bcc9736cSJeff Kirsher struct scatterlist *sg = &ctl->sg;
547bcc9736cSJeff Kirsher int err;
548bcc9736cSJeff Kirsher
549bcc9736cSJeff Kirsher ctl->skb = netdev_alloc_skb(netdev, DMA_BUFFER_SIZE);
550bcc9736cSJeff Kirsher if (ctl->skb) {
551bcc9736cSJeff Kirsher sg_init_table(sg, 1);
552bcc9736cSJeff Kirsher sg_dma_address(sg) = dma_map_single(adapter->dev,
553bcc9736cSJeff Kirsher ctl->skb->data, DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
5543af0d554SDan Carpenter if (dma_mapping_error(adapter->dev, sg_dma_address(sg))) {
5553af0d554SDan Carpenter err = -ENOMEM;
556bcc9736cSJeff Kirsher sg_dma_address(sg) = 0;
557bcc9736cSJeff Kirsher goto out;
558bcc9736cSJeff Kirsher }
559bcc9736cSJeff Kirsher
560bcc9736cSJeff Kirsher sg_dma_len(sg) = DMA_BUFFER_SIZE;
561bcc9736cSJeff Kirsher
56216052827SAlexandre Bounine ctl->adesc = dmaengine_prep_slave_sg(ctl->chan,
5630776ae7bSBartlomiej Zolnierkiewicz sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
564bcc9736cSJeff Kirsher
5653af0d554SDan Carpenter if (!ctl->adesc) {
5663af0d554SDan Carpenter err = -ENOMEM;
567bcc9736cSJeff Kirsher goto out;
5683af0d554SDan Carpenter }
569bcc9736cSJeff Kirsher
570bcc9736cSJeff Kirsher ctl->adesc->callback_param = netdev;
571bcc9736cSJeff Kirsher ctl->adesc->callback = ks8842_dma_rx_cb;
572bcc9736cSJeff Kirsher ctl->adesc->tx_submit(ctl->adesc);
573bcc9736cSJeff Kirsher } else {
574bcc9736cSJeff Kirsher err = -ENOMEM;
575bcc9736cSJeff Kirsher sg_dma_address(sg) = 0;
576bcc9736cSJeff Kirsher goto out;
577bcc9736cSJeff Kirsher }
578bcc9736cSJeff Kirsher
5793af0d554SDan Carpenter return 0;
580bcc9736cSJeff Kirsher out:
581bcc9736cSJeff Kirsher if (sg_dma_address(sg))
582bcc9736cSJeff Kirsher dma_unmap_single(adapter->dev, sg_dma_address(sg),
583bcc9736cSJeff Kirsher DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
584bcc9736cSJeff Kirsher sg_dma_address(sg) = 0;
585bcc9736cSJeff Kirsher dev_kfree_skb(ctl->skb);
586bcc9736cSJeff Kirsher ctl->skb = NULL;
587bcc9736cSJeff Kirsher
588bcc9736cSJeff Kirsher printk(KERN_ERR DRV_NAME": Failed to start RX DMA: %d\n", err);
589bcc9736cSJeff Kirsher return err;
590bcc9736cSJeff Kirsher }
591bcc9736cSJeff Kirsher
ks8842_rx_frame_dma_tasklet(struct tasklet_struct * t)5929ad5a250SAllen Pais static void ks8842_rx_frame_dma_tasklet(struct tasklet_struct *t)
593bcc9736cSJeff Kirsher {
5949ad5a250SAllen Pais struct ks8842_adapter *adapter = from_tasklet(adapter, t, dma_rx.tasklet);
5959ad5a250SAllen Pais struct net_device *netdev = adapter->netdev;
596bcc9736cSJeff Kirsher struct ks8842_rx_dma_ctl *ctl = &adapter->dma_rx;
597bcc9736cSJeff Kirsher struct sk_buff *skb = ctl->skb;
598bcc9736cSJeff Kirsher dma_addr_t addr = sg_dma_address(&ctl->sg);
599bcc9736cSJeff Kirsher u32 status;
600bcc9736cSJeff Kirsher
601bcc9736cSJeff Kirsher ctl->adesc = NULL;
602bcc9736cSJeff Kirsher
603bcc9736cSJeff Kirsher /* kick next transfer going */
604bcc9736cSJeff Kirsher __ks8842_start_new_rx_dma(netdev);
605bcc9736cSJeff Kirsher
606bcc9736cSJeff Kirsher /* now handle the data we got */
607bcc9736cSJeff Kirsher dma_unmap_single(adapter->dev, addr, DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
608bcc9736cSJeff Kirsher
609bcc9736cSJeff Kirsher status = *((u32 *)skb->data);
610bcc9736cSJeff Kirsher
611bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s - rx_data: status: %x\n",
612bcc9736cSJeff Kirsher __func__, status & 0xffff);
613bcc9736cSJeff Kirsher
614bcc9736cSJeff Kirsher /* check the status */
615bcc9736cSJeff Kirsher if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) {
616bcc9736cSJeff Kirsher int len = (status >> 16) & 0x7ff;
617bcc9736cSJeff Kirsher
618bcc9736cSJeff Kirsher ks8842_update_rx_counters(netdev, status, len);
619bcc9736cSJeff Kirsher
620bcc9736cSJeff Kirsher /* reserve 4 bytes which is the status word */
621bcc9736cSJeff Kirsher skb_reserve(skb, 4);
622bcc9736cSJeff Kirsher skb_put(skb, len);
623bcc9736cSJeff Kirsher
624bcc9736cSJeff Kirsher skb->protocol = eth_type_trans(skb, netdev);
625bcc9736cSJeff Kirsher netif_rx(skb);
626bcc9736cSJeff Kirsher } else {
627bcc9736cSJeff Kirsher ks8842_update_rx_err_counters(netdev, status);
628bcc9736cSJeff Kirsher dev_kfree_skb(skb);
629bcc9736cSJeff Kirsher }
630bcc9736cSJeff Kirsher }
631bcc9736cSJeff Kirsher
ks8842_rx_frame(struct net_device * netdev,struct ks8842_adapter * adapter)632bcc9736cSJeff Kirsher static void ks8842_rx_frame(struct net_device *netdev,
633bcc9736cSJeff Kirsher struct ks8842_adapter *adapter)
634bcc9736cSJeff Kirsher {
635bcc9736cSJeff Kirsher u32 status;
636bcc9736cSJeff Kirsher int len;
637bcc9736cSJeff Kirsher
638bcc9736cSJeff Kirsher if (adapter->conf_flags & KS884X_16BIT) {
639bcc9736cSJeff Kirsher status = ks8842_read16(adapter, 17, REG_QMU_DATA_LO);
640bcc9736cSJeff Kirsher len = ks8842_read16(adapter, 17, REG_QMU_DATA_HI);
641bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s - rx_data: status: %x\n",
642bcc9736cSJeff Kirsher __func__, status);
643bcc9736cSJeff Kirsher } else {
644bcc9736cSJeff Kirsher status = ks8842_read32(adapter, 17, REG_QMU_DATA_LO);
645bcc9736cSJeff Kirsher len = (status >> 16) & 0x7ff;
646bcc9736cSJeff Kirsher status &= 0xffff;
647bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s - rx_data: status: %x\n",
648bcc9736cSJeff Kirsher __func__, status);
649bcc9736cSJeff Kirsher }
650bcc9736cSJeff Kirsher
651bcc9736cSJeff Kirsher /* check the status */
652bcc9736cSJeff Kirsher if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) {
653bcc9736cSJeff Kirsher struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev, len + 3);
654bcc9736cSJeff Kirsher
655bcc9736cSJeff Kirsher if (skb) {
656bcc9736cSJeff Kirsher
657bcc9736cSJeff Kirsher ks8842_update_rx_counters(netdev, status, len);
658bcc9736cSJeff Kirsher
659bcc9736cSJeff Kirsher if (adapter->conf_flags & KS884X_16BIT) {
6604df864c1SJohannes Berg u16 *data16 = skb_put(skb, len);
661bcc9736cSJeff Kirsher ks8842_select_bank(adapter, 17);
662bcc9736cSJeff Kirsher while (len > 0) {
663bcc9736cSJeff Kirsher *data16++ = ioread16(adapter->hw_addr +
664bcc9736cSJeff Kirsher REG_QMU_DATA_LO);
665bcc9736cSJeff Kirsher *data16++ = ioread16(adapter->hw_addr +
666bcc9736cSJeff Kirsher REG_QMU_DATA_HI);
667bcc9736cSJeff Kirsher len -= sizeof(u32);
668bcc9736cSJeff Kirsher }
669bcc9736cSJeff Kirsher } else {
6704df864c1SJohannes Berg u32 *data = skb_put(skb, len);
671bcc9736cSJeff Kirsher
672bcc9736cSJeff Kirsher ks8842_select_bank(adapter, 17);
673bcc9736cSJeff Kirsher while (len > 0) {
674bcc9736cSJeff Kirsher *data++ = ioread32(adapter->hw_addr +
675bcc9736cSJeff Kirsher REG_QMU_DATA_LO);
676bcc9736cSJeff Kirsher len -= sizeof(u32);
677bcc9736cSJeff Kirsher }
678bcc9736cSJeff Kirsher }
679bcc9736cSJeff Kirsher skb->protocol = eth_type_trans(skb, netdev);
680bcc9736cSJeff Kirsher netif_rx(skb);
681bcc9736cSJeff Kirsher } else
682bcc9736cSJeff Kirsher netdev->stats.rx_dropped++;
683bcc9736cSJeff Kirsher } else
684bcc9736cSJeff Kirsher ks8842_update_rx_err_counters(netdev, status);
685bcc9736cSJeff Kirsher
686bcc9736cSJeff Kirsher /* set high watermark to 3K */
687bcc9736cSJeff Kirsher ks8842_clear_bits(adapter, 0, 1 << 12, REG_QRFCR);
688bcc9736cSJeff Kirsher
689bcc9736cSJeff Kirsher /* release the frame */
690bcc9736cSJeff Kirsher ks8842_write16(adapter, 17, 0x01, REG_RXQCR);
691bcc9736cSJeff Kirsher
692bcc9736cSJeff Kirsher /* set high watermark to 2K */
693bcc9736cSJeff Kirsher ks8842_enable_bits(adapter, 0, 1 << 12, REG_QRFCR);
694bcc9736cSJeff Kirsher }
695bcc9736cSJeff Kirsher
ks8842_handle_rx(struct net_device * netdev,struct ks8842_adapter * adapter)69651a700dbSJingoo Han static void ks8842_handle_rx(struct net_device *netdev,
69751a700dbSJingoo Han struct ks8842_adapter *adapter)
698bcc9736cSJeff Kirsher {
699bcc9736cSJeff Kirsher u16 rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff;
700bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s Entry - rx_data: %d\n", __func__, rx_data);
701bcc9736cSJeff Kirsher while (rx_data) {
702bcc9736cSJeff Kirsher ks8842_rx_frame(netdev, adapter);
703bcc9736cSJeff Kirsher rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff;
704bcc9736cSJeff Kirsher }
705bcc9736cSJeff Kirsher }
706bcc9736cSJeff Kirsher
ks8842_handle_tx(struct net_device * netdev,struct ks8842_adapter * adapter)70751a700dbSJingoo Han static void ks8842_handle_tx(struct net_device *netdev,
70851a700dbSJingoo Han struct ks8842_adapter *adapter)
709bcc9736cSJeff Kirsher {
710bcc9736cSJeff Kirsher u16 sr = ks8842_read16(adapter, 16, REG_TXSR);
711bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s - entry, sr: %x\n", __func__, sr);
712bcc9736cSJeff Kirsher netdev->stats.tx_packets++;
713bcc9736cSJeff Kirsher if (netif_queue_stopped(netdev))
714bcc9736cSJeff Kirsher netif_wake_queue(netdev);
715bcc9736cSJeff Kirsher }
716bcc9736cSJeff Kirsher
ks8842_handle_rx_overrun(struct net_device * netdev,struct ks8842_adapter * adapter)71751a700dbSJingoo Han static void ks8842_handle_rx_overrun(struct net_device *netdev,
718bcc9736cSJeff Kirsher struct ks8842_adapter *adapter)
719bcc9736cSJeff Kirsher {
720bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s: entry\n", __func__);
721bcc9736cSJeff Kirsher netdev->stats.rx_errors++;
722bcc9736cSJeff Kirsher netdev->stats.rx_fifo_errors++;
723bcc9736cSJeff Kirsher }
724bcc9736cSJeff Kirsher
ks8842_tasklet(struct tasklet_struct * t)7259ad5a250SAllen Pais static void ks8842_tasklet(struct tasklet_struct *t)
726bcc9736cSJeff Kirsher {
7279ad5a250SAllen Pais struct ks8842_adapter *adapter = from_tasklet(adapter, t, tasklet);
7289ad5a250SAllen Pais struct net_device *netdev = adapter->netdev;
729bcc9736cSJeff Kirsher u16 isr;
730bcc9736cSJeff Kirsher unsigned long flags;
731bcc9736cSJeff Kirsher u16 entry_bank;
732bcc9736cSJeff Kirsher
733bcc9736cSJeff Kirsher /* read current bank to be able to set it back */
734bcc9736cSJeff Kirsher spin_lock_irqsave(&adapter->lock, flags);
735bcc9736cSJeff Kirsher entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK);
736bcc9736cSJeff Kirsher spin_unlock_irqrestore(&adapter->lock, flags);
737bcc9736cSJeff Kirsher
738bcc9736cSJeff Kirsher isr = ks8842_read16(adapter, 18, REG_ISR);
739bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s - ISR: 0x%x\n", __func__, isr);
740bcc9736cSJeff Kirsher
741bcc9736cSJeff Kirsher /* when running in DMA mode, do not ack RX interrupts, it is handled
742bcc9736cSJeff Kirsher internally by timberdale, otherwise it's DMA FIFO:s would stop
743bcc9736cSJeff Kirsher */
744bcc9736cSJeff Kirsher if (KS8842_USE_DMA(adapter))
745bcc9736cSJeff Kirsher isr &= ~IRQ_RX;
746bcc9736cSJeff Kirsher
747bcc9736cSJeff Kirsher /* Ack */
748bcc9736cSJeff Kirsher ks8842_write16(adapter, 18, isr, REG_ISR);
749bcc9736cSJeff Kirsher
750bcc9736cSJeff Kirsher if (!(adapter->conf_flags & MICREL_KS884X))
751bcc9736cSJeff Kirsher /* Ack in the timberdale IP as well */
752bcc9736cSJeff Kirsher iowrite32(0x1, adapter->hw_addr + REG_TIMB_IAR);
753bcc9736cSJeff Kirsher
754bcc9736cSJeff Kirsher if (!netif_running(netdev))
755bcc9736cSJeff Kirsher return;
756bcc9736cSJeff Kirsher
757bcc9736cSJeff Kirsher if (isr & IRQ_LINK_CHANGE)
758bcc9736cSJeff Kirsher ks8842_update_link_status(netdev, adapter);
759bcc9736cSJeff Kirsher
760bcc9736cSJeff Kirsher /* should not get IRQ_RX when running DMA mode */
761bcc9736cSJeff Kirsher if (isr & (IRQ_RX | IRQ_RX_ERROR) && !KS8842_USE_DMA(adapter))
762bcc9736cSJeff Kirsher ks8842_handle_rx(netdev, adapter);
763bcc9736cSJeff Kirsher
764bcc9736cSJeff Kirsher /* should only happen when in PIO mode */
765bcc9736cSJeff Kirsher if (isr & IRQ_TX)
766bcc9736cSJeff Kirsher ks8842_handle_tx(netdev, adapter);
767bcc9736cSJeff Kirsher
768bcc9736cSJeff Kirsher if (isr & IRQ_RX_OVERRUN)
769bcc9736cSJeff Kirsher ks8842_handle_rx_overrun(netdev, adapter);
770bcc9736cSJeff Kirsher
771bcc9736cSJeff Kirsher if (isr & IRQ_TX_STOPPED) {
772bcc9736cSJeff Kirsher ks8842_disable_tx(adapter);
773bcc9736cSJeff Kirsher ks8842_enable_tx(adapter);
774bcc9736cSJeff Kirsher }
775bcc9736cSJeff Kirsher
776bcc9736cSJeff Kirsher if (isr & IRQ_RX_STOPPED) {
777bcc9736cSJeff Kirsher ks8842_disable_rx(adapter);
778bcc9736cSJeff Kirsher ks8842_enable_rx(adapter);
779bcc9736cSJeff Kirsher }
780bcc9736cSJeff Kirsher
781bcc9736cSJeff Kirsher /* re-enable interrupts, put back the bank selection register */
782bcc9736cSJeff Kirsher spin_lock_irqsave(&adapter->lock, flags);
783bcc9736cSJeff Kirsher if (KS8842_USE_DMA(adapter))
784bcc9736cSJeff Kirsher ks8842_write16(adapter, 18, ENABLED_IRQS_DMA, REG_IER);
785bcc9736cSJeff Kirsher else
786bcc9736cSJeff Kirsher ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER);
787bcc9736cSJeff Kirsher iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK);
788bcc9736cSJeff Kirsher
789bcc9736cSJeff Kirsher /* Make sure timberdale continues DMA operations, they are stopped while
790bcc9736cSJeff Kirsher we are handling the ks8842 because we might change bank */
791bcc9736cSJeff Kirsher if (KS8842_USE_DMA(adapter))
792bcc9736cSJeff Kirsher ks8842_resume_dma(adapter);
793bcc9736cSJeff Kirsher
794bcc9736cSJeff Kirsher spin_unlock_irqrestore(&adapter->lock, flags);
795bcc9736cSJeff Kirsher }
796bcc9736cSJeff Kirsher
ks8842_irq(int irq,void * devid)797bcc9736cSJeff Kirsher static irqreturn_t ks8842_irq(int irq, void *devid)
798bcc9736cSJeff Kirsher {
799bcc9736cSJeff Kirsher struct net_device *netdev = devid;
800bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
801bcc9736cSJeff Kirsher u16 isr;
802bcc9736cSJeff Kirsher u16 entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK);
803bcc9736cSJeff Kirsher irqreturn_t ret = IRQ_NONE;
804bcc9736cSJeff Kirsher
805bcc9736cSJeff Kirsher isr = ks8842_read16(adapter, 18, REG_ISR);
806bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s - ISR: 0x%x\n", __func__, isr);
807bcc9736cSJeff Kirsher
808bcc9736cSJeff Kirsher if (isr) {
809bcc9736cSJeff Kirsher if (KS8842_USE_DMA(adapter))
810bcc9736cSJeff Kirsher /* disable all but RX IRQ, since the FPGA relies on it*/
811bcc9736cSJeff Kirsher ks8842_write16(adapter, 18, IRQ_RX, REG_IER);
812bcc9736cSJeff Kirsher else
813bcc9736cSJeff Kirsher /* disable IRQ */
814bcc9736cSJeff Kirsher ks8842_write16(adapter, 18, 0x00, REG_IER);
815bcc9736cSJeff Kirsher
816bcc9736cSJeff Kirsher /* schedule tasklet */
817bcc9736cSJeff Kirsher tasklet_schedule(&adapter->tasklet);
818bcc9736cSJeff Kirsher
819bcc9736cSJeff Kirsher ret = IRQ_HANDLED;
820bcc9736cSJeff Kirsher }
821bcc9736cSJeff Kirsher
822bcc9736cSJeff Kirsher iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK);
823bcc9736cSJeff Kirsher
824bcc9736cSJeff Kirsher /* After an interrupt, tell timberdale to continue DMA operations.
825bcc9736cSJeff Kirsher DMA is disabled while we are handling the ks8842 because we might
826bcc9736cSJeff Kirsher change bank */
827bcc9736cSJeff Kirsher ks8842_resume_dma(adapter);
828bcc9736cSJeff Kirsher
829bcc9736cSJeff Kirsher return ret;
830bcc9736cSJeff Kirsher }
831bcc9736cSJeff Kirsher
ks8842_dma_rx_cb(void * data)832bcc9736cSJeff Kirsher static void ks8842_dma_rx_cb(void *data)
833bcc9736cSJeff Kirsher {
834bcc9736cSJeff Kirsher struct net_device *netdev = data;
835bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
836bcc9736cSJeff Kirsher
837bcc9736cSJeff Kirsher netdev_dbg(netdev, "RX DMA finished\n");
838bcc9736cSJeff Kirsher /* schedule tasklet */
839bcc9736cSJeff Kirsher if (adapter->dma_rx.adesc)
840bcc9736cSJeff Kirsher tasklet_schedule(&adapter->dma_rx.tasklet);
841bcc9736cSJeff Kirsher }
842bcc9736cSJeff Kirsher
ks8842_dma_tx_cb(void * data)843bcc9736cSJeff Kirsher static void ks8842_dma_tx_cb(void *data)
844bcc9736cSJeff Kirsher {
845bcc9736cSJeff Kirsher struct net_device *netdev = data;
846bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
847bcc9736cSJeff Kirsher struct ks8842_tx_dma_ctl *ctl = &adapter->dma_tx;
848bcc9736cSJeff Kirsher
849bcc9736cSJeff Kirsher netdev_dbg(netdev, "TX DMA finished\n");
850bcc9736cSJeff Kirsher
851bcc9736cSJeff Kirsher if (!ctl->adesc)
852bcc9736cSJeff Kirsher return;
853bcc9736cSJeff Kirsher
854bcc9736cSJeff Kirsher netdev->stats.tx_packets++;
855bcc9736cSJeff Kirsher ctl->adesc = NULL;
856bcc9736cSJeff Kirsher
857bcc9736cSJeff Kirsher if (netif_queue_stopped(netdev))
858bcc9736cSJeff Kirsher netif_wake_queue(netdev);
859bcc9736cSJeff Kirsher }
860bcc9736cSJeff Kirsher
ks8842_stop_dma(struct ks8842_adapter * adapter)861bcc9736cSJeff Kirsher static void ks8842_stop_dma(struct ks8842_adapter *adapter)
862bcc9736cSJeff Kirsher {
863bcc9736cSJeff Kirsher struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx;
864bcc9736cSJeff Kirsher struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx;
865bcc9736cSJeff Kirsher
866bcc9736cSJeff Kirsher tx_ctl->adesc = NULL;
867bcc9736cSJeff Kirsher if (tx_ctl->chan)
868843d349cSVinod Koul dmaengine_terminate_all(tx_ctl->chan);
869bcc9736cSJeff Kirsher
870bcc9736cSJeff Kirsher rx_ctl->adesc = NULL;
871bcc9736cSJeff Kirsher if (rx_ctl->chan)
872843d349cSVinod Koul dmaengine_terminate_all(rx_ctl->chan);
873bcc9736cSJeff Kirsher
874bcc9736cSJeff Kirsher if (sg_dma_address(&rx_ctl->sg))
875bcc9736cSJeff Kirsher dma_unmap_single(adapter->dev, sg_dma_address(&rx_ctl->sg),
876bcc9736cSJeff Kirsher DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
877bcc9736cSJeff Kirsher sg_dma_address(&rx_ctl->sg) = 0;
878bcc9736cSJeff Kirsher
879bcc9736cSJeff Kirsher dev_kfree_skb(rx_ctl->skb);
880bcc9736cSJeff Kirsher rx_ctl->skb = NULL;
881bcc9736cSJeff Kirsher }
882bcc9736cSJeff Kirsher
ks8842_dealloc_dma_bufs(struct ks8842_adapter * adapter)883bcc9736cSJeff Kirsher static void ks8842_dealloc_dma_bufs(struct ks8842_adapter *adapter)
884bcc9736cSJeff Kirsher {
885bcc9736cSJeff Kirsher struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx;
886bcc9736cSJeff Kirsher struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx;
887bcc9736cSJeff Kirsher
888bcc9736cSJeff Kirsher ks8842_stop_dma(adapter);
889bcc9736cSJeff Kirsher
890bcc9736cSJeff Kirsher if (tx_ctl->chan)
891bcc9736cSJeff Kirsher dma_release_channel(tx_ctl->chan);
892bcc9736cSJeff Kirsher tx_ctl->chan = NULL;
893bcc9736cSJeff Kirsher
894bcc9736cSJeff Kirsher if (rx_ctl->chan)
895bcc9736cSJeff Kirsher dma_release_channel(rx_ctl->chan);
896bcc9736cSJeff Kirsher rx_ctl->chan = NULL;
897bcc9736cSJeff Kirsher
898bcc9736cSJeff Kirsher tasklet_kill(&rx_ctl->tasklet);
899bcc9736cSJeff Kirsher
900bcc9736cSJeff Kirsher if (sg_dma_address(&tx_ctl->sg))
901bcc9736cSJeff Kirsher dma_unmap_single(adapter->dev, sg_dma_address(&tx_ctl->sg),
902bcc9736cSJeff Kirsher DMA_BUFFER_SIZE, DMA_TO_DEVICE);
903bcc9736cSJeff Kirsher sg_dma_address(&tx_ctl->sg) = 0;
904bcc9736cSJeff Kirsher
905bcc9736cSJeff Kirsher kfree(tx_ctl->buf);
906bcc9736cSJeff Kirsher tx_ctl->buf = NULL;
907bcc9736cSJeff Kirsher }
908bcc9736cSJeff Kirsher
ks8842_dma_filter_fn(struct dma_chan * chan,void * filter_param)909bcc9736cSJeff Kirsher static bool ks8842_dma_filter_fn(struct dma_chan *chan, void *filter_param)
910bcc9736cSJeff Kirsher {
911bcc9736cSJeff Kirsher return chan->chan_id == (long)filter_param;
912bcc9736cSJeff Kirsher }
913bcc9736cSJeff Kirsher
ks8842_alloc_dma_bufs(struct net_device * netdev)914bcc9736cSJeff Kirsher static int ks8842_alloc_dma_bufs(struct net_device *netdev)
915bcc9736cSJeff Kirsher {
916bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
917bcc9736cSJeff Kirsher struct ks8842_tx_dma_ctl *tx_ctl = &adapter->dma_tx;
918bcc9736cSJeff Kirsher struct ks8842_rx_dma_ctl *rx_ctl = &adapter->dma_rx;
919bcc9736cSJeff Kirsher int err;
920bcc9736cSJeff Kirsher
921bcc9736cSJeff Kirsher dma_cap_mask_t mask;
922bcc9736cSJeff Kirsher
923bcc9736cSJeff Kirsher dma_cap_zero(mask);
924bcc9736cSJeff Kirsher dma_cap_set(DMA_SLAVE, mask);
925bcc9736cSJeff Kirsher dma_cap_set(DMA_PRIVATE, mask);
926bcc9736cSJeff Kirsher
927bcc9736cSJeff Kirsher sg_init_table(&tx_ctl->sg, 1);
928bcc9736cSJeff Kirsher
929bcc9736cSJeff Kirsher tx_ctl->chan = dma_request_channel(mask, ks8842_dma_filter_fn,
930bcc9736cSJeff Kirsher (void *)(long)tx_ctl->channel);
931bcc9736cSJeff Kirsher if (!tx_ctl->chan) {
932bcc9736cSJeff Kirsher err = -ENODEV;
933bcc9736cSJeff Kirsher goto err;
934bcc9736cSJeff Kirsher }
935bcc9736cSJeff Kirsher
936bcc9736cSJeff Kirsher /* allocate DMA buffer */
937bcc9736cSJeff Kirsher tx_ctl->buf = kmalloc(DMA_BUFFER_SIZE, GFP_KERNEL);
938bcc9736cSJeff Kirsher if (!tx_ctl->buf) {
939bcc9736cSJeff Kirsher err = -ENOMEM;
940bcc9736cSJeff Kirsher goto err;
941bcc9736cSJeff Kirsher }
942bcc9736cSJeff Kirsher
943bcc9736cSJeff Kirsher sg_dma_address(&tx_ctl->sg) = dma_map_single(adapter->dev,
944bcc9736cSJeff Kirsher tx_ctl->buf, DMA_BUFFER_SIZE, DMA_TO_DEVICE);
9452902bc66SDan Carpenter if (dma_mapping_error(adapter->dev, sg_dma_address(&tx_ctl->sg))) {
9462902bc66SDan Carpenter err = -ENOMEM;
947bcc9736cSJeff Kirsher sg_dma_address(&tx_ctl->sg) = 0;
948bcc9736cSJeff Kirsher goto err;
949bcc9736cSJeff Kirsher }
950bcc9736cSJeff Kirsher
951bcc9736cSJeff Kirsher rx_ctl->chan = dma_request_channel(mask, ks8842_dma_filter_fn,
952bcc9736cSJeff Kirsher (void *)(long)rx_ctl->channel);
953bcc9736cSJeff Kirsher if (!rx_ctl->chan) {
954bcc9736cSJeff Kirsher err = -ENODEV;
955bcc9736cSJeff Kirsher goto err;
956bcc9736cSJeff Kirsher }
957bcc9736cSJeff Kirsher
9589ad5a250SAllen Pais tasklet_setup(&rx_ctl->tasklet, ks8842_rx_frame_dma_tasklet);
959bcc9736cSJeff Kirsher
960bcc9736cSJeff Kirsher return 0;
961bcc9736cSJeff Kirsher err:
962bcc9736cSJeff Kirsher ks8842_dealloc_dma_bufs(adapter);
963bcc9736cSJeff Kirsher return err;
964bcc9736cSJeff Kirsher }
965bcc9736cSJeff Kirsher
966bcc9736cSJeff Kirsher /* Netdevice operations */
967bcc9736cSJeff Kirsher
ks8842_open(struct net_device * netdev)968bcc9736cSJeff Kirsher static int ks8842_open(struct net_device *netdev)
969bcc9736cSJeff Kirsher {
970bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
971bcc9736cSJeff Kirsher int err;
972bcc9736cSJeff Kirsher
973bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s - entry\n", __func__);
974bcc9736cSJeff Kirsher
975bcc9736cSJeff Kirsher if (KS8842_USE_DMA(adapter)) {
976bcc9736cSJeff Kirsher err = ks8842_alloc_dma_bufs(netdev);
977bcc9736cSJeff Kirsher
978bcc9736cSJeff Kirsher if (!err) {
979bcc9736cSJeff Kirsher /* start RX dma */
980bcc9736cSJeff Kirsher err = __ks8842_start_new_rx_dma(netdev);
981bcc9736cSJeff Kirsher if (err)
982bcc9736cSJeff Kirsher ks8842_dealloc_dma_bufs(adapter);
983bcc9736cSJeff Kirsher }
984bcc9736cSJeff Kirsher
985bcc9736cSJeff Kirsher if (err) {
986bcc9736cSJeff Kirsher printk(KERN_WARNING DRV_NAME
987bcc9736cSJeff Kirsher ": Failed to initiate DMA, running PIO\n");
988bcc9736cSJeff Kirsher ks8842_dealloc_dma_bufs(adapter);
989bcc9736cSJeff Kirsher adapter->dma_rx.channel = -1;
990bcc9736cSJeff Kirsher adapter->dma_tx.channel = -1;
991bcc9736cSJeff Kirsher }
992bcc9736cSJeff Kirsher }
993bcc9736cSJeff Kirsher
994bcc9736cSJeff Kirsher /* reset the HW */
995bcc9736cSJeff Kirsher ks8842_reset_hw(adapter);
996bcc9736cSJeff Kirsher
997bcc9736cSJeff Kirsher ks8842_write_mac_addr(adapter, netdev->dev_addr);
998bcc9736cSJeff Kirsher
999bcc9736cSJeff Kirsher ks8842_update_link_status(netdev, adapter);
1000bcc9736cSJeff Kirsher
1001bcc9736cSJeff Kirsher err = request_irq(adapter->irq, ks8842_irq, IRQF_SHARED, DRV_NAME,
1002bcc9736cSJeff Kirsher netdev);
1003bcc9736cSJeff Kirsher if (err) {
1004bcc9736cSJeff Kirsher pr_err("Failed to request IRQ: %d: %d\n", adapter->irq, err);
1005bcc9736cSJeff Kirsher return err;
1006bcc9736cSJeff Kirsher }
1007bcc9736cSJeff Kirsher
1008bcc9736cSJeff Kirsher return 0;
1009bcc9736cSJeff Kirsher }
1010bcc9736cSJeff Kirsher
ks8842_close(struct net_device * netdev)1011bcc9736cSJeff Kirsher static int ks8842_close(struct net_device *netdev)
1012bcc9736cSJeff Kirsher {
1013bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
1014bcc9736cSJeff Kirsher
1015bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s - entry\n", __func__);
1016bcc9736cSJeff Kirsher
1017bcc9736cSJeff Kirsher cancel_work_sync(&adapter->timeout_work);
1018bcc9736cSJeff Kirsher
1019bcc9736cSJeff Kirsher if (KS8842_USE_DMA(adapter))
1020bcc9736cSJeff Kirsher ks8842_dealloc_dma_bufs(adapter);
1021bcc9736cSJeff Kirsher
1022bcc9736cSJeff Kirsher /* free the irq */
1023bcc9736cSJeff Kirsher free_irq(adapter->irq, netdev);
1024bcc9736cSJeff Kirsher
1025bcc9736cSJeff Kirsher /* disable the switch */
1026bcc9736cSJeff Kirsher ks8842_write16(adapter, 32, 0x0, REG_SW_ID_AND_ENABLE);
1027bcc9736cSJeff Kirsher
1028bcc9736cSJeff Kirsher return 0;
1029bcc9736cSJeff Kirsher }
1030bcc9736cSJeff Kirsher
ks8842_xmit_frame(struct sk_buff * skb,struct net_device * netdev)1031bcc9736cSJeff Kirsher static netdev_tx_t ks8842_xmit_frame(struct sk_buff *skb,
1032bcc9736cSJeff Kirsher struct net_device *netdev)
1033bcc9736cSJeff Kirsher {
1034bcc9736cSJeff Kirsher int ret;
1035bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
1036bcc9736cSJeff Kirsher
1037bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s: entry\n", __func__);
1038bcc9736cSJeff Kirsher
1039bcc9736cSJeff Kirsher if (KS8842_USE_DMA(adapter)) {
1040bcc9736cSJeff Kirsher unsigned long flags;
1041bcc9736cSJeff Kirsher ret = ks8842_tx_frame_dma(skb, netdev);
1042bcc9736cSJeff Kirsher /* for now only allow one transfer at the time */
1043bcc9736cSJeff Kirsher spin_lock_irqsave(&adapter->lock, flags);
1044bcc9736cSJeff Kirsher if (adapter->dma_tx.adesc)
1045bcc9736cSJeff Kirsher netif_stop_queue(netdev);
1046bcc9736cSJeff Kirsher spin_unlock_irqrestore(&adapter->lock, flags);
1047bcc9736cSJeff Kirsher return ret;
1048bcc9736cSJeff Kirsher }
1049bcc9736cSJeff Kirsher
1050bcc9736cSJeff Kirsher ret = ks8842_tx_frame(skb, netdev);
1051bcc9736cSJeff Kirsher
1052bcc9736cSJeff Kirsher if (ks8842_tx_fifo_space(adapter) < netdev->mtu + 8)
1053bcc9736cSJeff Kirsher netif_stop_queue(netdev);
1054bcc9736cSJeff Kirsher
1055bcc9736cSJeff Kirsher return ret;
1056bcc9736cSJeff Kirsher }
1057bcc9736cSJeff Kirsher
ks8842_set_mac(struct net_device * netdev,void * p)1058bcc9736cSJeff Kirsher static int ks8842_set_mac(struct net_device *netdev, void *p)
1059bcc9736cSJeff Kirsher {
1060bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
1061bcc9736cSJeff Kirsher struct sockaddr *addr = p;
1062bcc9736cSJeff Kirsher char *mac = (u8 *)addr->sa_data;
1063bcc9736cSJeff Kirsher
1064bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s: entry\n", __func__);
1065bcc9736cSJeff Kirsher
1066bcc9736cSJeff Kirsher if (!is_valid_ether_addr(addr->sa_data))
1067bcc9736cSJeff Kirsher return -EADDRNOTAVAIL;
1068bcc9736cSJeff Kirsher
1069a05e4c0aSJakub Kicinski eth_hw_addr_set(netdev, mac);
1070bcc9736cSJeff Kirsher
1071bcc9736cSJeff Kirsher ks8842_write_mac_addr(adapter, mac);
1072bcc9736cSJeff Kirsher return 0;
1073bcc9736cSJeff Kirsher }
1074bcc9736cSJeff Kirsher
ks8842_tx_timeout_work(struct work_struct * work)1075bcc9736cSJeff Kirsher static void ks8842_tx_timeout_work(struct work_struct *work)
1076bcc9736cSJeff Kirsher {
1077bcc9736cSJeff Kirsher struct ks8842_adapter *adapter =
1078bcc9736cSJeff Kirsher container_of(work, struct ks8842_adapter, timeout_work);
1079bcc9736cSJeff Kirsher struct net_device *netdev = adapter->netdev;
1080bcc9736cSJeff Kirsher unsigned long flags;
1081bcc9736cSJeff Kirsher
1082bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s: entry\n", __func__);
1083bcc9736cSJeff Kirsher
1084bcc9736cSJeff Kirsher spin_lock_irqsave(&adapter->lock, flags);
1085bcc9736cSJeff Kirsher
1086bcc9736cSJeff Kirsher if (KS8842_USE_DMA(adapter))
1087bcc9736cSJeff Kirsher ks8842_stop_dma(adapter);
1088bcc9736cSJeff Kirsher
1089bcc9736cSJeff Kirsher /* disable interrupts */
1090bcc9736cSJeff Kirsher ks8842_write16(adapter, 18, 0, REG_IER);
1091bcc9736cSJeff Kirsher ks8842_write16(adapter, 18, 0xFFFF, REG_ISR);
1092bcc9736cSJeff Kirsher
1093bcc9736cSJeff Kirsher netif_stop_queue(netdev);
1094bcc9736cSJeff Kirsher
1095bcc9736cSJeff Kirsher spin_unlock_irqrestore(&adapter->lock, flags);
1096bcc9736cSJeff Kirsher
1097bcc9736cSJeff Kirsher ks8842_reset_hw(adapter);
1098bcc9736cSJeff Kirsher
1099bcc9736cSJeff Kirsher ks8842_write_mac_addr(adapter, netdev->dev_addr);
1100bcc9736cSJeff Kirsher
1101bcc9736cSJeff Kirsher ks8842_update_link_status(netdev, adapter);
1102bcc9736cSJeff Kirsher
1103bcc9736cSJeff Kirsher if (KS8842_USE_DMA(adapter))
1104bcc9736cSJeff Kirsher __ks8842_start_new_rx_dma(netdev);
1105bcc9736cSJeff Kirsher }
1106bcc9736cSJeff Kirsher
ks8842_tx_timeout(struct net_device * netdev,unsigned int txqueue)11070290bd29SMichael S. Tsirkin static void ks8842_tx_timeout(struct net_device *netdev, unsigned int txqueue)
1108bcc9736cSJeff Kirsher {
1109bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
1110bcc9736cSJeff Kirsher
1111bcc9736cSJeff Kirsher netdev_dbg(netdev, "%s: entry\n", __func__);
1112bcc9736cSJeff Kirsher
1113bcc9736cSJeff Kirsher schedule_work(&adapter->timeout_work);
1114bcc9736cSJeff Kirsher }
1115bcc9736cSJeff Kirsher
1116bcc9736cSJeff Kirsher static const struct net_device_ops ks8842_netdev_ops = {
1117bcc9736cSJeff Kirsher .ndo_open = ks8842_open,
1118bcc9736cSJeff Kirsher .ndo_stop = ks8842_close,
1119bcc9736cSJeff Kirsher .ndo_start_xmit = ks8842_xmit_frame,
1120bcc9736cSJeff Kirsher .ndo_set_mac_address = ks8842_set_mac,
1121bcc9736cSJeff Kirsher .ndo_tx_timeout = ks8842_tx_timeout,
1122bcc9736cSJeff Kirsher .ndo_validate_addr = eth_validate_addr
1123bcc9736cSJeff Kirsher };
1124bcc9736cSJeff Kirsher
1125bcc9736cSJeff Kirsher static const struct ethtool_ops ks8842_ethtool_ops = {
1126bcc9736cSJeff Kirsher .get_link = ethtool_op_get_link,
1127bcc9736cSJeff Kirsher };
1128bcc9736cSJeff Kirsher
ks8842_probe(struct platform_device * pdev)1129654b8c5cSBill Pemberton static int ks8842_probe(struct platform_device *pdev)
1130bcc9736cSJeff Kirsher {
1131bcc9736cSJeff Kirsher int err = -ENOMEM;
1132bcc9736cSJeff Kirsher struct resource *iomem;
1133bcc9736cSJeff Kirsher struct net_device *netdev;
1134bcc9736cSJeff Kirsher struct ks8842_adapter *adapter;
11350dd14b67SJingoo Han struct ks8842_platform_data *pdata = dev_get_platdata(&pdev->dev);
1136bcc9736cSJeff Kirsher u16 id;
1137bcc9736cSJeff Kirsher unsigned i;
1138bcc9736cSJeff Kirsher
1139bcc9736cSJeff Kirsher iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
114020f1932eSYang Yingliang if (!iomem) {
114120f1932eSYang Yingliang dev_err(&pdev->dev, "Invalid resource\n");
114220f1932eSYang Yingliang return -EINVAL;
114320f1932eSYang Yingliang }
1144bcc9736cSJeff Kirsher if (!request_mem_region(iomem->start, resource_size(iomem), DRV_NAME))
1145bcc9736cSJeff Kirsher goto err_mem_region;
1146bcc9736cSJeff Kirsher
1147bcc9736cSJeff Kirsher netdev = alloc_etherdev(sizeof(struct ks8842_adapter));
1148bcc9736cSJeff Kirsher if (!netdev)
1149bcc9736cSJeff Kirsher goto err_alloc_etherdev;
1150bcc9736cSJeff Kirsher
1151bcc9736cSJeff Kirsher SET_NETDEV_DEV(netdev, &pdev->dev);
1152bcc9736cSJeff Kirsher
1153bcc9736cSJeff Kirsher adapter = netdev_priv(netdev);
1154bcc9736cSJeff Kirsher adapter->netdev = netdev;
1155bcc9736cSJeff Kirsher INIT_WORK(&adapter->timeout_work, ks8842_tx_timeout_work);
1156bcc9736cSJeff Kirsher adapter->hw_addr = ioremap(iomem->start, resource_size(iomem));
1157bcc9736cSJeff Kirsher adapter->conf_flags = iomem->flags;
1158bcc9736cSJeff Kirsher
1159bcc9736cSJeff Kirsher if (!adapter->hw_addr)
1160bcc9736cSJeff Kirsher goto err_ioremap;
1161bcc9736cSJeff Kirsher
1162bcc9736cSJeff Kirsher adapter->irq = platform_get_irq(pdev, 0);
1163bcc9736cSJeff Kirsher if (adapter->irq < 0) {
1164bcc9736cSJeff Kirsher err = adapter->irq;
1165bcc9736cSJeff Kirsher goto err_get_irq;
1166bcc9736cSJeff Kirsher }
1167bcc9736cSJeff Kirsher
1168bcc9736cSJeff Kirsher adapter->dev = (pdev->dev.parent) ? pdev->dev.parent : &pdev->dev;
1169bcc9736cSJeff Kirsher
1170bcc9736cSJeff Kirsher /* DMA is only supported when accessed via timberdale */
1171bcc9736cSJeff Kirsher if (!(adapter->conf_flags & MICREL_KS884X) && pdata &&
1172bcc9736cSJeff Kirsher (pdata->tx_dma_channel != -1) &&
1173bcc9736cSJeff Kirsher (pdata->rx_dma_channel != -1)) {
1174bcc9736cSJeff Kirsher adapter->dma_rx.channel = pdata->rx_dma_channel;
1175bcc9736cSJeff Kirsher adapter->dma_tx.channel = pdata->tx_dma_channel;
1176bcc9736cSJeff Kirsher } else {
1177bcc9736cSJeff Kirsher adapter->dma_rx.channel = -1;
1178bcc9736cSJeff Kirsher adapter->dma_tx.channel = -1;
1179bcc9736cSJeff Kirsher }
1180bcc9736cSJeff Kirsher
11819ad5a250SAllen Pais tasklet_setup(&adapter->tasklet, ks8842_tasklet);
1182bcc9736cSJeff Kirsher spin_lock_init(&adapter->lock);
1183bcc9736cSJeff Kirsher
1184bcc9736cSJeff Kirsher netdev->netdev_ops = &ks8842_netdev_ops;
1185bcc9736cSJeff Kirsher netdev->ethtool_ops = &ks8842_ethtool_ops;
1186bcc9736cSJeff Kirsher
1187bcc9736cSJeff Kirsher /* Check if a mac address was given */
1188bcc9736cSJeff Kirsher i = netdev->addr_len;
1189bcc9736cSJeff Kirsher if (pdata) {
1190bcc9736cSJeff Kirsher for (i = 0; i < netdev->addr_len; i++)
1191bcc9736cSJeff Kirsher if (pdata->macaddr[i] != 0)
1192bcc9736cSJeff Kirsher break;
1193bcc9736cSJeff Kirsher
1194bcc9736cSJeff Kirsher if (i < netdev->addr_len)
1195bcc9736cSJeff Kirsher /* an address was passed, use it */
1196a05e4c0aSJakub Kicinski eth_hw_addr_set(netdev, pdata->macaddr);
1197bcc9736cSJeff Kirsher }
1198bcc9736cSJeff Kirsher
1199bcc9736cSJeff Kirsher if (i == netdev->addr_len) {
1200*4abd7cffSJakub Kicinski ks8842_init_mac_addr(adapter);
1201bcc9736cSJeff Kirsher
1202bcc9736cSJeff Kirsher if (!is_valid_ether_addr(netdev->dev_addr))
12037ce5d222SDanny Kukawka eth_hw_addr_random(netdev);
1204bcc9736cSJeff Kirsher }
1205bcc9736cSJeff Kirsher
1206bcc9736cSJeff Kirsher id = ks8842_read16(adapter, 32, REG_SW_ID_AND_ENABLE);
1207bcc9736cSJeff Kirsher
1208bcc9736cSJeff Kirsher strcpy(netdev->name, "eth%d");
1209bcc9736cSJeff Kirsher err = register_netdev(netdev);
1210bcc9736cSJeff Kirsher if (err)
1211bcc9736cSJeff Kirsher goto err_register;
1212bcc9736cSJeff Kirsher
1213bcc9736cSJeff Kirsher platform_set_drvdata(pdev, netdev);
1214bcc9736cSJeff Kirsher
1215bcc9736cSJeff Kirsher pr_info("Found chip, family: 0x%x, id: 0x%x, rev: 0x%x\n",
1216bcc9736cSJeff Kirsher (id >> 8) & 0xff, (id >> 4) & 0xf, (id >> 1) & 0x7);
1217bcc9736cSJeff Kirsher
1218bcc9736cSJeff Kirsher return 0;
1219bcc9736cSJeff Kirsher
1220bcc9736cSJeff Kirsher err_register:
1221bcc9736cSJeff Kirsher err_get_irq:
1222bcc9736cSJeff Kirsher iounmap(adapter->hw_addr);
1223bcc9736cSJeff Kirsher err_ioremap:
1224bcc9736cSJeff Kirsher free_netdev(netdev);
1225bcc9736cSJeff Kirsher err_alloc_etherdev:
1226bcc9736cSJeff Kirsher release_mem_region(iomem->start, resource_size(iomem));
1227bcc9736cSJeff Kirsher err_mem_region:
1228bcc9736cSJeff Kirsher return err;
1229bcc9736cSJeff Kirsher }
1230bcc9736cSJeff Kirsher
ks8842_remove(struct platform_device * pdev)1231654b8c5cSBill Pemberton static int ks8842_remove(struct platform_device *pdev)
1232bcc9736cSJeff Kirsher {
1233bcc9736cSJeff Kirsher struct net_device *netdev = platform_get_drvdata(pdev);
1234bcc9736cSJeff Kirsher struct ks8842_adapter *adapter = netdev_priv(netdev);
1235bcc9736cSJeff Kirsher struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1236bcc9736cSJeff Kirsher
1237bcc9736cSJeff Kirsher unregister_netdev(netdev);
1238bcc9736cSJeff Kirsher tasklet_kill(&adapter->tasklet);
1239bcc9736cSJeff Kirsher iounmap(adapter->hw_addr);
1240bcc9736cSJeff Kirsher free_netdev(netdev);
1241bcc9736cSJeff Kirsher release_mem_region(iomem->start, resource_size(iomem));
1242bcc9736cSJeff Kirsher return 0;
1243bcc9736cSJeff Kirsher }
1244bcc9736cSJeff Kirsher
1245bcc9736cSJeff Kirsher
1246bcc9736cSJeff Kirsher static struct platform_driver ks8842_platform_driver = {
1247bcc9736cSJeff Kirsher .driver = {
1248bcc9736cSJeff Kirsher .name = DRV_NAME,
1249bcc9736cSJeff Kirsher },
1250bcc9736cSJeff Kirsher .probe = ks8842_probe,
1251654b8c5cSBill Pemberton .remove = ks8842_remove,
1252bcc9736cSJeff Kirsher };
1253bcc9736cSJeff Kirsher
1254db62f684SAxel Lin module_platform_driver(ks8842_platform_driver);
1255bcc9736cSJeff Kirsher
1256bcc9736cSJeff Kirsher MODULE_DESCRIPTION("Timberdale KS8842 ethernet driver");
1257bcc9736cSJeff Kirsher MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
1258bcc9736cSJeff Kirsher MODULE_LICENSE("GPL v2");
1259bcc9736cSJeff Kirsher MODULE_ALIAS("platform:ks8842");
1260bcc9736cSJeff Kirsher
1261