xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/davicom/dm9000.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *      Davicom DM9000 Fast Ethernet driver for Linux.
4*4882a593Smuzhiyun  * 	Copyright (C) 1997  Sten Wang
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * (C) Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Additional updates, Copyright:
9*4882a593Smuzhiyun  *	Ben Dooks <ben@simtec.co.uk>
10*4882a593Smuzhiyun  *	Sascha Hauer <s.hauer@pengutronix.de>
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/ioport.h>
15*4882a593Smuzhiyun #include <linux/netdevice.h>
16*4882a593Smuzhiyun #include <linux/etherdevice.h>
17*4882a593Smuzhiyun #include <linux/interrupt.h>
18*4882a593Smuzhiyun #include <linux/skbuff.h>
19*4882a593Smuzhiyun #include <linux/spinlock.h>
20*4882a593Smuzhiyun #include <linux/crc32.h>
21*4882a593Smuzhiyun #include <linux/mii.h>
22*4882a593Smuzhiyun #include <linux/of.h>
23*4882a593Smuzhiyun #include <linux/of_net.h>
24*4882a593Smuzhiyun #include <linux/ethtool.h>
25*4882a593Smuzhiyun #include <linux/dm9000.h>
26*4882a593Smuzhiyun #include <linux/delay.h>
27*4882a593Smuzhiyun #include <linux/platform_device.h>
28*4882a593Smuzhiyun #include <linux/irq.h>
29*4882a593Smuzhiyun #include <linux/slab.h>
30*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
31*4882a593Smuzhiyun #include <linux/gpio.h>
32*4882a593Smuzhiyun #include <linux/of_gpio.h>
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include <asm/delay.h>
35*4882a593Smuzhiyun #include <asm/irq.h>
36*4882a593Smuzhiyun #include <asm/io.h>
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #include "dm9000.h"
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun /* Board/System/Debug information/definition ---------------- */
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #define DM9000_PHY		0x40	/* PHY address 0x01 */
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #define CARDNAME	"dm9000"
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun  * Transmit timeout, default 5 seconds.
48*4882a593Smuzhiyun  */
49*4882a593Smuzhiyun static int watchdog = 5000;
50*4882a593Smuzhiyun module_param(watchdog, int, 0400);
51*4882a593Smuzhiyun MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun /*
54*4882a593Smuzhiyun  * Debug messages level
55*4882a593Smuzhiyun  */
56*4882a593Smuzhiyun static int debug;
57*4882a593Smuzhiyun module_param(debug, int, 0644);
58*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "dm9000 debug level (0-6)");
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /* DM9000 register address locking.
61*4882a593Smuzhiyun  *
62*4882a593Smuzhiyun  * The DM9000 uses an address register to control where data written
63*4882a593Smuzhiyun  * to the data register goes. This means that the address register
64*4882a593Smuzhiyun  * must be preserved over interrupts or similar calls.
65*4882a593Smuzhiyun  *
66*4882a593Smuzhiyun  * During interrupt and other critical calls, a spinlock is used to
67*4882a593Smuzhiyun  * protect the system, but the calls themselves save the address
68*4882a593Smuzhiyun  * in the address register in case they are interrupting another
69*4882a593Smuzhiyun  * access to the device.
70*4882a593Smuzhiyun  *
71*4882a593Smuzhiyun  * For general accesses a lock is provided so that calls which are
72*4882a593Smuzhiyun  * allowed to sleep are serialised so that the address register does
73*4882a593Smuzhiyun  * not need to be saved. This lock also serves to serialise access
74*4882a593Smuzhiyun  * to the EEPROM and PHY access registers which are shared between
75*4882a593Smuzhiyun  * these two devices.
76*4882a593Smuzhiyun  */
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /* The driver supports the original DM9000E, and now the two newer
79*4882a593Smuzhiyun  * devices, DM9000A and DM9000B.
80*4882a593Smuzhiyun  */
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun enum dm9000_type {
83*4882a593Smuzhiyun 	TYPE_DM9000E,	/* original DM9000 */
84*4882a593Smuzhiyun 	TYPE_DM9000A,
85*4882a593Smuzhiyun 	TYPE_DM9000B
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun /* Structure/enum declaration ------------------------------- */
89*4882a593Smuzhiyun struct board_info {
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	void __iomem	*io_addr;	/* Register I/O base address */
92*4882a593Smuzhiyun 	void __iomem	*io_data;	/* Data I/O address */
93*4882a593Smuzhiyun 	u16		 irq;		/* IRQ */
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	u16		tx_pkt_cnt;
96*4882a593Smuzhiyun 	u16		queue_pkt_len;
97*4882a593Smuzhiyun 	u16		queue_start_addr;
98*4882a593Smuzhiyun 	u16		queue_ip_summed;
99*4882a593Smuzhiyun 	u16		dbug_cnt;
100*4882a593Smuzhiyun 	u8		io_mode;		/* 0:word, 2:byte */
101*4882a593Smuzhiyun 	u8		phy_addr;
102*4882a593Smuzhiyun 	u8		imr_all;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	unsigned int	flags;
105*4882a593Smuzhiyun 	unsigned int	in_timeout:1;
106*4882a593Smuzhiyun 	unsigned int	in_suspend:1;
107*4882a593Smuzhiyun 	unsigned int	wake_supported:1;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	enum dm9000_type type;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	void (*inblk)(void __iomem *port, void *data, int length);
112*4882a593Smuzhiyun 	void (*outblk)(void __iomem *port, void *data, int length);
113*4882a593Smuzhiyun 	void (*dumpblk)(void __iomem *port, int length);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	struct device	*dev;	     /* parent device */
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	struct resource	*addr_res;   /* resources found */
118*4882a593Smuzhiyun 	struct resource *data_res;
119*4882a593Smuzhiyun 	struct resource	*addr_req;   /* resources requested */
120*4882a593Smuzhiyun 	struct resource *data_req;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	int		 irq_wake;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	struct mutex	 addr_lock;	/* phy and eeprom access lock */
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	struct delayed_work phy_poll;
127*4882a593Smuzhiyun 	struct net_device  *ndev;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	spinlock_t	lock;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	struct mii_if_info mii;
132*4882a593Smuzhiyun 	u32		msg_enable;
133*4882a593Smuzhiyun 	u32		wake_state;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	int		ip_summed;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	struct regulator *power_supply;
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun /* debug code */
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun #define dm9000_dbg(db, lev, msg...) do {		\
143*4882a593Smuzhiyun 	if ((lev) < debug) {				\
144*4882a593Smuzhiyun 		dev_dbg(db->dev, msg);			\
145*4882a593Smuzhiyun 	}						\
146*4882a593Smuzhiyun } while (0)
147*4882a593Smuzhiyun 
to_dm9000_board(struct net_device * dev)148*4882a593Smuzhiyun static inline struct board_info *to_dm9000_board(struct net_device *dev)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	return netdev_priv(dev);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun /* DM9000 network board routine ---------------------------- */
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun /*
156*4882a593Smuzhiyun  *   Read a byte from I/O port
157*4882a593Smuzhiyun  */
158*4882a593Smuzhiyun static u8
ior(struct board_info * db,int reg)159*4882a593Smuzhiyun ior(struct board_info *db, int reg)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	writeb(reg, db->io_addr);
162*4882a593Smuzhiyun 	return readb(db->io_data);
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun /*
166*4882a593Smuzhiyun  *   Write a byte to I/O port
167*4882a593Smuzhiyun  */
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun static void
iow(struct board_info * db,int reg,int value)170*4882a593Smuzhiyun iow(struct board_info *db, int reg, int value)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun 	writeb(reg, db->io_addr);
173*4882a593Smuzhiyun 	writeb(value, db->io_data);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun static void
dm9000_reset(struct board_info * db)177*4882a593Smuzhiyun dm9000_reset(struct board_info *db)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	dev_dbg(db->dev, "resetting device\n");
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	/* Reset DM9000, see DM9000 Application Notes V1.22 Jun 11, 2004 page 29
182*4882a593Smuzhiyun 	 * The essential point is that we have to do a double reset, and the
183*4882a593Smuzhiyun 	 * instruction is to set LBK into MAC internal loopback mode.
184*4882a593Smuzhiyun 	 */
185*4882a593Smuzhiyun 	iow(db, DM9000_NCR, NCR_RST | NCR_MAC_LBK);
186*4882a593Smuzhiyun 	udelay(100); /* Application note says at least 20 us */
187*4882a593Smuzhiyun 	if (ior(db, DM9000_NCR) & 1)
188*4882a593Smuzhiyun 		dev_err(db->dev, "dm9000 did not respond to first reset\n");
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	iow(db, DM9000_NCR, 0);
191*4882a593Smuzhiyun 	iow(db, DM9000_NCR, NCR_RST | NCR_MAC_LBK);
192*4882a593Smuzhiyun 	udelay(100);
193*4882a593Smuzhiyun 	if (ior(db, DM9000_NCR) & 1)
194*4882a593Smuzhiyun 		dev_err(db->dev, "dm9000 did not respond to second reset\n");
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun /* routines for sending block to chip */
198*4882a593Smuzhiyun 
dm9000_outblk_8bit(void __iomem * reg,void * data,int count)199*4882a593Smuzhiyun static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	iowrite8_rep(reg, data, count);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun 
dm9000_outblk_16bit(void __iomem * reg,void * data,int count)204*4882a593Smuzhiyun static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	iowrite16_rep(reg, data, (count+1) >> 1);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
dm9000_outblk_32bit(void __iomem * reg,void * data,int count)209*4882a593Smuzhiyun static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun 	iowrite32_rep(reg, data, (count+3) >> 2);
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun /* input block from chip to memory */
215*4882a593Smuzhiyun 
dm9000_inblk_8bit(void __iomem * reg,void * data,int count)216*4882a593Smuzhiyun static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	ioread8_rep(reg, data, count);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 
dm9000_inblk_16bit(void __iomem * reg,void * data,int count)222*4882a593Smuzhiyun static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	ioread16_rep(reg, data, (count+1) >> 1);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
dm9000_inblk_32bit(void __iomem * reg,void * data,int count)227*4882a593Smuzhiyun static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun 	ioread32_rep(reg, data, (count+3) >> 2);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun /* dump block from chip to null */
233*4882a593Smuzhiyun 
dm9000_dumpblk_8bit(void __iomem * reg,int count)234*4882a593Smuzhiyun static void dm9000_dumpblk_8bit(void __iomem *reg, int count)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun 	int i;
237*4882a593Smuzhiyun 	int tmp;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	for (i = 0; i < count; i++)
240*4882a593Smuzhiyun 		tmp = readb(reg);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun 
dm9000_dumpblk_16bit(void __iomem * reg,int count)243*4882a593Smuzhiyun static void dm9000_dumpblk_16bit(void __iomem *reg, int count)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	int i;
246*4882a593Smuzhiyun 	int tmp;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	count = (count + 1) >> 1;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	for (i = 0; i < count; i++)
251*4882a593Smuzhiyun 		tmp = readw(reg);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
dm9000_dumpblk_32bit(void __iomem * reg,int count)254*4882a593Smuzhiyun static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	int i;
257*4882a593Smuzhiyun 	int tmp;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	count = (count + 3) >> 2;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	for (i = 0; i < count; i++)
262*4882a593Smuzhiyun 		tmp = readl(reg);
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun /*
266*4882a593Smuzhiyun  * Sleep, either by using msleep() or if we are suspending, then
267*4882a593Smuzhiyun  * use mdelay() to sleep.
268*4882a593Smuzhiyun  */
dm9000_msleep(struct board_info * db,unsigned int ms)269*4882a593Smuzhiyun static void dm9000_msleep(struct board_info *db, unsigned int ms)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun 	if (db->in_suspend || db->in_timeout)
272*4882a593Smuzhiyun 		mdelay(ms);
273*4882a593Smuzhiyun 	else
274*4882a593Smuzhiyun 		msleep(ms);
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun /* Read a word from phyxcer */
278*4882a593Smuzhiyun static int
dm9000_phy_read(struct net_device * dev,int phy_reg_unused,int reg)279*4882a593Smuzhiyun dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
282*4882a593Smuzhiyun 	unsigned long flags;
283*4882a593Smuzhiyun 	unsigned int reg_save;
284*4882a593Smuzhiyun 	int ret;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	mutex_lock(&db->addr_lock);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	/* Save previous register address */
291*4882a593Smuzhiyun 	reg_save = readb(db->io_addr);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	/* Fill the phyxcer register into REG_0C */
294*4882a593Smuzhiyun 	iow(db, DM9000_EPAR, DM9000_PHY | reg);
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	/* Issue phyxcer read command */
297*4882a593Smuzhiyun 	iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	writeb(reg_save, db->io_addr);
300*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	dm9000_msleep(db, 1);		/* Wait read complete */
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
305*4882a593Smuzhiyun 	reg_save = readb(db->io_addr);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer read command */
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	/* The read data keeps on REG_0D & REG_0E */
310*4882a593Smuzhiyun 	ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	/* restore the previous address */
313*4882a593Smuzhiyun 	writeb(reg_save, db->io_addr);
314*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	mutex_unlock(&db->addr_lock);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
319*4882a593Smuzhiyun 	return ret;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun /* Write a word to phyxcer */
323*4882a593Smuzhiyun static void
dm9000_phy_write(struct net_device * dev,int phyaddr_unused,int reg,int value)324*4882a593Smuzhiyun dm9000_phy_write(struct net_device *dev,
325*4882a593Smuzhiyun 		 int phyaddr_unused, int reg, int value)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
328*4882a593Smuzhiyun 	unsigned long flags;
329*4882a593Smuzhiyun 	unsigned long reg_save;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
332*4882a593Smuzhiyun 	if (!db->in_timeout)
333*4882a593Smuzhiyun 		mutex_lock(&db->addr_lock);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	/* Save previous register address */
338*4882a593Smuzhiyun 	reg_save = readb(db->io_addr);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	/* Fill the phyxcer register into REG_0C */
341*4882a593Smuzhiyun 	iow(db, DM9000_EPAR, DM9000_PHY | reg);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	/* Fill the written data into REG_0D & REG_0E */
344*4882a593Smuzhiyun 	iow(db, DM9000_EPDRL, value);
345*4882a593Smuzhiyun 	iow(db, DM9000_EPDRH, value >> 8);
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	/* Issue phyxcer write command */
348*4882a593Smuzhiyun 	iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	writeb(reg_save, db->io_addr);
351*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	dm9000_msleep(db, 1);		/* Wait write complete */
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
356*4882a593Smuzhiyun 	reg_save = readb(db->io_addr);
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	/* restore the previous address */
361*4882a593Smuzhiyun 	writeb(reg_save, db->io_addr);
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
364*4882a593Smuzhiyun 	if (!db->in_timeout)
365*4882a593Smuzhiyun 		mutex_unlock(&db->addr_lock);
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun /* dm9000_set_io
369*4882a593Smuzhiyun  *
370*4882a593Smuzhiyun  * select the specified set of io routines to use with the
371*4882a593Smuzhiyun  * device
372*4882a593Smuzhiyun  */
373*4882a593Smuzhiyun 
dm9000_set_io(struct board_info * db,int byte_width)374*4882a593Smuzhiyun static void dm9000_set_io(struct board_info *db, int byte_width)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun 	/* use the size of the data resource to work out what IO
377*4882a593Smuzhiyun 	 * routines we want to use
378*4882a593Smuzhiyun 	 */
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	switch (byte_width) {
381*4882a593Smuzhiyun 	case 1:
382*4882a593Smuzhiyun 		db->dumpblk = dm9000_dumpblk_8bit;
383*4882a593Smuzhiyun 		db->outblk  = dm9000_outblk_8bit;
384*4882a593Smuzhiyun 		db->inblk   = dm9000_inblk_8bit;
385*4882a593Smuzhiyun 		break;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	case 3:
389*4882a593Smuzhiyun 		dev_dbg(db->dev, ": 3 byte IO, falling back to 16bit\n");
390*4882a593Smuzhiyun 		fallthrough;
391*4882a593Smuzhiyun 	case 2:
392*4882a593Smuzhiyun 		db->dumpblk = dm9000_dumpblk_16bit;
393*4882a593Smuzhiyun 		db->outblk  = dm9000_outblk_16bit;
394*4882a593Smuzhiyun 		db->inblk   = dm9000_inblk_16bit;
395*4882a593Smuzhiyun 		break;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	case 4:
398*4882a593Smuzhiyun 	default:
399*4882a593Smuzhiyun 		db->dumpblk = dm9000_dumpblk_32bit;
400*4882a593Smuzhiyun 		db->outblk  = dm9000_outblk_32bit;
401*4882a593Smuzhiyun 		db->inblk   = dm9000_inblk_32bit;
402*4882a593Smuzhiyun 		break;
403*4882a593Smuzhiyun 	}
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun 
dm9000_schedule_poll(struct board_info * db)406*4882a593Smuzhiyun static void dm9000_schedule_poll(struct board_info *db)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	if (db->type == TYPE_DM9000E)
409*4882a593Smuzhiyun 		schedule_delayed_work(&db->phy_poll, HZ * 2);
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
dm9000_ioctl(struct net_device * dev,struct ifreq * req,int cmd)412*4882a593Smuzhiyun static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	if (!netif_running(dev))
417*4882a593Smuzhiyun 		return -EINVAL;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun static unsigned int
dm9000_read_locked(struct board_info * db,int reg)423*4882a593Smuzhiyun dm9000_read_locked(struct board_info *db, int reg)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun 	unsigned long flags;
426*4882a593Smuzhiyun 	unsigned int ret;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
429*4882a593Smuzhiyun 	ret = ior(db, reg);
430*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	return ret;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun 
dm9000_wait_eeprom(struct board_info * db)435*4882a593Smuzhiyun static int dm9000_wait_eeprom(struct board_info *db)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun 	unsigned int status;
438*4882a593Smuzhiyun 	int timeout = 8;	/* wait max 8msec */
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	/* The DM9000 data sheets say we should be able to
441*4882a593Smuzhiyun 	 * poll the ERRE bit in EPCR to wait for the EEPROM
442*4882a593Smuzhiyun 	 * operation. From testing several chips, this bit
443*4882a593Smuzhiyun 	 * does not seem to work.
444*4882a593Smuzhiyun 	 *
445*4882a593Smuzhiyun 	 * We attempt to use the bit, but fall back to the
446*4882a593Smuzhiyun 	 * timeout (which is why we do not return an error
447*4882a593Smuzhiyun 	 * on expiry) to say that the EEPROM operation has
448*4882a593Smuzhiyun 	 * completed.
449*4882a593Smuzhiyun 	 */
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	while (1) {
452*4882a593Smuzhiyun 		status = dm9000_read_locked(db, DM9000_EPCR);
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 		if ((status & EPCR_ERRE) == 0)
455*4882a593Smuzhiyun 			break;
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 		msleep(1);
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 		if (timeout-- < 0) {
460*4882a593Smuzhiyun 			dev_dbg(db->dev, "timeout waiting EEPROM\n");
461*4882a593Smuzhiyun 			break;
462*4882a593Smuzhiyun 		}
463*4882a593Smuzhiyun 	}
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	return 0;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun /*
469*4882a593Smuzhiyun  *  Read a word data from EEPROM
470*4882a593Smuzhiyun  */
471*4882a593Smuzhiyun static void
dm9000_read_eeprom(struct board_info * db,int offset,u8 * to)472*4882a593Smuzhiyun dm9000_read_eeprom(struct board_info *db, int offset, u8 *to)
473*4882a593Smuzhiyun {
474*4882a593Smuzhiyun 	unsigned long flags;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	if (db->flags & DM9000_PLATF_NO_EEPROM) {
477*4882a593Smuzhiyun 		to[0] = 0xff;
478*4882a593Smuzhiyun 		to[1] = 0xff;
479*4882a593Smuzhiyun 		return;
480*4882a593Smuzhiyun 	}
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	mutex_lock(&db->addr_lock);
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	iow(db, DM9000_EPAR, offset);
487*4882a593Smuzhiyun 	iow(db, DM9000_EPCR, EPCR_ERPRR);
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	dm9000_wait_eeprom(db);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	/* delay for at-least 150uS */
494*4882a593Smuzhiyun 	msleep(1);
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	iow(db, DM9000_EPCR, 0x0);
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	to[0] = ior(db, DM9000_EPDRL);
501*4882a593Smuzhiyun 	to[1] = ior(db, DM9000_EPDRH);
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	mutex_unlock(&db->addr_lock);
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun /*
509*4882a593Smuzhiyun  * Write a word data to SROM
510*4882a593Smuzhiyun  */
511*4882a593Smuzhiyun static void
dm9000_write_eeprom(struct board_info * db,int offset,u8 * data)512*4882a593Smuzhiyun dm9000_write_eeprom(struct board_info *db, int offset, u8 *data)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun 	unsigned long flags;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	if (db->flags & DM9000_PLATF_NO_EEPROM)
517*4882a593Smuzhiyun 		return;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 	mutex_lock(&db->addr_lock);
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
522*4882a593Smuzhiyun 	iow(db, DM9000_EPAR, offset);
523*4882a593Smuzhiyun 	iow(db, DM9000_EPDRH, data[1]);
524*4882a593Smuzhiyun 	iow(db, DM9000_EPDRL, data[0]);
525*4882a593Smuzhiyun 	iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
526*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	dm9000_wait_eeprom(db);
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	mdelay(1);	/* wait at least 150uS to clear */
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
533*4882a593Smuzhiyun 	iow(db, DM9000_EPCR, 0);
534*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	mutex_unlock(&db->addr_lock);
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun /* ethtool ops */
540*4882a593Smuzhiyun 
dm9000_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)541*4882a593Smuzhiyun static void dm9000_get_drvinfo(struct net_device *dev,
542*4882a593Smuzhiyun 			       struct ethtool_drvinfo *info)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	strlcpy(info->driver, CARDNAME, sizeof(info->driver));
547*4882a593Smuzhiyun 	strlcpy(info->bus_info, to_platform_device(dm->dev)->name,
548*4882a593Smuzhiyun 		sizeof(info->bus_info));
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun 
dm9000_get_msglevel(struct net_device * dev)551*4882a593Smuzhiyun static u32 dm9000_get_msglevel(struct net_device *dev)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 	return dm->msg_enable;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun 
dm9000_set_msglevel(struct net_device * dev,u32 value)558*4882a593Smuzhiyun static void dm9000_set_msglevel(struct net_device *dev, u32 value)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	dm->msg_enable = value;
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun 
dm9000_get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * cmd)565*4882a593Smuzhiyun static int dm9000_get_link_ksettings(struct net_device *dev,
566*4882a593Smuzhiyun 				     struct ethtool_link_ksettings *cmd)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	mii_ethtool_get_link_ksettings(&dm->mii, cmd);
571*4882a593Smuzhiyun 	return 0;
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun 
dm9000_set_link_ksettings(struct net_device * dev,const struct ethtool_link_ksettings * cmd)574*4882a593Smuzhiyun static int dm9000_set_link_ksettings(struct net_device *dev,
575*4882a593Smuzhiyun 				     const struct ethtool_link_ksettings *cmd)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	return mii_ethtool_set_link_ksettings(&dm->mii, cmd);
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun 
dm9000_nway_reset(struct net_device * dev)582*4882a593Smuzhiyun static int dm9000_nway_reset(struct net_device *dev)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
585*4882a593Smuzhiyun 	return mii_nway_restart(&dm->mii);
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun 
dm9000_set_features(struct net_device * dev,netdev_features_t features)588*4882a593Smuzhiyun static int dm9000_set_features(struct net_device *dev,
589*4882a593Smuzhiyun 	netdev_features_t features)
590*4882a593Smuzhiyun {
591*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
592*4882a593Smuzhiyun 	netdev_features_t changed = dev->features ^ features;
593*4882a593Smuzhiyun 	unsigned long flags;
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	if (!(changed & NETIF_F_RXCSUM))
596*4882a593Smuzhiyun 		return 0;
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	spin_lock_irqsave(&dm->lock, flags);
599*4882a593Smuzhiyun 	iow(dm, DM9000_RCSR, (features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0);
600*4882a593Smuzhiyun 	spin_unlock_irqrestore(&dm->lock, flags);
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	return 0;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun 
dm9000_get_link(struct net_device * dev)605*4882a593Smuzhiyun static u32 dm9000_get_link(struct net_device *dev)
606*4882a593Smuzhiyun {
607*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
608*4882a593Smuzhiyun 	u32 ret;
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	if (dm->flags & DM9000_PLATF_EXT_PHY)
611*4882a593Smuzhiyun 		ret = mii_link_ok(&dm->mii);
612*4882a593Smuzhiyun 	else
613*4882a593Smuzhiyun 		ret = dm9000_read_locked(dm, DM9000_NSR) & NSR_LINKST ? 1 : 0;
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 	return ret;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun #define DM_EEPROM_MAGIC		(0x444D394B)
619*4882a593Smuzhiyun 
dm9000_get_eeprom_len(struct net_device * dev)620*4882a593Smuzhiyun static int dm9000_get_eeprom_len(struct net_device *dev)
621*4882a593Smuzhiyun {
622*4882a593Smuzhiyun 	return 128;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun 
dm9000_get_eeprom(struct net_device * dev,struct ethtool_eeprom * ee,u8 * data)625*4882a593Smuzhiyun static int dm9000_get_eeprom(struct net_device *dev,
626*4882a593Smuzhiyun 			     struct ethtool_eeprom *ee, u8 *data)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
629*4882a593Smuzhiyun 	int offset = ee->offset;
630*4882a593Smuzhiyun 	int len = ee->len;
631*4882a593Smuzhiyun 	int i;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	/* EEPROM access is aligned to two bytes */
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	if ((len & 1) != 0 || (offset & 1) != 0)
636*4882a593Smuzhiyun 		return -EINVAL;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	if (dm->flags & DM9000_PLATF_NO_EEPROM)
639*4882a593Smuzhiyun 		return -ENOENT;
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	ee->magic = DM_EEPROM_MAGIC;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	for (i = 0; i < len; i += 2)
644*4882a593Smuzhiyun 		dm9000_read_eeprom(dm, (offset + i) / 2, data + i);
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	return 0;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
dm9000_set_eeprom(struct net_device * dev,struct ethtool_eeprom * ee,u8 * data)649*4882a593Smuzhiyun static int dm9000_set_eeprom(struct net_device *dev,
650*4882a593Smuzhiyun 			     struct ethtool_eeprom *ee, u8 *data)
651*4882a593Smuzhiyun {
652*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
653*4882a593Smuzhiyun 	int offset = ee->offset;
654*4882a593Smuzhiyun 	int len = ee->len;
655*4882a593Smuzhiyun 	int done;
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	/* EEPROM access is aligned to two bytes */
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	if (dm->flags & DM9000_PLATF_NO_EEPROM)
660*4882a593Smuzhiyun 		return -ENOENT;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	if (ee->magic != DM_EEPROM_MAGIC)
663*4882a593Smuzhiyun 		return -EINVAL;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	while (len > 0) {
666*4882a593Smuzhiyun 		if (len & 1 || offset & 1) {
667*4882a593Smuzhiyun 			int which = offset & 1;
668*4882a593Smuzhiyun 			u8 tmp[2];
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 			dm9000_read_eeprom(dm, offset / 2, tmp);
671*4882a593Smuzhiyun 			tmp[which] = *data;
672*4882a593Smuzhiyun 			dm9000_write_eeprom(dm, offset / 2, tmp);
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 			done = 1;
675*4882a593Smuzhiyun 		} else {
676*4882a593Smuzhiyun 			dm9000_write_eeprom(dm, offset / 2, data);
677*4882a593Smuzhiyun 			done = 2;
678*4882a593Smuzhiyun 		}
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 		data += done;
681*4882a593Smuzhiyun 		offset += done;
682*4882a593Smuzhiyun 		len -= done;
683*4882a593Smuzhiyun 	}
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	return 0;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun 
dm9000_get_wol(struct net_device * dev,struct ethtool_wolinfo * w)688*4882a593Smuzhiyun static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	memset(w, 0, sizeof(struct ethtool_wolinfo));
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	/* note, we could probably support wake-phy too */
695*4882a593Smuzhiyun 	w->supported = dm->wake_supported ? WAKE_MAGIC : 0;
696*4882a593Smuzhiyun 	w->wolopts = dm->wake_state;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun 
dm9000_set_wol(struct net_device * dev,struct ethtool_wolinfo * w)699*4882a593Smuzhiyun static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
702*4882a593Smuzhiyun 	unsigned long flags;
703*4882a593Smuzhiyun 	u32 opts = w->wolopts;
704*4882a593Smuzhiyun 	u32 wcr = 0;
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	if (!dm->wake_supported)
707*4882a593Smuzhiyun 		return -EOPNOTSUPP;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	if (opts & ~WAKE_MAGIC)
710*4882a593Smuzhiyun 		return -EINVAL;
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	if (opts & WAKE_MAGIC)
713*4882a593Smuzhiyun 		wcr |= WCR_MAGICEN;
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	mutex_lock(&dm->addr_lock);
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 	spin_lock_irqsave(&dm->lock, flags);
718*4882a593Smuzhiyun 	iow(dm, DM9000_WCR, wcr);
719*4882a593Smuzhiyun 	spin_unlock_irqrestore(&dm->lock, flags);
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	mutex_unlock(&dm->addr_lock);
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	if (dm->wake_state != opts) {
724*4882a593Smuzhiyun 		/* change in wol state, update IRQ state */
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 		if (!dm->wake_state)
727*4882a593Smuzhiyun 			irq_set_irq_wake(dm->irq_wake, 1);
728*4882a593Smuzhiyun 		else if (dm->wake_state && !opts)
729*4882a593Smuzhiyun 			irq_set_irq_wake(dm->irq_wake, 0);
730*4882a593Smuzhiyun 	}
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 	dm->wake_state = opts;
733*4882a593Smuzhiyun 	return 0;
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun static const struct ethtool_ops dm9000_ethtool_ops = {
737*4882a593Smuzhiyun 	.get_drvinfo		= dm9000_get_drvinfo,
738*4882a593Smuzhiyun 	.get_msglevel		= dm9000_get_msglevel,
739*4882a593Smuzhiyun 	.set_msglevel		= dm9000_set_msglevel,
740*4882a593Smuzhiyun 	.nway_reset		= dm9000_nway_reset,
741*4882a593Smuzhiyun 	.get_link		= dm9000_get_link,
742*4882a593Smuzhiyun 	.get_wol		= dm9000_get_wol,
743*4882a593Smuzhiyun 	.set_wol		= dm9000_set_wol,
744*4882a593Smuzhiyun 	.get_eeprom_len		= dm9000_get_eeprom_len,
745*4882a593Smuzhiyun 	.get_eeprom		= dm9000_get_eeprom,
746*4882a593Smuzhiyun 	.set_eeprom		= dm9000_set_eeprom,
747*4882a593Smuzhiyun 	.get_link_ksettings	= dm9000_get_link_ksettings,
748*4882a593Smuzhiyun 	.set_link_ksettings	= dm9000_set_link_ksettings,
749*4882a593Smuzhiyun };
750*4882a593Smuzhiyun 
dm9000_show_carrier(struct board_info * db,unsigned carrier,unsigned nsr)751*4882a593Smuzhiyun static void dm9000_show_carrier(struct board_info *db,
752*4882a593Smuzhiyun 				unsigned carrier, unsigned nsr)
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun 	int lpa;
755*4882a593Smuzhiyun 	struct net_device *ndev = db->ndev;
756*4882a593Smuzhiyun 	struct mii_if_info *mii = &db->mii;
757*4882a593Smuzhiyun 	unsigned ncr = dm9000_read_locked(db, DM9000_NCR);
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	if (carrier) {
760*4882a593Smuzhiyun 		lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
761*4882a593Smuzhiyun 		dev_info(db->dev,
762*4882a593Smuzhiyun 			 "%s: link up, %dMbps, %s-duplex, lpa 0x%04X\n",
763*4882a593Smuzhiyun 			 ndev->name, (nsr & NSR_SPEED) ? 10 : 100,
764*4882a593Smuzhiyun 			 (ncr & NCR_FDX) ? "full" : "half", lpa);
765*4882a593Smuzhiyun 	} else {
766*4882a593Smuzhiyun 		dev_info(db->dev, "%s: link down\n", ndev->name);
767*4882a593Smuzhiyun 	}
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun static void
dm9000_poll_work(struct work_struct * w)771*4882a593Smuzhiyun dm9000_poll_work(struct work_struct *w)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun 	struct delayed_work *dw = to_delayed_work(w);
774*4882a593Smuzhiyun 	struct board_info *db = container_of(dw, struct board_info, phy_poll);
775*4882a593Smuzhiyun 	struct net_device *ndev = db->ndev;
776*4882a593Smuzhiyun 
777*4882a593Smuzhiyun 	if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
778*4882a593Smuzhiyun 	    !(db->flags & DM9000_PLATF_EXT_PHY)) {
779*4882a593Smuzhiyun 		unsigned nsr = dm9000_read_locked(db, DM9000_NSR);
780*4882a593Smuzhiyun 		unsigned old_carrier = netif_carrier_ok(ndev) ? 1 : 0;
781*4882a593Smuzhiyun 		unsigned new_carrier;
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 		new_carrier = (nsr & NSR_LINKST) ? 1 : 0;
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 		if (old_carrier != new_carrier) {
786*4882a593Smuzhiyun 			if (netif_msg_link(db))
787*4882a593Smuzhiyun 				dm9000_show_carrier(db, new_carrier, nsr);
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 			if (!new_carrier)
790*4882a593Smuzhiyun 				netif_carrier_off(ndev);
791*4882a593Smuzhiyun 			else
792*4882a593Smuzhiyun 				netif_carrier_on(ndev);
793*4882a593Smuzhiyun 		}
794*4882a593Smuzhiyun 	} else
795*4882a593Smuzhiyun 		mii_check_media(&db->mii, netif_msg_link(db), 0);
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	if (netif_running(ndev))
798*4882a593Smuzhiyun 		dm9000_schedule_poll(db);
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun /* dm9000_release_board
802*4882a593Smuzhiyun  *
803*4882a593Smuzhiyun  * release a board, and any mapped resources
804*4882a593Smuzhiyun  */
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun static void
dm9000_release_board(struct platform_device * pdev,struct board_info * db)807*4882a593Smuzhiyun dm9000_release_board(struct platform_device *pdev, struct board_info *db)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun 	/* unmap our resources */
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun 	iounmap(db->io_addr);
812*4882a593Smuzhiyun 	iounmap(db->io_data);
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 	/* release the resources */
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun 	if (db->data_req)
817*4882a593Smuzhiyun 		release_resource(db->data_req);
818*4882a593Smuzhiyun 	kfree(db->data_req);
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 	if (db->addr_req)
821*4882a593Smuzhiyun 		release_resource(db->addr_req);
822*4882a593Smuzhiyun 	kfree(db->addr_req);
823*4882a593Smuzhiyun }
824*4882a593Smuzhiyun 
dm9000_type_to_char(enum dm9000_type type)825*4882a593Smuzhiyun static unsigned char dm9000_type_to_char(enum dm9000_type type)
826*4882a593Smuzhiyun {
827*4882a593Smuzhiyun 	switch (type) {
828*4882a593Smuzhiyun 	case TYPE_DM9000E: return 'e';
829*4882a593Smuzhiyun 	case TYPE_DM9000A: return 'a';
830*4882a593Smuzhiyun 	case TYPE_DM9000B: return 'b';
831*4882a593Smuzhiyun 	}
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun 	return '?';
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun /*
837*4882a593Smuzhiyun  *  Set DM9000 multicast address
838*4882a593Smuzhiyun  */
839*4882a593Smuzhiyun static void
dm9000_hash_table_unlocked(struct net_device * dev)840*4882a593Smuzhiyun dm9000_hash_table_unlocked(struct net_device *dev)
841*4882a593Smuzhiyun {
842*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
843*4882a593Smuzhiyun 	struct netdev_hw_addr *ha;
844*4882a593Smuzhiyun 	int i, oft;
845*4882a593Smuzhiyun 	u32 hash_val;
846*4882a593Smuzhiyun 	u16 hash_table[4] = { 0, 0, 0, 0x8000 }; /* broadcast address */
847*4882a593Smuzhiyun 	u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun 	dm9000_dbg(db, 1, "entering %s\n", __func__);
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
852*4882a593Smuzhiyun 		iow(db, oft, dev->dev_addr[i]);
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun 	if (dev->flags & IFF_PROMISC)
855*4882a593Smuzhiyun 		rcr |= RCR_PRMSC;
856*4882a593Smuzhiyun 
857*4882a593Smuzhiyun 	if (dev->flags & IFF_ALLMULTI)
858*4882a593Smuzhiyun 		rcr |= RCR_ALL;
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	/* the multicast address in Hash Table : 64 bits */
861*4882a593Smuzhiyun 	netdev_for_each_mc_addr(ha, dev) {
862*4882a593Smuzhiyun 		hash_val = ether_crc_le(6, ha->addr) & 0x3f;
863*4882a593Smuzhiyun 		hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
864*4882a593Smuzhiyun 	}
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun 	/* Write the hash table to MAC MD table */
867*4882a593Smuzhiyun 	for (i = 0, oft = DM9000_MAR; i < 4; i++) {
868*4882a593Smuzhiyun 		iow(db, oft++, hash_table[i]);
869*4882a593Smuzhiyun 		iow(db, oft++, hash_table[i] >> 8);
870*4882a593Smuzhiyun 	}
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	iow(db, DM9000_RCR, rcr);
873*4882a593Smuzhiyun }
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun static void
dm9000_hash_table(struct net_device * dev)876*4882a593Smuzhiyun dm9000_hash_table(struct net_device *dev)
877*4882a593Smuzhiyun {
878*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
879*4882a593Smuzhiyun 	unsigned long flags;
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
882*4882a593Smuzhiyun 	dm9000_hash_table_unlocked(dev);
883*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
884*4882a593Smuzhiyun }
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun static void
dm9000_mask_interrupts(struct board_info * db)887*4882a593Smuzhiyun dm9000_mask_interrupts(struct board_info *db)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun 	iow(db, DM9000_IMR, IMR_PAR);
890*4882a593Smuzhiyun }
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun static void
dm9000_unmask_interrupts(struct board_info * db)893*4882a593Smuzhiyun dm9000_unmask_interrupts(struct board_info *db)
894*4882a593Smuzhiyun {
895*4882a593Smuzhiyun 	iow(db, DM9000_IMR, db->imr_all);
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun 
898*4882a593Smuzhiyun /*
899*4882a593Smuzhiyun  * Initialize dm9000 board
900*4882a593Smuzhiyun  */
901*4882a593Smuzhiyun static void
dm9000_init_dm9000(struct net_device * dev)902*4882a593Smuzhiyun dm9000_init_dm9000(struct net_device *dev)
903*4882a593Smuzhiyun {
904*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
905*4882a593Smuzhiyun 	unsigned int imr;
906*4882a593Smuzhiyun 	unsigned int ncr;
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun 	dm9000_dbg(db, 1, "entering %s\n", __func__);
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun 	dm9000_reset(db);
911*4882a593Smuzhiyun 	dm9000_mask_interrupts(db);
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun 	/* I/O mode */
914*4882a593Smuzhiyun 	db->io_mode = ior(db, DM9000_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 	/* Checksum mode */
917*4882a593Smuzhiyun 	if (dev->hw_features & NETIF_F_RXCSUM)
918*4882a593Smuzhiyun 		iow(db, DM9000_RCSR,
919*4882a593Smuzhiyun 			(dev->features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0);
920*4882a593Smuzhiyun 
921*4882a593Smuzhiyun 	iow(db, DM9000_GPCR, GPCR_GEP_CNTL);	/* Let GPIO0 output */
922*4882a593Smuzhiyun 	iow(db, DM9000_GPR, 0);
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	/* If we are dealing with DM9000B, some extra steps are required: a
925*4882a593Smuzhiyun 	 * manual phy reset, and setting init params.
926*4882a593Smuzhiyun 	 */
927*4882a593Smuzhiyun 	if (db->type == TYPE_DM9000B) {
928*4882a593Smuzhiyun 		dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);
929*4882a593Smuzhiyun 		dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM);
930*4882a593Smuzhiyun 	}
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun 	ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun 	/* if wol is needed, then always set NCR_WAKEEN otherwise we end
935*4882a593Smuzhiyun 	 * up dumping the wake events if we disable this. There is already
936*4882a593Smuzhiyun 	 * a wake-mask in DM9000_WCR */
937*4882a593Smuzhiyun 	if (db->wake_supported)
938*4882a593Smuzhiyun 		ncr |= NCR_WAKEEN;
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 	iow(db, DM9000_NCR, ncr);
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 	/* Program operating register */
943*4882a593Smuzhiyun 	iow(db, DM9000_TCR, 0);	        /* TX Polling clear */
944*4882a593Smuzhiyun 	iow(db, DM9000_BPTR, 0x3f);	/* Less 3Kb, 200us */
945*4882a593Smuzhiyun 	iow(db, DM9000_FCR, 0xff);	/* Flow Control */
946*4882a593Smuzhiyun 	iow(db, DM9000_SMCR, 0);        /* Special Mode */
947*4882a593Smuzhiyun 	/* clear TX status */
948*4882a593Smuzhiyun 	iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
949*4882a593Smuzhiyun 	iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */
950*4882a593Smuzhiyun 
951*4882a593Smuzhiyun 	/* Set address filter table */
952*4882a593Smuzhiyun 	dm9000_hash_table_unlocked(dev);
953*4882a593Smuzhiyun 
954*4882a593Smuzhiyun 	imr = IMR_PAR | IMR_PTM | IMR_PRM;
955*4882a593Smuzhiyun 	if (db->type != TYPE_DM9000E)
956*4882a593Smuzhiyun 		imr |= IMR_LNKCHNG;
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	db->imr_all = imr;
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun 	/* Init Driver variable */
961*4882a593Smuzhiyun 	db->tx_pkt_cnt = 0;
962*4882a593Smuzhiyun 	db->queue_pkt_len = 0;
963*4882a593Smuzhiyun 	netif_trans_update(dev);
964*4882a593Smuzhiyun }
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun /* Our watchdog timed out. Called by the networking layer */
dm9000_timeout(struct net_device * dev,unsigned int txqueue)967*4882a593Smuzhiyun static void dm9000_timeout(struct net_device *dev, unsigned int txqueue)
968*4882a593Smuzhiyun {
969*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
970*4882a593Smuzhiyun 	u8 reg_save;
971*4882a593Smuzhiyun 	unsigned long flags;
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun 	/* Save previous register address */
974*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
975*4882a593Smuzhiyun 	db->in_timeout = 1;
976*4882a593Smuzhiyun 	reg_save = readb(db->io_addr);
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun 	netif_stop_queue(dev);
979*4882a593Smuzhiyun 	dm9000_init_dm9000(dev);
980*4882a593Smuzhiyun 	dm9000_unmask_interrupts(db);
981*4882a593Smuzhiyun 	/* We can accept TX packets again */
982*4882a593Smuzhiyun 	netif_trans_update(dev); /* prevent tx timeout */
983*4882a593Smuzhiyun 	netif_wake_queue(dev);
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun 	/* Restore previous register address */
986*4882a593Smuzhiyun 	writeb(reg_save, db->io_addr);
987*4882a593Smuzhiyun 	db->in_timeout = 0;
988*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun 
dm9000_send_packet(struct net_device * dev,int ip_summed,u16 pkt_len)991*4882a593Smuzhiyun static void dm9000_send_packet(struct net_device *dev,
992*4882a593Smuzhiyun 			       int ip_summed,
993*4882a593Smuzhiyun 			       u16 pkt_len)
994*4882a593Smuzhiyun {
995*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(dev);
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun 	/* The DM9000 is not smart enough to leave fragmented packets alone. */
998*4882a593Smuzhiyun 	if (dm->ip_summed != ip_summed) {
999*4882a593Smuzhiyun 		if (ip_summed == CHECKSUM_NONE)
1000*4882a593Smuzhiyun 			iow(dm, DM9000_TCCR, 0);
1001*4882a593Smuzhiyun 		else
1002*4882a593Smuzhiyun 			iow(dm, DM9000_TCCR, TCCR_IP | TCCR_UDP | TCCR_TCP);
1003*4882a593Smuzhiyun 		dm->ip_summed = ip_summed;
1004*4882a593Smuzhiyun 	}
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	/* Set TX length to DM9000 */
1007*4882a593Smuzhiyun 	iow(dm, DM9000_TXPLL, pkt_len);
1008*4882a593Smuzhiyun 	iow(dm, DM9000_TXPLH, pkt_len >> 8);
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun 	/* Issue TX polling command */
1011*4882a593Smuzhiyun 	iow(dm, DM9000_TCR, TCR_TXREQ);	/* Cleared after TX complete */
1012*4882a593Smuzhiyun }
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun /*
1015*4882a593Smuzhiyun  *  Hardware start transmission.
1016*4882a593Smuzhiyun  *  Send a packet to media from the upper layer.
1017*4882a593Smuzhiyun  */
1018*4882a593Smuzhiyun static int
dm9000_start_xmit(struct sk_buff * skb,struct net_device * dev)1019*4882a593Smuzhiyun dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
1020*4882a593Smuzhiyun {
1021*4882a593Smuzhiyun 	unsigned long flags;
1022*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun 	dm9000_dbg(db, 3, "%s:\n", __func__);
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun 	if (db->tx_pkt_cnt > 1)
1027*4882a593Smuzhiyun 		return NETDEV_TX_BUSY;
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun 	/* Move data to DM9000 TX RAM */
1032*4882a593Smuzhiyun 	writeb(DM9000_MWCMD, db->io_addr);
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	(db->outblk)(db->io_data, skb->data, skb->len);
1035*4882a593Smuzhiyun 	dev->stats.tx_bytes += skb->len;
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun 	db->tx_pkt_cnt++;
1038*4882a593Smuzhiyun 	/* TX control: First packet immediately send, second packet queue */
1039*4882a593Smuzhiyun 	if (db->tx_pkt_cnt == 1) {
1040*4882a593Smuzhiyun 		dm9000_send_packet(dev, skb->ip_summed, skb->len);
1041*4882a593Smuzhiyun 	} else {
1042*4882a593Smuzhiyun 		/* Second packet */
1043*4882a593Smuzhiyun 		db->queue_pkt_len = skb->len;
1044*4882a593Smuzhiyun 		db->queue_ip_summed = skb->ip_summed;
1045*4882a593Smuzhiyun 		netif_stop_queue(dev);
1046*4882a593Smuzhiyun 	}
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun 	/* free this SKB */
1051*4882a593Smuzhiyun 	dev_consume_skb_any(skb);
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun 	return NETDEV_TX_OK;
1054*4882a593Smuzhiyun }
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun /*
1057*4882a593Smuzhiyun  * DM9000 interrupt handler
1058*4882a593Smuzhiyun  * receive the packet to upper layer, free the transmitted packet
1059*4882a593Smuzhiyun  */
1060*4882a593Smuzhiyun 
dm9000_tx_done(struct net_device * dev,struct board_info * db)1061*4882a593Smuzhiyun static void dm9000_tx_done(struct net_device *dev, struct board_info *db)
1062*4882a593Smuzhiyun {
1063*4882a593Smuzhiyun 	int tx_status = ior(db, DM9000_NSR);	/* Got TX status */
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun 	if (tx_status & (NSR_TX2END | NSR_TX1END)) {
1066*4882a593Smuzhiyun 		/* One packet sent complete */
1067*4882a593Smuzhiyun 		db->tx_pkt_cnt--;
1068*4882a593Smuzhiyun 		dev->stats.tx_packets++;
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun 		if (netif_msg_tx_done(db))
1071*4882a593Smuzhiyun 			dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
1072*4882a593Smuzhiyun 
1073*4882a593Smuzhiyun 		/* Queue packet check & send */
1074*4882a593Smuzhiyun 		if (db->tx_pkt_cnt > 0)
1075*4882a593Smuzhiyun 			dm9000_send_packet(dev, db->queue_ip_summed,
1076*4882a593Smuzhiyun 					   db->queue_pkt_len);
1077*4882a593Smuzhiyun 		netif_wake_queue(dev);
1078*4882a593Smuzhiyun 	}
1079*4882a593Smuzhiyun }
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun struct dm9000_rxhdr {
1082*4882a593Smuzhiyun 	u8	RxPktReady;
1083*4882a593Smuzhiyun 	u8	RxStatus;
1084*4882a593Smuzhiyun 	__le16	RxLen;
1085*4882a593Smuzhiyun } __packed;
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun /*
1088*4882a593Smuzhiyun  *  Received a packet and pass to upper layer
1089*4882a593Smuzhiyun  */
1090*4882a593Smuzhiyun static void
dm9000_rx(struct net_device * dev)1091*4882a593Smuzhiyun dm9000_rx(struct net_device *dev)
1092*4882a593Smuzhiyun {
1093*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
1094*4882a593Smuzhiyun 	struct dm9000_rxhdr rxhdr;
1095*4882a593Smuzhiyun 	struct sk_buff *skb;
1096*4882a593Smuzhiyun 	u8 rxbyte, *rdptr;
1097*4882a593Smuzhiyun 	bool GoodPacket;
1098*4882a593Smuzhiyun 	int RxLen;
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun 	/* Check packet ready or not */
1101*4882a593Smuzhiyun 	do {
1102*4882a593Smuzhiyun 		ior(db, DM9000_MRCMDX);	/* Dummy read */
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun 		/* Get most updated data */
1105*4882a593Smuzhiyun 		rxbyte = readb(db->io_data);
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun 		/* Status check: this byte must be 0 or 1 */
1108*4882a593Smuzhiyun 		if (rxbyte & DM9000_PKT_ERR) {
1109*4882a593Smuzhiyun 			dev_warn(db->dev, "status check fail: %d\n", rxbyte);
1110*4882a593Smuzhiyun 			iow(db, DM9000_RCR, 0x00);	/* Stop Device */
1111*4882a593Smuzhiyun 			return;
1112*4882a593Smuzhiyun 		}
1113*4882a593Smuzhiyun 
1114*4882a593Smuzhiyun 		if (!(rxbyte & DM9000_PKT_RDY))
1115*4882a593Smuzhiyun 			return;
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun 		/* A packet ready now  & Get status/length */
1118*4882a593Smuzhiyun 		GoodPacket = true;
1119*4882a593Smuzhiyun 		writeb(DM9000_MRCMD, db->io_addr);
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun 		(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun 		RxLen = le16_to_cpu(rxhdr.RxLen);
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun 		if (netif_msg_rx_status(db))
1126*4882a593Smuzhiyun 			dev_dbg(db->dev, "RX: status %02x, length %04x\n",
1127*4882a593Smuzhiyun 				rxhdr.RxStatus, RxLen);
1128*4882a593Smuzhiyun 
1129*4882a593Smuzhiyun 		/* Packet Status check */
1130*4882a593Smuzhiyun 		if (RxLen < 0x40) {
1131*4882a593Smuzhiyun 			GoodPacket = false;
1132*4882a593Smuzhiyun 			if (netif_msg_rx_err(db))
1133*4882a593Smuzhiyun 				dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
1134*4882a593Smuzhiyun 		}
1135*4882a593Smuzhiyun 
1136*4882a593Smuzhiyun 		if (RxLen > DM9000_PKT_MAX) {
1137*4882a593Smuzhiyun 			dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
1138*4882a593Smuzhiyun 		}
1139*4882a593Smuzhiyun 
1140*4882a593Smuzhiyun 		/* rxhdr.RxStatus is identical to RSR register. */
1141*4882a593Smuzhiyun 		if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
1142*4882a593Smuzhiyun 				      RSR_PLE | RSR_RWTO |
1143*4882a593Smuzhiyun 				      RSR_LCS | RSR_RF)) {
1144*4882a593Smuzhiyun 			GoodPacket = false;
1145*4882a593Smuzhiyun 			if (rxhdr.RxStatus & RSR_FOE) {
1146*4882a593Smuzhiyun 				if (netif_msg_rx_err(db))
1147*4882a593Smuzhiyun 					dev_dbg(db->dev, "fifo error\n");
1148*4882a593Smuzhiyun 				dev->stats.rx_fifo_errors++;
1149*4882a593Smuzhiyun 			}
1150*4882a593Smuzhiyun 			if (rxhdr.RxStatus & RSR_CE) {
1151*4882a593Smuzhiyun 				if (netif_msg_rx_err(db))
1152*4882a593Smuzhiyun 					dev_dbg(db->dev, "crc error\n");
1153*4882a593Smuzhiyun 				dev->stats.rx_crc_errors++;
1154*4882a593Smuzhiyun 			}
1155*4882a593Smuzhiyun 			if (rxhdr.RxStatus & RSR_RF) {
1156*4882a593Smuzhiyun 				if (netif_msg_rx_err(db))
1157*4882a593Smuzhiyun 					dev_dbg(db->dev, "length error\n");
1158*4882a593Smuzhiyun 				dev->stats.rx_length_errors++;
1159*4882a593Smuzhiyun 			}
1160*4882a593Smuzhiyun 		}
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun 		/* Move data from DM9000 */
1163*4882a593Smuzhiyun 		if (GoodPacket &&
1164*4882a593Smuzhiyun 		    ((skb = netdev_alloc_skb(dev, RxLen + 4)) != NULL)) {
1165*4882a593Smuzhiyun 			skb_reserve(skb, 2);
1166*4882a593Smuzhiyun 			rdptr = skb_put(skb, RxLen - 4);
1167*4882a593Smuzhiyun 
1168*4882a593Smuzhiyun 			/* Read received packet from RX SRAM */
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun 			(db->inblk)(db->io_data, rdptr, RxLen);
1171*4882a593Smuzhiyun 			dev->stats.rx_bytes += RxLen;
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 			/* Pass to upper layer */
1174*4882a593Smuzhiyun 			skb->protocol = eth_type_trans(skb, dev);
1175*4882a593Smuzhiyun 			if (dev->features & NETIF_F_RXCSUM) {
1176*4882a593Smuzhiyun 				if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)
1177*4882a593Smuzhiyun 					skb->ip_summed = CHECKSUM_UNNECESSARY;
1178*4882a593Smuzhiyun 				else
1179*4882a593Smuzhiyun 					skb_checksum_none_assert(skb);
1180*4882a593Smuzhiyun 			}
1181*4882a593Smuzhiyun 			netif_rx(skb);
1182*4882a593Smuzhiyun 			dev->stats.rx_packets++;
1183*4882a593Smuzhiyun 
1184*4882a593Smuzhiyun 		} else {
1185*4882a593Smuzhiyun 			/* need to dump the packet's data */
1186*4882a593Smuzhiyun 
1187*4882a593Smuzhiyun 			(db->dumpblk)(db->io_data, RxLen);
1188*4882a593Smuzhiyun 		}
1189*4882a593Smuzhiyun 	} while (rxbyte & DM9000_PKT_RDY);
1190*4882a593Smuzhiyun }
1191*4882a593Smuzhiyun 
dm9000_interrupt(int irq,void * dev_id)1192*4882a593Smuzhiyun static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
1193*4882a593Smuzhiyun {
1194*4882a593Smuzhiyun 	struct net_device *dev = dev_id;
1195*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
1196*4882a593Smuzhiyun 	int int_status;
1197*4882a593Smuzhiyun 	unsigned long flags;
1198*4882a593Smuzhiyun 	u8 reg_save;
1199*4882a593Smuzhiyun 
1200*4882a593Smuzhiyun 	dm9000_dbg(db, 3, "entering %s\n", __func__);
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun 	/* A real interrupt coming */
1203*4882a593Smuzhiyun 
1204*4882a593Smuzhiyun 	/* holders of db->lock must always block IRQs */
1205*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
1206*4882a593Smuzhiyun 
1207*4882a593Smuzhiyun 	/* Save previous register address */
1208*4882a593Smuzhiyun 	reg_save = readb(db->io_addr);
1209*4882a593Smuzhiyun 
1210*4882a593Smuzhiyun 	dm9000_mask_interrupts(db);
1211*4882a593Smuzhiyun 	/* Got DM9000 interrupt status */
1212*4882a593Smuzhiyun 	int_status = ior(db, DM9000_ISR);	/* Got ISR */
1213*4882a593Smuzhiyun 	iow(db, DM9000_ISR, int_status);	/* Clear ISR status */
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun 	if (netif_msg_intr(db))
1216*4882a593Smuzhiyun 		dev_dbg(db->dev, "interrupt status %02x\n", int_status);
1217*4882a593Smuzhiyun 
1218*4882a593Smuzhiyun 	/* Received the coming packet */
1219*4882a593Smuzhiyun 	if (int_status & ISR_PRS)
1220*4882a593Smuzhiyun 		dm9000_rx(dev);
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun 	/* Transmit Interrupt check */
1223*4882a593Smuzhiyun 	if (int_status & ISR_PTS)
1224*4882a593Smuzhiyun 		dm9000_tx_done(dev, db);
1225*4882a593Smuzhiyun 
1226*4882a593Smuzhiyun 	if (db->type != TYPE_DM9000E) {
1227*4882a593Smuzhiyun 		if (int_status & ISR_LNKCHNG) {
1228*4882a593Smuzhiyun 			/* fire a link-change request */
1229*4882a593Smuzhiyun 			schedule_delayed_work(&db->phy_poll, 1);
1230*4882a593Smuzhiyun 		}
1231*4882a593Smuzhiyun 	}
1232*4882a593Smuzhiyun 
1233*4882a593Smuzhiyun 	dm9000_unmask_interrupts(db);
1234*4882a593Smuzhiyun 	/* Restore previous register address */
1235*4882a593Smuzhiyun 	writeb(reg_save, db->io_addr);
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
1238*4882a593Smuzhiyun 
1239*4882a593Smuzhiyun 	return IRQ_HANDLED;
1240*4882a593Smuzhiyun }
1241*4882a593Smuzhiyun 
dm9000_wol_interrupt(int irq,void * dev_id)1242*4882a593Smuzhiyun static irqreturn_t dm9000_wol_interrupt(int irq, void *dev_id)
1243*4882a593Smuzhiyun {
1244*4882a593Smuzhiyun 	struct net_device *dev = dev_id;
1245*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
1246*4882a593Smuzhiyun 	unsigned long flags;
1247*4882a593Smuzhiyun 	unsigned nsr, wcr;
1248*4882a593Smuzhiyun 
1249*4882a593Smuzhiyun 	spin_lock_irqsave(&db->lock, flags);
1250*4882a593Smuzhiyun 
1251*4882a593Smuzhiyun 	nsr = ior(db, DM9000_NSR);
1252*4882a593Smuzhiyun 	wcr = ior(db, DM9000_WCR);
1253*4882a593Smuzhiyun 
1254*4882a593Smuzhiyun 	dev_dbg(db->dev, "%s: NSR=0x%02x, WCR=0x%02x\n", __func__, nsr, wcr);
1255*4882a593Smuzhiyun 
1256*4882a593Smuzhiyun 	if (nsr & NSR_WAKEST) {
1257*4882a593Smuzhiyun 		/* clear, so we can avoid */
1258*4882a593Smuzhiyun 		iow(db, DM9000_NSR, NSR_WAKEST);
1259*4882a593Smuzhiyun 
1260*4882a593Smuzhiyun 		if (wcr & WCR_LINKST)
1261*4882a593Smuzhiyun 			dev_info(db->dev, "wake by link status change\n");
1262*4882a593Smuzhiyun 		if (wcr & WCR_SAMPLEST)
1263*4882a593Smuzhiyun 			dev_info(db->dev, "wake by sample packet\n");
1264*4882a593Smuzhiyun 		if (wcr & WCR_MAGICST)
1265*4882a593Smuzhiyun 			dev_info(db->dev, "wake by magic packet\n");
1266*4882a593Smuzhiyun 		if (!(wcr & (WCR_LINKST | WCR_SAMPLEST | WCR_MAGICST)))
1267*4882a593Smuzhiyun 			dev_err(db->dev, "wake signalled with no reason? "
1268*4882a593Smuzhiyun 				"NSR=0x%02x, WSR=0x%02x\n", nsr, wcr);
1269*4882a593Smuzhiyun 	}
1270*4882a593Smuzhiyun 
1271*4882a593Smuzhiyun 	spin_unlock_irqrestore(&db->lock, flags);
1272*4882a593Smuzhiyun 
1273*4882a593Smuzhiyun 	return (nsr & NSR_WAKEST) ? IRQ_HANDLED : IRQ_NONE;
1274*4882a593Smuzhiyun }
1275*4882a593Smuzhiyun 
1276*4882a593Smuzhiyun #ifdef CONFIG_NET_POLL_CONTROLLER
1277*4882a593Smuzhiyun /*
1278*4882a593Smuzhiyun  *Used by netconsole
1279*4882a593Smuzhiyun  */
dm9000_poll_controller(struct net_device * dev)1280*4882a593Smuzhiyun static void dm9000_poll_controller(struct net_device *dev)
1281*4882a593Smuzhiyun {
1282*4882a593Smuzhiyun 	disable_irq(dev->irq);
1283*4882a593Smuzhiyun 	dm9000_interrupt(dev->irq, dev);
1284*4882a593Smuzhiyun 	enable_irq(dev->irq);
1285*4882a593Smuzhiyun }
1286*4882a593Smuzhiyun #endif
1287*4882a593Smuzhiyun 
1288*4882a593Smuzhiyun /*
1289*4882a593Smuzhiyun  *  Open the interface.
1290*4882a593Smuzhiyun  *  The interface is opened whenever "ifconfig" actives it.
1291*4882a593Smuzhiyun  */
1292*4882a593Smuzhiyun static int
dm9000_open(struct net_device * dev)1293*4882a593Smuzhiyun dm9000_open(struct net_device *dev)
1294*4882a593Smuzhiyun {
1295*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
1296*4882a593Smuzhiyun 	unsigned int irq_flags = irq_get_trigger_type(dev->irq);
1297*4882a593Smuzhiyun 
1298*4882a593Smuzhiyun 	if (netif_msg_ifup(db))
1299*4882a593Smuzhiyun 		dev_dbg(db->dev, "enabling %s\n", dev->name);
1300*4882a593Smuzhiyun 
1301*4882a593Smuzhiyun 	/* If there is no IRQ type specified, tell the user that this is a
1302*4882a593Smuzhiyun 	 * problem
1303*4882a593Smuzhiyun 	 */
1304*4882a593Smuzhiyun 	if (irq_flags == IRQF_TRIGGER_NONE)
1305*4882a593Smuzhiyun 		dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
1306*4882a593Smuzhiyun 
1307*4882a593Smuzhiyun 	irq_flags |= IRQF_SHARED;
1308*4882a593Smuzhiyun 
1309*4882a593Smuzhiyun 	/* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */
1310*4882a593Smuzhiyun 	iow(db, DM9000_GPR, 0);	/* REG_1F bit0 activate phyxcer */
1311*4882a593Smuzhiyun 	mdelay(1); /* delay needs by DM9000B */
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun 	/* Initialize DM9000 board */
1314*4882a593Smuzhiyun 	dm9000_init_dm9000(dev);
1315*4882a593Smuzhiyun 
1316*4882a593Smuzhiyun 	if (request_irq(dev->irq, dm9000_interrupt, irq_flags, dev->name, dev))
1317*4882a593Smuzhiyun 		return -EAGAIN;
1318*4882a593Smuzhiyun 	/* Now that we have an interrupt handler hooked up we can unmask
1319*4882a593Smuzhiyun 	 * our interrupts
1320*4882a593Smuzhiyun 	 */
1321*4882a593Smuzhiyun 	dm9000_unmask_interrupts(db);
1322*4882a593Smuzhiyun 
1323*4882a593Smuzhiyun 	/* Init driver variable */
1324*4882a593Smuzhiyun 	db->dbug_cnt = 0;
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun 	mii_check_media(&db->mii, netif_msg_link(db), 1);
1327*4882a593Smuzhiyun 	netif_start_queue(dev);
1328*4882a593Smuzhiyun 
1329*4882a593Smuzhiyun 	/* Poll initial link status */
1330*4882a593Smuzhiyun 	schedule_delayed_work(&db->phy_poll, 1);
1331*4882a593Smuzhiyun 
1332*4882a593Smuzhiyun 	return 0;
1333*4882a593Smuzhiyun }
1334*4882a593Smuzhiyun 
1335*4882a593Smuzhiyun static void
dm9000_shutdown(struct net_device * dev)1336*4882a593Smuzhiyun dm9000_shutdown(struct net_device *dev)
1337*4882a593Smuzhiyun {
1338*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(dev);
1339*4882a593Smuzhiyun 
1340*4882a593Smuzhiyun 	/* RESET device */
1341*4882a593Smuzhiyun 	dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);	/* PHY RESET */
1342*4882a593Smuzhiyun 	iow(db, DM9000_GPR, 0x01);	/* Power-Down PHY */
1343*4882a593Smuzhiyun 	dm9000_mask_interrupts(db);
1344*4882a593Smuzhiyun 	iow(db, DM9000_RCR, 0x00);	/* Disable RX */
1345*4882a593Smuzhiyun }
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun /*
1348*4882a593Smuzhiyun  * Stop the interface.
1349*4882a593Smuzhiyun  * The interface is stopped when it is brought.
1350*4882a593Smuzhiyun  */
1351*4882a593Smuzhiyun static int
dm9000_stop(struct net_device * ndev)1352*4882a593Smuzhiyun dm9000_stop(struct net_device *ndev)
1353*4882a593Smuzhiyun {
1354*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(ndev);
1355*4882a593Smuzhiyun 
1356*4882a593Smuzhiyun 	if (netif_msg_ifdown(db))
1357*4882a593Smuzhiyun 		dev_dbg(db->dev, "shutting down %s\n", ndev->name);
1358*4882a593Smuzhiyun 
1359*4882a593Smuzhiyun 	cancel_delayed_work_sync(&db->phy_poll);
1360*4882a593Smuzhiyun 
1361*4882a593Smuzhiyun 	netif_stop_queue(ndev);
1362*4882a593Smuzhiyun 	netif_carrier_off(ndev);
1363*4882a593Smuzhiyun 
1364*4882a593Smuzhiyun 	/* free interrupt */
1365*4882a593Smuzhiyun 	free_irq(ndev->irq, ndev);
1366*4882a593Smuzhiyun 
1367*4882a593Smuzhiyun 	dm9000_shutdown(ndev);
1368*4882a593Smuzhiyun 
1369*4882a593Smuzhiyun 	return 0;
1370*4882a593Smuzhiyun }
1371*4882a593Smuzhiyun 
1372*4882a593Smuzhiyun static const struct net_device_ops dm9000_netdev_ops = {
1373*4882a593Smuzhiyun 	.ndo_open		= dm9000_open,
1374*4882a593Smuzhiyun 	.ndo_stop		= dm9000_stop,
1375*4882a593Smuzhiyun 	.ndo_start_xmit		= dm9000_start_xmit,
1376*4882a593Smuzhiyun 	.ndo_tx_timeout		= dm9000_timeout,
1377*4882a593Smuzhiyun 	.ndo_set_rx_mode	= dm9000_hash_table,
1378*4882a593Smuzhiyun 	.ndo_do_ioctl		= dm9000_ioctl,
1379*4882a593Smuzhiyun 	.ndo_set_features	= dm9000_set_features,
1380*4882a593Smuzhiyun 	.ndo_validate_addr	= eth_validate_addr,
1381*4882a593Smuzhiyun 	.ndo_set_mac_address	= eth_mac_addr,
1382*4882a593Smuzhiyun #ifdef CONFIG_NET_POLL_CONTROLLER
1383*4882a593Smuzhiyun 	.ndo_poll_controller	= dm9000_poll_controller,
1384*4882a593Smuzhiyun #endif
1385*4882a593Smuzhiyun };
1386*4882a593Smuzhiyun 
dm9000_parse_dt(struct device * dev)1387*4882a593Smuzhiyun static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev)
1388*4882a593Smuzhiyun {
1389*4882a593Smuzhiyun 	struct dm9000_plat_data *pdata;
1390*4882a593Smuzhiyun 	struct device_node *np = dev->of_node;
1391*4882a593Smuzhiyun 	const void *mac_addr;
1392*4882a593Smuzhiyun 
1393*4882a593Smuzhiyun 	if (!IS_ENABLED(CONFIG_OF) || !np)
1394*4882a593Smuzhiyun 		return ERR_PTR(-ENXIO);
1395*4882a593Smuzhiyun 
1396*4882a593Smuzhiyun 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1397*4882a593Smuzhiyun 	if (!pdata)
1398*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
1399*4882a593Smuzhiyun 
1400*4882a593Smuzhiyun 	if (of_find_property(np, "davicom,ext-phy", NULL))
1401*4882a593Smuzhiyun 		pdata->flags |= DM9000_PLATF_EXT_PHY;
1402*4882a593Smuzhiyun 	if (of_find_property(np, "davicom,no-eeprom", NULL))
1403*4882a593Smuzhiyun 		pdata->flags |= DM9000_PLATF_NO_EEPROM;
1404*4882a593Smuzhiyun 
1405*4882a593Smuzhiyun 	mac_addr = of_get_mac_address(np);
1406*4882a593Smuzhiyun 	if (!IS_ERR(mac_addr))
1407*4882a593Smuzhiyun 		ether_addr_copy(pdata->dev_addr, mac_addr);
1408*4882a593Smuzhiyun 	else if (PTR_ERR(mac_addr) == -EPROBE_DEFER)
1409*4882a593Smuzhiyun 		return ERR_CAST(mac_addr);
1410*4882a593Smuzhiyun 
1411*4882a593Smuzhiyun 	return pdata;
1412*4882a593Smuzhiyun }
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun /*
1415*4882a593Smuzhiyun  * Search DM9000 board, allocate space and register it
1416*4882a593Smuzhiyun  */
1417*4882a593Smuzhiyun static int
dm9000_probe(struct platform_device * pdev)1418*4882a593Smuzhiyun dm9000_probe(struct platform_device *pdev)
1419*4882a593Smuzhiyun {
1420*4882a593Smuzhiyun 	struct dm9000_plat_data *pdata = dev_get_platdata(&pdev->dev);
1421*4882a593Smuzhiyun 	struct board_info *db;	/* Point a board information structure */
1422*4882a593Smuzhiyun 	struct net_device *ndev;
1423*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
1424*4882a593Smuzhiyun 	const unsigned char *mac_src;
1425*4882a593Smuzhiyun 	int ret = 0;
1426*4882a593Smuzhiyun 	int iosize;
1427*4882a593Smuzhiyun 	int i;
1428*4882a593Smuzhiyun 	u32 id_val;
1429*4882a593Smuzhiyun 	int reset_gpios;
1430*4882a593Smuzhiyun 	enum of_gpio_flags flags;
1431*4882a593Smuzhiyun 	struct regulator *power;
1432*4882a593Smuzhiyun 	bool inv_mac_addr = false;
1433*4882a593Smuzhiyun 
1434*4882a593Smuzhiyun 	power = devm_regulator_get(dev, "vcc");
1435*4882a593Smuzhiyun 	if (IS_ERR(power)) {
1436*4882a593Smuzhiyun 		if (PTR_ERR(power) == -EPROBE_DEFER)
1437*4882a593Smuzhiyun 			return -EPROBE_DEFER;
1438*4882a593Smuzhiyun 		dev_dbg(dev, "no regulator provided\n");
1439*4882a593Smuzhiyun 	} else {
1440*4882a593Smuzhiyun 		ret = regulator_enable(power);
1441*4882a593Smuzhiyun 		if (ret != 0) {
1442*4882a593Smuzhiyun 			dev_err(dev,
1443*4882a593Smuzhiyun 				"Failed to enable power regulator: %d\n", ret);
1444*4882a593Smuzhiyun 			return ret;
1445*4882a593Smuzhiyun 		}
1446*4882a593Smuzhiyun 		dev_dbg(dev, "regulator enabled\n");
1447*4882a593Smuzhiyun 	}
1448*4882a593Smuzhiyun 
1449*4882a593Smuzhiyun 	reset_gpios = of_get_named_gpio_flags(dev->of_node, "reset-gpios", 0,
1450*4882a593Smuzhiyun 					      &flags);
1451*4882a593Smuzhiyun 	if (gpio_is_valid(reset_gpios)) {
1452*4882a593Smuzhiyun 		ret = devm_gpio_request_one(dev, reset_gpios, flags,
1453*4882a593Smuzhiyun 					    "dm9000_reset");
1454*4882a593Smuzhiyun 		if (ret) {
1455*4882a593Smuzhiyun 			dev_err(dev, "failed to request reset gpio %d: %d\n",
1456*4882a593Smuzhiyun 				reset_gpios, ret);
1457*4882a593Smuzhiyun 			goto out_regulator_disable;
1458*4882a593Smuzhiyun 		}
1459*4882a593Smuzhiyun 
1460*4882a593Smuzhiyun 		/* According to manual PWRST# Low Period Min 1ms */
1461*4882a593Smuzhiyun 		msleep(2);
1462*4882a593Smuzhiyun 		gpio_set_value(reset_gpios, 1);
1463*4882a593Smuzhiyun 		/* Needs 3ms to read eeprom when PWRST is deasserted */
1464*4882a593Smuzhiyun 		msleep(4);
1465*4882a593Smuzhiyun 	}
1466*4882a593Smuzhiyun 
1467*4882a593Smuzhiyun 	if (!pdata) {
1468*4882a593Smuzhiyun 		pdata = dm9000_parse_dt(&pdev->dev);
1469*4882a593Smuzhiyun 		if (IS_ERR(pdata)) {
1470*4882a593Smuzhiyun 			ret = PTR_ERR(pdata);
1471*4882a593Smuzhiyun 			goto out_regulator_disable;
1472*4882a593Smuzhiyun 		}
1473*4882a593Smuzhiyun 	}
1474*4882a593Smuzhiyun 
1475*4882a593Smuzhiyun 	/* Init network device */
1476*4882a593Smuzhiyun 	ndev = alloc_etherdev(sizeof(struct board_info));
1477*4882a593Smuzhiyun 	if (!ndev) {
1478*4882a593Smuzhiyun 		ret = -ENOMEM;
1479*4882a593Smuzhiyun 		goto out_regulator_disable;
1480*4882a593Smuzhiyun 	}
1481*4882a593Smuzhiyun 
1482*4882a593Smuzhiyun 	SET_NETDEV_DEV(ndev, &pdev->dev);
1483*4882a593Smuzhiyun 
1484*4882a593Smuzhiyun 	dev_dbg(&pdev->dev, "dm9000_probe()\n");
1485*4882a593Smuzhiyun 
1486*4882a593Smuzhiyun 	/* setup board info structure */
1487*4882a593Smuzhiyun 	db = netdev_priv(ndev);
1488*4882a593Smuzhiyun 
1489*4882a593Smuzhiyun 	db->dev = &pdev->dev;
1490*4882a593Smuzhiyun 	db->ndev = ndev;
1491*4882a593Smuzhiyun 	if (!IS_ERR(power))
1492*4882a593Smuzhiyun 		db->power_supply = power;
1493*4882a593Smuzhiyun 
1494*4882a593Smuzhiyun 	spin_lock_init(&db->lock);
1495*4882a593Smuzhiyun 	mutex_init(&db->addr_lock);
1496*4882a593Smuzhiyun 
1497*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);
1498*4882a593Smuzhiyun 
1499*4882a593Smuzhiyun 	db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1500*4882a593Smuzhiyun 	db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1501*4882a593Smuzhiyun 
1502*4882a593Smuzhiyun 	if (!db->addr_res || !db->data_res) {
1503*4882a593Smuzhiyun 		dev_err(db->dev, "insufficient resources addr=%p data=%p\n",
1504*4882a593Smuzhiyun 			db->addr_res, db->data_res);
1505*4882a593Smuzhiyun 		ret = -ENOENT;
1506*4882a593Smuzhiyun 		goto out;
1507*4882a593Smuzhiyun 	}
1508*4882a593Smuzhiyun 
1509*4882a593Smuzhiyun 	ndev->irq = platform_get_irq(pdev, 0);
1510*4882a593Smuzhiyun 	if (ndev->irq < 0) {
1511*4882a593Smuzhiyun 		ret = ndev->irq;
1512*4882a593Smuzhiyun 		goto out;
1513*4882a593Smuzhiyun 	}
1514*4882a593Smuzhiyun 
1515*4882a593Smuzhiyun 	db->irq_wake = platform_get_irq_optional(pdev, 1);
1516*4882a593Smuzhiyun 	if (db->irq_wake >= 0) {
1517*4882a593Smuzhiyun 		dev_dbg(db->dev, "wakeup irq %d\n", db->irq_wake);
1518*4882a593Smuzhiyun 
1519*4882a593Smuzhiyun 		ret = request_irq(db->irq_wake, dm9000_wol_interrupt,
1520*4882a593Smuzhiyun 				  IRQF_SHARED, dev_name(db->dev), ndev);
1521*4882a593Smuzhiyun 		if (ret) {
1522*4882a593Smuzhiyun 			dev_err(db->dev, "cannot get wakeup irq (%d)\n", ret);
1523*4882a593Smuzhiyun 		} else {
1524*4882a593Smuzhiyun 
1525*4882a593Smuzhiyun 			/* test to see if irq is really wakeup capable */
1526*4882a593Smuzhiyun 			ret = irq_set_irq_wake(db->irq_wake, 1);
1527*4882a593Smuzhiyun 			if (ret) {
1528*4882a593Smuzhiyun 				dev_err(db->dev, "irq %d cannot set wakeup (%d)\n",
1529*4882a593Smuzhiyun 					db->irq_wake, ret);
1530*4882a593Smuzhiyun 				ret = 0;
1531*4882a593Smuzhiyun 			} else {
1532*4882a593Smuzhiyun 				irq_set_irq_wake(db->irq_wake, 0);
1533*4882a593Smuzhiyun 				db->wake_supported = 1;
1534*4882a593Smuzhiyun 			}
1535*4882a593Smuzhiyun 		}
1536*4882a593Smuzhiyun 	}
1537*4882a593Smuzhiyun 
1538*4882a593Smuzhiyun 	iosize = resource_size(db->addr_res);
1539*4882a593Smuzhiyun 	db->addr_req = request_mem_region(db->addr_res->start, iosize,
1540*4882a593Smuzhiyun 					  pdev->name);
1541*4882a593Smuzhiyun 
1542*4882a593Smuzhiyun 	if (db->addr_req == NULL) {
1543*4882a593Smuzhiyun 		dev_err(db->dev, "cannot claim address reg area\n");
1544*4882a593Smuzhiyun 		ret = -EIO;
1545*4882a593Smuzhiyun 		goto out;
1546*4882a593Smuzhiyun 	}
1547*4882a593Smuzhiyun 
1548*4882a593Smuzhiyun 	db->io_addr = ioremap(db->addr_res->start, iosize);
1549*4882a593Smuzhiyun 
1550*4882a593Smuzhiyun 	if (db->io_addr == NULL) {
1551*4882a593Smuzhiyun 		dev_err(db->dev, "failed to ioremap address reg\n");
1552*4882a593Smuzhiyun 		ret = -EINVAL;
1553*4882a593Smuzhiyun 		goto out;
1554*4882a593Smuzhiyun 	}
1555*4882a593Smuzhiyun 
1556*4882a593Smuzhiyun 	iosize = resource_size(db->data_res);
1557*4882a593Smuzhiyun 	db->data_req = request_mem_region(db->data_res->start, iosize,
1558*4882a593Smuzhiyun 					  pdev->name);
1559*4882a593Smuzhiyun 
1560*4882a593Smuzhiyun 	if (db->data_req == NULL) {
1561*4882a593Smuzhiyun 		dev_err(db->dev, "cannot claim data reg area\n");
1562*4882a593Smuzhiyun 		ret = -EIO;
1563*4882a593Smuzhiyun 		goto out;
1564*4882a593Smuzhiyun 	}
1565*4882a593Smuzhiyun 
1566*4882a593Smuzhiyun 	db->io_data = ioremap(db->data_res->start, iosize);
1567*4882a593Smuzhiyun 
1568*4882a593Smuzhiyun 	if (db->io_data == NULL) {
1569*4882a593Smuzhiyun 		dev_err(db->dev, "failed to ioremap data reg\n");
1570*4882a593Smuzhiyun 		ret = -EINVAL;
1571*4882a593Smuzhiyun 		goto out;
1572*4882a593Smuzhiyun 	}
1573*4882a593Smuzhiyun 
1574*4882a593Smuzhiyun 	/* fill in parameters for net-dev structure */
1575*4882a593Smuzhiyun 	ndev->base_addr = (unsigned long)db->io_addr;
1576*4882a593Smuzhiyun 
1577*4882a593Smuzhiyun 	/* ensure at least we have a default set of IO routines */
1578*4882a593Smuzhiyun 	dm9000_set_io(db, iosize);
1579*4882a593Smuzhiyun 
1580*4882a593Smuzhiyun 	/* check to see if anything is being over-ridden */
1581*4882a593Smuzhiyun 	if (pdata != NULL) {
1582*4882a593Smuzhiyun 		/* check to see if the driver wants to over-ride the
1583*4882a593Smuzhiyun 		 * default IO width */
1584*4882a593Smuzhiyun 
1585*4882a593Smuzhiyun 		if (pdata->flags & DM9000_PLATF_8BITONLY)
1586*4882a593Smuzhiyun 			dm9000_set_io(db, 1);
1587*4882a593Smuzhiyun 
1588*4882a593Smuzhiyun 		if (pdata->flags & DM9000_PLATF_16BITONLY)
1589*4882a593Smuzhiyun 			dm9000_set_io(db, 2);
1590*4882a593Smuzhiyun 
1591*4882a593Smuzhiyun 		if (pdata->flags & DM9000_PLATF_32BITONLY)
1592*4882a593Smuzhiyun 			dm9000_set_io(db, 4);
1593*4882a593Smuzhiyun 
1594*4882a593Smuzhiyun 		/* check to see if there are any IO routine
1595*4882a593Smuzhiyun 		 * over-rides */
1596*4882a593Smuzhiyun 
1597*4882a593Smuzhiyun 		if (pdata->inblk != NULL)
1598*4882a593Smuzhiyun 			db->inblk = pdata->inblk;
1599*4882a593Smuzhiyun 
1600*4882a593Smuzhiyun 		if (pdata->outblk != NULL)
1601*4882a593Smuzhiyun 			db->outblk = pdata->outblk;
1602*4882a593Smuzhiyun 
1603*4882a593Smuzhiyun 		if (pdata->dumpblk != NULL)
1604*4882a593Smuzhiyun 			db->dumpblk = pdata->dumpblk;
1605*4882a593Smuzhiyun 
1606*4882a593Smuzhiyun 		db->flags = pdata->flags;
1607*4882a593Smuzhiyun 	}
1608*4882a593Smuzhiyun 
1609*4882a593Smuzhiyun #ifdef CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL
1610*4882a593Smuzhiyun 	db->flags |= DM9000_PLATF_SIMPLE_PHY;
1611*4882a593Smuzhiyun #endif
1612*4882a593Smuzhiyun 
1613*4882a593Smuzhiyun 	dm9000_reset(db);
1614*4882a593Smuzhiyun 
1615*4882a593Smuzhiyun 	/* try multiple times, DM9000 sometimes gets the read wrong */
1616*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
1617*4882a593Smuzhiyun 		id_val  = ior(db, DM9000_VIDL);
1618*4882a593Smuzhiyun 		id_val |= (u32)ior(db, DM9000_VIDH) << 8;
1619*4882a593Smuzhiyun 		id_val |= (u32)ior(db, DM9000_PIDL) << 16;
1620*4882a593Smuzhiyun 		id_val |= (u32)ior(db, DM9000_PIDH) << 24;
1621*4882a593Smuzhiyun 
1622*4882a593Smuzhiyun 		if (id_val == DM9000_ID)
1623*4882a593Smuzhiyun 			break;
1624*4882a593Smuzhiyun 		dev_err(db->dev, "read wrong id 0x%08x\n", id_val);
1625*4882a593Smuzhiyun 	}
1626*4882a593Smuzhiyun 
1627*4882a593Smuzhiyun 	if (id_val != DM9000_ID) {
1628*4882a593Smuzhiyun 		dev_err(db->dev, "wrong id: 0x%08x\n", id_val);
1629*4882a593Smuzhiyun 		ret = -ENODEV;
1630*4882a593Smuzhiyun 		goto out;
1631*4882a593Smuzhiyun 	}
1632*4882a593Smuzhiyun 
1633*4882a593Smuzhiyun 	/* Identify what type of DM9000 we are working on */
1634*4882a593Smuzhiyun 
1635*4882a593Smuzhiyun 	id_val = ior(db, DM9000_CHIPR);
1636*4882a593Smuzhiyun 	dev_dbg(db->dev, "dm9000 revision 0x%02x\n", id_val);
1637*4882a593Smuzhiyun 
1638*4882a593Smuzhiyun 	switch (id_val) {
1639*4882a593Smuzhiyun 	case CHIPR_DM9000A:
1640*4882a593Smuzhiyun 		db->type = TYPE_DM9000A;
1641*4882a593Smuzhiyun 		break;
1642*4882a593Smuzhiyun 	case CHIPR_DM9000B:
1643*4882a593Smuzhiyun 		db->type = TYPE_DM9000B;
1644*4882a593Smuzhiyun 		break;
1645*4882a593Smuzhiyun 	default:
1646*4882a593Smuzhiyun 		dev_dbg(db->dev, "ID %02x => defaulting to DM9000E\n", id_val);
1647*4882a593Smuzhiyun 		db->type = TYPE_DM9000E;
1648*4882a593Smuzhiyun 	}
1649*4882a593Smuzhiyun 
1650*4882a593Smuzhiyun 	/* dm9000a/b are capable of hardware checksum offload */
1651*4882a593Smuzhiyun 	if (db->type == TYPE_DM9000A || db->type == TYPE_DM9000B) {
1652*4882a593Smuzhiyun 		ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
1653*4882a593Smuzhiyun 		ndev->features |= ndev->hw_features;
1654*4882a593Smuzhiyun 	}
1655*4882a593Smuzhiyun 
1656*4882a593Smuzhiyun 	/* from this point we assume that we have found a DM9000 */
1657*4882a593Smuzhiyun 
1658*4882a593Smuzhiyun 	ndev->netdev_ops	= &dm9000_netdev_ops;
1659*4882a593Smuzhiyun 	ndev->watchdog_timeo	= msecs_to_jiffies(watchdog);
1660*4882a593Smuzhiyun 	ndev->ethtool_ops	= &dm9000_ethtool_ops;
1661*4882a593Smuzhiyun 
1662*4882a593Smuzhiyun 	db->msg_enable       = NETIF_MSG_LINK;
1663*4882a593Smuzhiyun 	db->mii.phy_id_mask  = 0x1f;
1664*4882a593Smuzhiyun 	db->mii.reg_num_mask = 0x1f;
1665*4882a593Smuzhiyun 	db->mii.force_media  = 0;
1666*4882a593Smuzhiyun 	db->mii.full_duplex  = 0;
1667*4882a593Smuzhiyun 	db->mii.dev	     = ndev;
1668*4882a593Smuzhiyun 	db->mii.mdio_read    = dm9000_phy_read;
1669*4882a593Smuzhiyun 	db->mii.mdio_write   = dm9000_phy_write;
1670*4882a593Smuzhiyun 
1671*4882a593Smuzhiyun 	mac_src = "eeprom";
1672*4882a593Smuzhiyun 
1673*4882a593Smuzhiyun 	/* try reading the node address from the attached EEPROM */
1674*4882a593Smuzhiyun 	for (i = 0; i < 6; i += 2)
1675*4882a593Smuzhiyun 		dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);
1676*4882a593Smuzhiyun 
1677*4882a593Smuzhiyun 	if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) {
1678*4882a593Smuzhiyun 		mac_src = "platform data";
1679*4882a593Smuzhiyun 		memcpy(ndev->dev_addr, pdata->dev_addr, ETH_ALEN);
1680*4882a593Smuzhiyun 	}
1681*4882a593Smuzhiyun 
1682*4882a593Smuzhiyun 	if (!is_valid_ether_addr(ndev->dev_addr)) {
1683*4882a593Smuzhiyun 		/* try reading from mac */
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun 		mac_src = "chip";
1686*4882a593Smuzhiyun 		for (i = 0; i < 6; i++)
1687*4882a593Smuzhiyun 			ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
1688*4882a593Smuzhiyun 	}
1689*4882a593Smuzhiyun 
1690*4882a593Smuzhiyun 	if (!is_valid_ether_addr(ndev->dev_addr)) {
1691*4882a593Smuzhiyun 		inv_mac_addr = true;
1692*4882a593Smuzhiyun 		eth_hw_addr_random(ndev);
1693*4882a593Smuzhiyun 		mac_src = "random";
1694*4882a593Smuzhiyun 	}
1695*4882a593Smuzhiyun 
1696*4882a593Smuzhiyun 
1697*4882a593Smuzhiyun 	platform_set_drvdata(pdev, ndev);
1698*4882a593Smuzhiyun 	ret = register_netdev(ndev);
1699*4882a593Smuzhiyun 
1700*4882a593Smuzhiyun 	if (ret == 0) {
1701*4882a593Smuzhiyun 		if (inv_mac_addr)
1702*4882a593Smuzhiyun 			dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please set using ip\n",
1703*4882a593Smuzhiyun 				 ndev->name);
1704*4882a593Smuzhiyun 		printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n",
1705*4882a593Smuzhiyun 		       ndev->name, dm9000_type_to_char(db->type),
1706*4882a593Smuzhiyun 		       db->io_addr, db->io_data, ndev->irq,
1707*4882a593Smuzhiyun 		       ndev->dev_addr, mac_src);
1708*4882a593Smuzhiyun 	}
1709*4882a593Smuzhiyun 	return 0;
1710*4882a593Smuzhiyun 
1711*4882a593Smuzhiyun out:
1712*4882a593Smuzhiyun 	dev_err(db->dev, "not found (%d).\n", ret);
1713*4882a593Smuzhiyun 
1714*4882a593Smuzhiyun 	dm9000_release_board(pdev, db);
1715*4882a593Smuzhiyun 	free_netdev(ndev);
1716*4882a593Smuzhiyun 
1717*4882a593Smuzhiyun out_regulator_disable:
1718*4882a593Smuzhiyun 	if (!IS_ERR(power))
1719*4882a593Smuzhiyun 		regulator_disable(power);
1720*4882a593Smuzhiyun 
1721*4882a593Smuzhiyun 	return ret;
1722*4882a593Smuzhiyun }
1723*4882a593Smuzhiyun 
1724*4882a593Smuzhiyun static int
dm9000_drv_suspend(struct device * dev)1725*4882a593Smuzhiyun dm9000_drv_suspend(struct device *dev)
1726*4882a593Smuzhiyun {
1727*4882a593Smuzhiyun 	struct net_device *ndev = dev_get_drvdata(dev);
1728*4882a593Smuzhiyun 	struct board_info *db;
1729*4882a593Smuzhiyun 
1730*4882a593Smuzhiyun 	if (ndev) {
1731*4882a593Smuzhiyun 		db = netdev_priv(ndev);
1732*4882a593Smuzhiyun 		db->in_suspend = 1;
1733*4882a593Smuzhiyun 
1734*4882a593Smuzhiyun 		if (!netif_running(ndev))
1735*4882a593Smuzhiyun 			return 0;
1736*4882a593Smuzhiyun 
1737*4882a593Smuzhiyun 		netif_device_detach(ndev);
1738*4882a593Smuzhiyun 
1739*4882a593Smuzhiyun 		/* only shutdown if not using WoL */
1740*4882a593Smuzhiyun 		if (!db->wake_state)
1741*4882a593Smuzhiyun 			dm9000_shutdown(ndev);
1742*4882a593Smuzhiyun 	}
1743*4882a593Smuzhiyun 	return 0;
1744*4882a593Smuzhiyun }
1745*4882a593Smuzhiyun 
1746*4882a593Smuzhiyun static int
dm9000_drv_resume(struct device * dev)1747*4882a593Smuzhiyun dm9000_drv_resume(struct device *dev)
1748*4882a593Smuzhiyun {
1749*4882a593Smuzhiyun 	struct net_device *ndev = dev_get_drvdata(dev);
1750*4882a593Smuzhiyun 	struct board_info *db = netdev_priv(ndev);
1751*4882a593Smuzhiyun 
1752*4882a593Smuzhiyun 	if (ndev) {
1753*4882a593Smuzhiyun 		if (netif_running(ndev)) {
1754*4882a593Smuzhiyun 			/* reset if we were not in wake mode to ensure if
1755*4882a593Smuzhiyun 			 * the device was powered off it is in a known state */
1756*4882a593Smuzhiyun 			if (!db->wake_state) {
1757*4882a593Smuzhiyun 				dm9000_init_dm9000(ndev);
1758*4882a593Smuzhiyun 				dm9000_unmask_interrupts(db);
1759*4882a593Smuzhiyun 			}
1760*4882a593Smuzhiyun 
1761*4882a593Smuzhiyun 			netif_device_attach(ndev);
1762*4882a593Smuzhiyun 		}
1763*4882a593Smuzhiyun 
1764*4882a593Smuzhiyun 		db->in_suspend = 0;
1765*4882a593Smuzhiyun 	}
1766*4882a593Smuzhiyun 	return 0;
1767*4882a593Smuzhiyun }
1768*4882a593Smuzhiyun 
1769*4882a593Smuzhiyun static const struct dev_pm_ops dm9000_drv_pm_ops = {
1770*4882a593Smuzhiyun 	.suspend	= dm9000_drv_suspend,
1771*4882a593Smuzhiyun 	.resume		= dm9000_drv_resume,
1772*4882a593Smuzhiyun };
1773*4882a593Smuzhiyun 
1774*4882a593Smuzhiyun static int
dm9000_drv_remove(struct platform_device * pdev)1775*4882a593Smuzhiyun dm9000_drv_remove(struct platform_device *pdev)
1776*4882a593Smuzhiyun {
1777*4882a593Smuzhiyun 	struct net_device *ndev = platform_get_drvdata(pdev);
1778*4882a593Smuzhiyun 	struct board_info *dm = to_dm9000_board(ndev);
1779*4882a593Smuzhiyun 
1780*4882a593Smuzhiyun 	unregister_netdev(ndev);
1781*4882a593Smuzhiyun 	dm9000_release_board(pdev, dm);
1782*4882a593Smuzhiyun 	free_netdev(ndev);		/* free device structure */
1783*4882a593Smuzhiyun 	if (dm->power_supply)
1784*4882a593Smuzhiyun 		regulator_disable(dm->power_supply);
1785*4882a593Smuzhiyun 
1786*4882a593Smuzhiyun 	dev_dbg(&pdev->dev, "released and freed device\n");
1787*4882a593Smuzhiyun 	return 0;
1788*4882a593Smuzhiyun }
1789*4882a593Smuzhiyun 
1790*4882a593Smuzhiyun #ifdef CONFIG_OF
1791*4882a593Smuzhiyun static const struct of_device_id dm9000_of_matches[] = {
1792*4882a593Smuzhiyun 	{ .compatible = "davicom,dm9000", },
1793*4882a593Smuzhiyun 	{ /* sentinel */ }
1794*4882a593Smuzhiyun };
1795*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, dm9000_of_matches);
1796*4882a593Smuzhiyun #endif
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun static struct platform_driver dm9000_driver = {
1799*4882a593Smuzhiyun 	.driver	= {
1800*4882a593Smuzhiyun 		.name    = "dm9000",
1801*4882a593Smuzhiyun 		.pm	 = &dm9000_drv_pm_ops,
1802*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(dm9000_of_matches),
1803*4882a593Smuzhiyun 	},
1804*4882a593Smuzhiyun 	.probe   = dm9000_probe,
1805*4882a593Smuzhiyun 	.remove  = dm9000_drv_remove,
1806*4882a593Smuzhiyun };
1807*4882a593Smuzhiyun 
1808*4882a593Smuzhiyun module_platform_driver(dm9000_driver);
1809*4882a593Smuzhiyun 
1810*4882a593Smuzhiyun MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
1811*4882a593Smuzhiyun MODULE_DESCRIPTION("Davicom DM9000 network driver");
1812*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1813*4882a593Smuzhiyun MODULE_ALIAS("platform:dm9000");
1814