1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Allwinner EMAC Fast Ethernet driver for Linux.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright 2012-2013 Stefan Roese <sr@denx.de>
5*4882a593Smuzhiyun * Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Based on the Linux driver provided by Allwinner:
8*4882a593Smuzhiyun * Copyright (C) 1997 Sten Wang
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * This file is licensed under the terms of the GNU General Public
11*4882a593Smuzhiyun * License version 2. This program is licensed "as is" without any
12*4882a593Smuzhiyun * warranty of any kind, whether express or implied.
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <linux/clk.h>
16*4882a593Smuzhiyun #include <linux/etherdevice.h>
17*4882a593Smuzhiyun #include <linux/ethtool.h>
18*4882a593Smuzhiyun #include <linux/gpio.h>
19*4882a593Smuzhiyun #include <linux/interrupt.h>
20*4882a593Smuzhiyun #include <linux/irq.h>
21*4882a593Smuzhiyun #include <linux/mii.h>
22*4882a593Smuzhiyun #include <linux/module.h>
23*4882a593Smuzhiyun #include <linux/netdevice.h>
24*4882a593Smuzhiyun #include <linux/of_address.h>
25*4882a593Smuzhiyun #include <linux/of_irq.h>
26*4882a593Smuzhiyun #include <linux/of_mdio.h>
27*4882a593Smuzhiyun #include <linux/of_net.h>
28*4882a593Smuzhiyun #include <linux/of_platform.h>
29*4882a593Smuzhiyun #include <linux/platform_device.h>
30*4882a593Smuzhiyun #include <linux/phy.h>
31*4882a593Smuzhiyun #include <linux/soc/sunxi/sunxi_sram.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #include "sun4i-emac.h"
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define DRV_NAME "sun4i-emac"
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define EMAC_MAX_FRAME_LEN 0x0600
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #define EMAC_DEFAULT_MSG_ENABLE 0x0000
40*4882a593Smuzhiyun static int debug = -1; /* defaults above */;
41*4882a593Smuzhiyun module_param(debug, int, 0);
42*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "debug message flags");
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* Transmit timeout, default 5 seconds. */
45*4882a593Smuzhiyun static int watchdog = 5000;
46*4882a593Smuzhiyun module_param(watchdog, int, 0400);
47*4882a593Smuzhiyun MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /* EMAC register address locking.
50*4882a593Smuzhiyun *
51*4882a593Smuzhiyun * The EMAC uses an address register to control where data written
52*4882a593Smuzhiyun * to the data register goes. This means that the address register
53*4882a593Smuzhiyun * must be preserved over interrupts or similar calls.
54*4882a593Smuzhiyun *
55*4882a593Smuzhiyun * During interrupt and other critical calls, a spinlock is used to
56*4882a593Smuzhiyun * protect the system, but the calls themselves save the address
57*4882a593Smuzhiyun * in the address register in case they are interrupting another
58*4882a593Smuzhiyun * access to the device.
59*4882a593Smuzhiyun *
60*4882a593Smuzhiyun * For general accesses a lock is provided so that calls which are
61*4882a593Smuzhiyun * allowed to sleep are serialised so that the address register does
62*4882a593Smuzhiyun * not need to be saved. This lock also serves to serialise access
63*4882a593Smuzhiyun * to the EEPROM and PHY access registers which are shared between
64*4882a593Smuzhiyun * these two devices.
65*4882a593Smuzhiyun */
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /* The driver supports the original EMACE, and now the two newer
68*4882a593Smuzhiyun * devices, EMACA and EMACB.
69*4882a593Smuzhiyun */
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun struct emac_board_info {
72*4882a593Smuzhiyun struct clk *clk;
73*4882a593Smuzhiyun struct device *dev;
74*4882a593Smuzhiyun struct platform_device *pdev;
75*4882a593Smuzhiyun spinlock_t lock;
76*4882a593Smuzhiyun void __iomem *membase;
77*4882a593Smuzhiyun u32 msg_enable;
78*4882a593Smuzhiyun struct net_device *ndev;
79*4882a593Smuzhiyun struct sk_buff *skb_last;
80*4882a593Smuzhiyun u16 tx_fifo_stat;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun int emacrx_completed_flag;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun struct device_node *phy_node;
85*4882a593Smuzhiyun unsigned int link;
86*4882a593Smuzhiyun unsigned int speed;
87*4882a593Smuzhiyun unsigned int duplex;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun phy_interface_t phy_interface;
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun
emac_update_speed(struct net_device * dev)92*4882a593Smuzhiyun static void emac_update_speed(struct net_device *dev)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
95*4882a593Smuzhiyun unsigned int reg_val;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /* set EMAC SPEED, depend on PHY */
98*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_MAC_SUPP_REG);
99*4882a593Smuzhiyun reg_val &= ~(0x1 << 8);
100*4882a593Smuzhiyun if (db->speed == SPEED_100)
101*4882a593Smuzhiyun reg_val |= 1 << 8;
102*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_MAC_SUPP_REG);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
emac_update_duplex(struct net_device * dev)105*4882a593Smuzhiyun static void emac_update_duplex(struct net_device *dev)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
108*4882a593Smuzhiyun unsigned int reg_val;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /* set duplex depend on phy */
111*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_MAC_CTL1_REG);
112*4882a593Smuzhiyun reg_val &= ~EMAC_MAC_CTL1_DUPLEX_EN;
113*4882a593Smuzhiyun if (db->duplex)
114*4882a593Smuzhiyun reg_val |= EMAC_MAC_CTL1_DUPLEX_EN;
115*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_MAC_CTL1_REG);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
emac_handle_link_change(struct net_device * dev)118*4882a593Smuzhiyun static void emac_handle_link_change(struct net_device *dev)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
121*4882a593Smuzhiyun struct phy_device *phydev = dev->phydev;
122*4882a593Smuzhiyun unsigned long flags;
123*4882a593Smuzhiyun int status_change = 0;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun if (phydev->link) {
126*4882a593Smuzhiyun if (db->speed != phydev->speed) {
127*4882a593Smuzhiyun spin_lock_irqsave(&db->lock, flags);
128*4882a593Smuzhiyun db->speed = phydev->speed;
129*4882a593Smuzhiyun emac_update_speed(dev);
130*4882a593Smuzhiyun spin_unlock_irqrestore(&db->lock, flags);
131*4882a593Smuzhiyun status_change = 1;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun if (db->duplex != phydev->duplex) {
135*4882a593Smuzhiyun spin_lock_irqsave(&db->lock, flags);
136*4882a593Smuzhiyun db->duplex = phydev->duplex;
137*4882a593Smuzhiyun emac_update_duplex(dev);
138*4882a593Smuzhiyun spin_unlock_irqrestore(&db->lock, flags);
139*4882a593Smuzhiyun status_change = 1;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun if (phydev->link != db->link) {
144*4882a593Smuzhiyun if (!phydev->link) {
145*4882a593Smuzhiyun db->speed = 0;
146*4882a593Smuzhiyun db->duplex = -1;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun db->link = phydev->link;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun status_change = 1;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun if (status_change)
154*4882a593Smuzhiyun phy_print_status(phydev);
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
emac_mdio_probe(struct net_device * dev)157*4882a593Smuzhiyun static int emac_mdio_probe(struct net_device *dev)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
160*4882a593Smuzhiyun struct phy_device *phydev;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun /* to-do: PHY interrupts are currently not supported */
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* attach the mac to the phy */
165*4882a593Smuzhiyun phydev = of_phy_connect(db->ndev, db->phy_node,
166*4882a593Smuzhiyun &emac_handle_link_change, 0,
167*4882a593Smuzhiyun db->phy_interface);
168*4882a593Smuzhiyun if (!phydev) {
169*4882a593Smuzhiyun netdev_err(db->ndev, "could not find the PHY\n");
170*4882a593Smuzhiyun return -ENODEV;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /* mask with MAC supported features */
174*4882a593Smuzhiyun phy_set_max_speed(phydev, SPEED_100);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun db->link = 0;
177*4882a593Smuzhiyun db->speed = 0;
178*4882a593Smuzhiyun db->duplex = -1;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun return 0;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
emac_mdio_remove(struct net_device * dev)183*4882a593Smuzhiyun static void emac_mdio_remove(struct net_device *dev)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun phy_disconnect(dev->phydev);
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
emac_reset(struct emac_board_info * db)188*4882a593Smuzhiyun static void emac_reset(struct emac_board_info *db)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun dev_dbg(db->dev, "resetting device\n");
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun /* RESET device */
193*4882a593Smuzhiyun writel(0, db->membase + EMAC_CTL_REG);
194*4882a593Smuzhiyun udelay(200);
195*4882a593Smuzhiyun writel(EMAC_CTL_RESET, db->membase + EMAC_CTL_REG);
196*4882a593Smuzhiyun udelay(200);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
emac_outblk_32bit(void __iomem * reg,void * data,int count)199*4882a593Smuzhiyun static void emac_outblk_32bit(void __iomem *reg, void *data, int count)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun writesl(reg, data, round_up(count, 4) / 4);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
emac_inblk_32bit(void __iomem * reg,void * data,int count)204*4882a593Smuzhiyun static void emac_inblk_32bit(void __iomem *reg, void *data, int count)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun readsl(reg, data, round_up(count, 4) / 4);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun /* ethtool ops */
emac_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)210*4882a593Smuzhiyun static void emac_get_drvinfo(struct net_device *dev,
211*4882a593Smuzhiyun struct ethtool_drvinfo *info)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
214*4882a593Smuzhiyun strlcpy(info->bus_info, dev_name(&dev->dev), sizeof(info->bus_info));
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
emac_get_msglevel(struct net_device * dev)217*4882a593Smuzhiyun static u32 emac_get_msglevel(struct net_device *dev)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun return db->msg_enable;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
emac_set_msglevel(struct net_device * dev,u32 value)224*4882a593Smuzhiyun static void emac_set_msglevel(struct net_device *dev, u32 value)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun db->msg_enable = value;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun static const struct ethtool_ops emac_ethtool_ops = {
232*4882a593Smuzhiyun .get_drvinfo = emac_get_drvinfo,
233*4882a593Smuzhiyun .get_link = ethtool_op_get_link,
234*4882a593Smuzhiyun .get_link_ksettings = phy_ethtool_get_link_ksettings,
235*4882a593Smuzhiyun .set_link_ksettings = phy_ethtool_set_link_ksettings,
236*4882a593Smuzhiyun .get_msglevel = emac_get_msglevel,
237*4882a593Smuzhiyun .set_msglevel = emac_set_msglevel,
238*4882a593Smuzhiyun };
239*4882a593Smuzhiyun
emac_setup(struct net_device * ndev)240*4882a593Smuzhiyun static unsigned int emac_setup(struct net_device *ndev)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(ndev);
243*4882a593Smuzhiyun unsigned int reg_val;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun /* set up TX */
246*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_TX_MODE_REG);
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun writel(reg_val | EMAC_TX_MODE_ABORTED_FRAME_EN,
249*4882a593Smuzhiyun db->membase + EMAC_TX_MODE_REG);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /* set MAC */
252*4882a593Smuzhiyun /* set MAC CTL0 */
253*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_MAC_CTL0_REG);
254*4882a593Smuzhiyun writel(reg_val | EMAC_MAC_CTL0_RX_FLOW_CTL_EN |
255*4882a593Smuzhiyun EMAC_MAC_CTL0_TX_FLOW_CTL_EN,
256*4882a593Smuzhiyun db->membase + EMAC_MAC_CTL0_REG);
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun /* set MAC CTL1 */
259*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_MAC_CTL1_REG);
260*4882a593Smuzhiyun reg_val |= EMAC_MAC_CTL1_LEN_CHECK_EN;
261*4882a593Smuzhiyun reg_val |= EMAC_MAC_CTL1_CRC_EN;
262*4882a593Smuzhiyun reg_val |= EMAC_MAC_CTL1_PAD_EN;
263*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_MAC_CTL1_REG);
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun /* set up IPGT */
266*4882a593Smuzhiyun writel(EMAC_MAC_IPGT_FULL_DUPLEX, db->membase + EMAC_MAC_IPGT_REG);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun /* set up IPGR */
269*4882a593Smuzhiyun writel((EMAC_MAC_IPGR_IPG1 << 8) | EMAC_MAC_IPGR_IPG2,
270*4882a593Smuzhiyun db->membase + EMAC_MAC_IPGR_REG);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /* set up Collison window */
273*4882a593Smuzhiyun writel((EMAC_MAC_CLRT_COLLISION_WINDOW << 8) | EMAC_MAC_CLRT_RM,
274*4882a593Smuzhiyun db->membase + EMAC_MAC_CLRT_REG);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun /* set up Max Frame Length */
277*4882a593Smuzhiyun writel(EMAC_MAX_FRAME_LEN,
278*4882a593Smuzhiyun db->membase + EMAC_MAC_MAXF_REG);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun return 0;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
emac_set_rx_mode(struct net_device * ndev)283*4882a593Smuzhiyun static void emac_set_rx_mode(struct net_device *ndev)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(ndev);
286*4882a593Smuzhiyun unsigned int reg_val;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun /* set up RX */
289*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_RX_CTL_REG);
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (ndev->flags & IFF_PROMISC)
292*4882a593Smuzhiyun reg_val |= EMAC_RX_CTL_PASS_ALL_EN;
293*4882a593Smuzhiyun else
294*4882a593Smuzhiyun reg_val &= ~EMAC_RX_CTL_PASS_ALL_EN;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun writel(reg_val | EMAC_RX_CTL_PASS_LEN_OOR_EN |
297*4882a593Smuzhiyun EMAC_RX_CTL_ACCEPT_UNICAST_EN | EMAC_RX_CTL_DA_FILTER_EN |
298*4882a593Smuzhiyun EMAC_RX_CTL_ACCEPT_MULTICAST_EN |
299*4882a593Smuzhiyun EMAC_RX_CTL_ACCEPT_BROADCAST_EN,
300*4882a593Smuzhiyun db->membase + EMAC_RX_CTL_REG);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
emac_powerup(struct net_device * ndev)303*4882a593Smuzhiyun static unsigned int emac_powerup(struct net_device *ndev)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(ndev);
306*4882a593Smuzhiyun unsigned int reg_val;
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun /* initial EMAC */
309*4882a593Smuzhiyun /* flush RX FIFO */
310*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_RX_CTL_REG);
311*4882a593Smuzhiyun reg_val |= 0x8;
312*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_RX_CTL_REG);
313*4882a593Smuzhiyun udelay(1);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun /* initial MAC */
316*4882a593Smuzhiyun /* soft reset MAC */
317*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_MAC_CTL0_REG);
318*4882a593Smuzhiyun reg_val &= ~EMAC_MAC_CTL0_SOFT_RESET;
319*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_MAC_CTL0_REG);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /* set MII clock */
322*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_MAC_MCFG_REG);
323*4882a593Smuzhiyun reg_val &= (~(0xf << 2));
324*4882a593Smuzhiyun reg_val |= (0xD << 2);
325*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_MAC_MCFG_REG);
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun /* clear RX counter */
328*4882a593Smuzhiyun writel(0x0, db->membase + EMAC_RX_FBC_REG);
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun /* disable all interrupt and clear interrupt status */
331*4882a593Smuzhiyun writel(0, db->membase + EMAC_INT_CTL_REG);
332*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_INT_STA_REG);
333*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_INT_STA_REG);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun udelay(1);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun /* set up EMAC */
338*4882a593Smuzhiyun emac_setup(ndev);
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun /* set mac_address to chip */
341*4882a593Smuzhiyun writel(ndev->dev_addr[0] << 16 | ndev->dev_addr[1] << 8 | ndev->
342*4882a593Smuzhiyun dev_addr[2], db->membase + EMAC_MAC_A1_REG);
343*4882a593Smuzhiyun writel(ndev->dev_addr[3] << 16 | ndev->dev_addr[4] << 8 | ndev->
344*4882a593Smuzhiyun dev_addr[5], db->membase + EMAC_MAC_A0_REG);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun mdelay(1);
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun return 0;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun
emac_set_mac_address(struct net_device * dev,void * p)351*4882a593Smuzhiyun static int emac_set_mac_address(struct net_device *dev, void *p)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun struct sockaddr *addr = p;
354*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun if (netif_running(dev))
357*4882a593Smuzhiyun return -EBUSY;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun writel(dev->dev_addr[0] << 16 | dev->dev_addr[1] << 8 | dev->
362*4882a593Smuzhiyun dev_addr[2], db->membase + EMAC_MAC_A1_REG);
363*4882a593Smuzhiyun writel(dev->dev_addr[3] << 16 | dev->dev_addr[4] << 8 | dev->
364*4882a593Smuzhiyun dev_addr[5], db->membase + EMAC_MAC_A0_REG);
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun return 0;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun /* Initialize emac board */
emac_init_device(struct net_device * dev)370*4882a593Smuzhiyun static void emac_init_device(struct net_device *dev)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
373*4882a593Smuzhiyun unsigned long flags;
374*4882a593Smuzhiyun unsigned int reg_val;
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun spin_lock_irqsave(&db->lock, flags);
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun emac_update_speed(dev);
379*4882a593Smuzhiyun emac_update_duplex(dev);
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun /* enable RX/TX */
382*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_CTL_REG);
383*4882a593Smuzhiyun writel(reg_val | EMAC_CTL_RESET | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN,
384*4882a593Smuzhiyun db->membase + EMAC_CTL_REG);
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun /* enable RX/TX0/RX Hlevel interrup */
387*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_INT_CTL_REG);
388*4882a593Smuzhiyun reg_val |= (0xf << 0) | (0x01 << 8);
389*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_INT_CTL_REG);
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun spin_unlock_irqrestore(&db->lock, flags);
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun /* Our watchdog timed out. Called by the networking layer */
emac_timeout(struct net_device * dev,unsigned int txqueue)395*4882a593Smuzhiyun static void emac_timeout(struct net_device *dev, unsigned int txqueue)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
398*4882a593Smuzhiyun unsigned long flags;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun if (netif_msg_timer(db))
401*4882a593Smuzhiyun dev_err(db->dev, "tx time out.\n");
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun /* Save previous register address */
404*4882a593Smuzhiyun spin_lock_irqsave(&db->lock, flags);
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun netif_stop_queue(dev);
407*4882a593Smuzhiyun emac_reset(db);
408*4882a593Smuzhiyun emac_init_device(dev);
409*4882a593Smuzhiyun /* We can accept TX packets again */
410*4882a593Smuzhiyun netif_trans_update(dev);
411*4882a593Smuzhiyun netif_wake_queue(dev);
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun /* Restore previous register address */
414*4882a593Smuzhiyun spin_unlock_irqrestore(&db->lock, flags);
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /* Hardware start transmission.
418*4882a593Smuzhiyun * Send a packet to media from the upper layer.
419*4882a593Smuzhiyun */
emac_start_xmit(struct sk_buff * skb,struct net_device * dev)420*4882a593Smuzhiyun static netdev_tx_t emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
423*4882a593Smuzhiyun unsigned long channel;
424*4882a593Smuzhiyun unsigned long flags;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun channel = db->tx_fifo_stat & 3;
427*4882a593Smuzhiyun if (channel == 3)
428*4882a593Smuzhiyun return NETDEV_TX_BUSY;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun channel = (channel == 1 ? 1 : 0);
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun spin_lock_irqsave(&db->lock, flags);
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun writel(channel, db->membase + EMAC_TX_INS_REG);
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun emac_outblk_32bit(db->membase + EMAC_TX_IO_DATA_REG,
437*4882a593Smuzhiyun skb->data, skb->len);
438*4882a593Smuzhiyun dev->stats.tx_bytes += skb->len;
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun db->tx_fifo_stat |= 1 << channel;
441*4882a593Smuzhiyun /* TX control: First packet immediately send, second packet queue */
442*4882a593Smuzhiyun if (channel == 0) {
443*4882a593Smuzhiyun /* set TX len */
444*4882a593Smuzhiyun writel(skb->len, db->membase + EMAC_TX_PL0_REG);
445*4882a593Smuzhiyun /* start translate from fifo to phy */
446*4882a593Smuzhiyun writel(readl(db->membase + EMAC_TX_CTL0_REG) | 1,
447*4882a593Smuzhiyun db->membase + EMAC_TX_CTL0_REG);
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun /* save the time stamp */
450*4882a593Smuzhiyun netif_trans_update(dev);
451*4882a593Smuzhiyun } else if (channel == 1) {
452*4882a593Smuzhiyun /* set TX len */
453*4882a593Smuzhiyun writel(skb->len, db->membase + EMAC_TX_PL1_REG);
454*4882a593Smuzhiyun /* start translate from fifo to phy */
455*4882a593Smuzhiyun writel(readl(db->membase + EMAC_TX_CTL1_REG) | 1,
456*4882a593Smuzhiyun db->membase + EMAC_TX_CTL1_REG);
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun /* save the time stamp */
459*4882a593Smuzhiyun netif_trans_update(dev);
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun if ((db->tx_fifo_stat & 3) == 3) {
463*4882a593Smuzhiyun /* Second packet */
464*4882a593Smuzhiyun netif_stop_queue(dev);
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun spin_unlock_irqrestore(&db->lock, flags);
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun /* free this SKB */
470*4882a593Smuzhiyun dev_consume_skb_any(skb);
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun return NETDEV_TX_OK;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun /* EMAC interrupt handler
476*4882a593Smuzhiyun * receive the packet to upper layer, free the transmitted packet
477*4882a593Smuzhiyun */
emac_tx_done(struct net_device * dev,struct emac_board_info * db,unsigned int tx_status)478*4882a593Smuzhiyun static void emac_tx_done(struct net_device *dev, struct emac_board_info *db,
479*4882a593Smuzhiyun unsigned int tx_status)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun /* One packet sent complete */
482*4882a593Smuzhiyun db->tx_fifo_stat &= ~(tx_status & 3);
483*4882a593Smuzhiyun if (3 == (tx_status & 3))
484*4882a593Smuzhiyun dev->stats.tx_packets += 2;
485*4882a593Smuzhiyun else
486*4882a593Smuzhiyun dev->stats.tx_packets++;
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun if (netif_msg_tx_done(db))
489*4882a593Smuzhiyun dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun netif_wake_queue(dev);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun /* Received a packet and pass to upper layer
495*4882a593Smuzhiyun */
emac_rx(struct net_device * dev)496*4882a593Smuzhiyun static void emac_rx(struct net_device *dev)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
499*4882a593Smuzhiyun struct sk_buff *skb;
500*4882a593Smuzhiyun u8 *rdptr;
501*4882a593Smuzhiyun bool good_packet;
502*4882a593Smuzhiyun static int rxlen_last;
503*4882a593Smuzhiyun unsigned int reg_val;
504*4882a593Smuzhiyun u32 rxhdr, rxstatus, rxcount, rxlen;
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun /* Check packet ready or not */
507*4882a593Smuzhiyun while (1) {
508*4882a593Smuzhiyun /* race warning: the first packet might arrive with
509*4882a593Smuzhiyun * the interrupts disabled, but the second will fix
510*4882a593Smuzhiyun * it
511*4882a593Smuzhiyun */
512*4882a593Smuzhiyun rxcount = readl(db->membase + EMAC_RX_FBC_REG);
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun if (netif_msg_rx_status(db))
515*4882a593Smuzhiyun dev_dbg(db->dev, "RXCount: %x\n", rxcount);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun if ((db->skb_last != NULL) && (rxlen_last > 0)) {
518*4882a593Smuzhiyun dev->stats.rx_bytes += rxlen_last;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun /* Pass to upper layer */
521*4882a593Smuzhiyun db->skb_last->protocol = eth_type_trans(db->skb_last,
522*4882a593Smuzhiyun dev);
523*4882a593Smuzhiyun netif_rx(db->skb_last);
524*4882a593Smuzhiyun dev->stats.rx_packets++;
525*4882a593Smuzhiyun db->skb_last = NULL;
526*4882a593Smuzhiyun rxlen_last = 0;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_RX_CTL_REG);
529*4882a593Smuzhiyun reg_val &= ~EMAC_RX_CTL_DMA_EN;
530*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_RX_CTL_REG);
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun if (!rxcount) {
534*4882a593Smuzhiyun db->emacrx_completed_flag = 1;
535*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_INT_CTL_REG);
536*4882a593Smuzhiyun reg_val |= (0xf << 0) | (0x01 << 8);
537*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_INT_CTL_REG);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun /* had one stuck? */
540*4882a593Smuzhiyun rxcount = readl(db->membase + EMAC_RX_FBC_REG);
541*4882a593Smuzhiyun if (!rxcount)
542*4882a593Smuzhiyun return;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_RX_IO_DATA_REG);
546*4882a593Smuzhiyun if (netif_msg_rx_status(db))
547*4882a593Smuzhiyun dev_dbg(db->dev, "receive header: %x\n", reg_val);
548*4882a593Smuzhiyun if (reg_val != EMAC_UNDOCUMENTED_MAGIC) {
549*4882a593Smuzhiyun /* disable RX */
550*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_CTL_REG);
551*4882a593Smuzhiyun writel(reg_val & ~EMAC_CTL_RX_EN,
552*4882a593Smuzhiyun db->membase + EMAC_CTL_REG);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun /* Flush RX FIFO */
555*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_RX_CTL_REG);
556*4882a593Smuzhiyun writel(reg_val | (1 << 3),
557*4882a593Smuzhiyun db->membase + EMAC_RX_CTL_REG);
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun do {
560*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_RX_CTL_REG);
561*4882a593Smuzhiyun } while (reg_val & (1 << 3));
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun /* enable RX */
564*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_CTL_REG);
565*4882a593Smuzhiyun writel(reg_val | EMAC_CTL_RX_EN,
566*4882a593Smuzhiyun db->membase + EMAC_CTL_REG);
567*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_INT_CTL_REG);
568*4882a593Smuzhiyun reg_val |= (0xf << 0) | (0x01 << 8);
569*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_INT_CTL_REG);
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun db->emacrx_completed_flag = 1;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun return;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun /* A packet ready now & Get status/length */
577*4882a593Smuzhiyun good_packet = true;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun rxhdr = readl(db->membase + EMAC_RX_IO_DATA_REG);
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun if (netif_msg_rx_status(db))
582*4882a593Smuzhiyun dev_dbg(db->dev, "rxhdr: %x\n", *((int *)(&rxhdr)));
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun rxlen = EMAC_RX_IO_DATA_LEN(rxhdr);
585*4882a593Smuzhiyun rxstatus = EMAC_RX_IO_DATA_STATUS(rxhdr);
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun if (netif_msg_rx_status(db))
588*4882a593Smuzhiyun dev_dbg(db->dev, "RX: status %02x, length %04x\n",
589*4882a593Smuzhiyun rxstatus, rxlen);
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun /* Packet Status check */
592*4882a593Smuzhiyun if (rxlen < 0x40) {
593*4882a593Smuzhiyun good_packet = false;
594*4882a593Smuzhiyun if (netif_msg_rx_err(db))
595*4882a593Smuzhiyun dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun if (unlikely(!(rxstatus & EMAC_RX_IO_DATA_STATUS_OK))) {
599*4882a593Smuzhiyun good_packet = false;
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun if (rxstatus & EMAC_RX_IO_DATA_STATUS_CRC_ERR) {
602*4882a593Smuzhiyun if (netif_msg_rx_err(db))
603*4882a593Smuzhiyun dev_dbg(db->dev, "crc error\n");
604*4882a593Smuzhiyun dev->stats.rx_crc_errors++;
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun if (rxstatus & EMAC_RX_IO_DATA_STATUS_LEN_ERR) {
608*4882a593Smuzhiyun if (netif_msg_rx_err(db))
609*4882a593Smuzhiyun dev_dbg(db->dev, "length error\n");
610*4882a593Smuzhiyun dev->stats.rx_length_errors++;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun /* Move data from EMAC */
615*4882a593Smuzhiyun if (good_packet) {
616*4882a593Smuzhiyun skb = netdev_alloc_skb(dev, rxlen + 4);
617*4882a593Smuzhiyun if (!skb)
618*4882a593Smuzhiyun continue;
619*4882a593Smuzhiyun skb_reserve(skb, 2);
620*4882a593Smuzhiyun rdptr = skb_put(skb, rxlen - 4);
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun /* Read received packet from RX SRAM */
623*4882a593Smuzhiyun if (netif_msg_rx_status(db))
624*4882a593Smuzhiyun dev_dbg(db->dev, "RxLen %x\n", rxlen);
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
627*4882a593Smuzhiyun rdptr, rxlen);
628*4882a593Smuzhiyun dev->stats.rx_bytes += rxlen;
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun /* Pass to upper layer */
631*4882a593Smuzhiyun skb->protocol = eth_type_trans(skb, dev);
632*4882a593Smuzhiyun netif_rx(skb);
633*4882a593Smuzhiyun dev->stats.rx_packets++;
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun
emac_interrupt(int irq,void * dev_id)638*4882a593Smuzhiyun static irqreturn_t emac_interrupt(int irq, void *dev_id)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun struct net_device *dev = dev_id;
641*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
642*4882a593Smuzhiyun int int_status;
643*4882a593Smuzhiyun unsigned int reg_val;
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun /* A real interrupt coming */
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun spin_lock(&db->lock);
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun /* Disable all interrupts */
650*4882a593Smuzhiyun writel(0, db->membase + EMAC_INT_CTL_REG);
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun /* Got EMAC interrupt status */
653*4882a593Smuzhiyun /* Got ISR */
654*4882a593Smuzhiyun int_status = readl(db->membase + EMAC_INT_STA_REG);
655*4882a593Smuzhiyun /* Clear ISR status */
656*4882a593Smuzhiyun writel(int_status, db->membase + EMAC_INT_STA_REG);
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun if (netif_msg_intr(db))
659*4882a593Smuzhiyun dev_dbg(db->dev, "emac interrupt %02x\n", int_status);
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun /* Received the coming packet */
662*4882a593Smuzhiyun if ((int_status & 0x100) && (db->emacrx_completed_flag == 1)) {
663*4882a593Smuzhiyun /* carrier lost */
664*4882a593Smuzhiyun db->emacrx_completed_flag = 0;
665*4882a593Smuzhiyun emac_rx(dev);
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun /* Transmit Interrupt check */
669*4882a593Smuzhiyun if (int_status & (0x01 | 0x02))
670*4882a593Smuzhiyun emac_tx_done(dev, db, int_status);
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun if (int_status & (0x04 | 0x08))
673*4882a593Smuzhiyun netdev_info(dev, " ab : %x\n", int_status);
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun /* Re-enable interrupt mask */
676*4882a593Smuzhiyun if (db->emacrx_completed_flag == 1) {
677*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_INT_CTL_REG);
678*4882a593Smuzhiyun reg_val |= (0xf << 0) | (0x01 << 8);
679*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_INT_CTL_REG);
680*4882a593Smuzhiyun }
681*4882a593Smuzhiyun spin_unlock(&db->lock);
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun return IRQ_HANDLED;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun #ifdef CONFIG_NET_POLL_CONTROLLER
687*4882a593Smuzhiyun /*
688*4882a593Smuzhiyun * Used by netconsole
689*4882a593Smuzhiyun */
emac_poll_controller(struct net_device * dev)690*4882a593Smuzhiyun static void emac_poll_controller(struct net_device *dev)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun disable_irq(dev->irq);
693*4882a593Smuzhiyun emac_interrupt(dev->irq, dev);
694*4882a593Smuzhiyun enable_irq(dev->irq);
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun #endif
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun /* Open the interface.
699*4882a593Smuzhiyun * The interface is opened whenever "ifconfig" actives it.
700*4882a593Smuzhiyun */
emac_open(struct net_device * dev)701*4882a593Smuzhiyun static int emac_open(struct net_device *dev)
702*4882a593Smuzhiyun {
703*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
704*4882a593Smuzhiyun int ret;
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun if (netif_msg_ifup(db))
707*4882a593Smuzhiyun dev_dbg(db->dev, "enabling %s\n", dev->name);
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun if (request_irq(dev->irq, &emac_interrupt, 0, dev->name, dev))
710*4882a593Smuzhiyun return -EAGAIN;
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun /* Initialize EMAC board */
713*4882a593Smuzhiyun emac_reset(db);
714*4882a593Smuzhiyun emac_init_device(dev);
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun ret = emac_mdio_probe(dev);
717*4882a593Smuzhiyun if (ret < 0) {
718*4882a593Smuzhiyun free_irq(dev->irq, dev);
719*4882a593Smuzhiyun netdev_err(dev, "cannot probe MDIO bus\n");
720*4882a593Smuzhiyun return ret;
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun phy_start(dev->phydev);
724*4882a593Smuzhiyun netif_start_queue(dev);
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun return 0;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun
emac_shutdown(struct net_device * dev)729*4882a593Smuzhiyun static void emac_shutdown(struct net_device *dev)
730*4882a593Smuzhiyun {
731*4882a593Smuzhiyun unsigned int reg_val;
732*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(dev);
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun /* Disable all interrupt */
735*4882a593Smuzhiyun writel(0, db->membase + EMAC_INT_CTL_REG);
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun /* clear interrupt status */
738*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_INT_STA_REG);
739*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_INT_STA_REG);
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun /* Disable RX/TX */
742*4882a593Smuzhiyun reg_val = readl(db->membase + EMAC_CTL_REG);
743*4882a593Smuzhiyun reg_val &= ~(EMAC_CTL_TX_EN | EMAC_CTL_RX_EN | EMAC_CTL_RESET);
744*4882a593Smuzhiyun writel(reg_val, db->membase + EMAC_CTL_REG);
745*4882a593Smuzhiyun }
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun /* Stop the interface.
748*4882a593Smuzhiyun * The interface is stopped when it is brought.
749*4882a593Smuzhiyun */
emac_stop(struct net_device * ndev)750*4882a593Smuzhiyun static int emac_stop(struct net_device *ndev)
751*4882a593Smuzhiyun {
752*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(ndev);
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun if (netif_msg_ifdown(db))
755*4882a593Smuzhiyun dev_dbg(db->dev, "shutting down %s\n", ndev->name);
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun netif_stop_queue(ndev);
758*4882a593Smuzhiyun netif_carrier_off(ndev);
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun phy_stop(ndev->phydev);
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun emac_mdio_remove(ndev);
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun emac_shutdown(ndev);
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun free_irq(ndev->irq, ndev);
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun return 0;
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun static const struct net_device_ops emac_netdev_ops = {
772*4882a593Smuzhiyun .ndo_open = emac_open,
773*4882a593Smuzhiyun .ndo_stop = emac_stop,
774*4882a593Smuzhiyun .ndo_start_xmit = emac_start_xmit,
775*4882a593Smuzhiyun .ndo_tx_timeout = emac_timeout,
776*4882a593Smuzhiyun .ndo_set_rx_mode = emac_set_rx_mode,
777*4882a593Smuzhiyun .ndo_do_ioctl = phy_do_ioctl_running,
778*4882a593Smuzhiyun .ndo_validate_addr = eth_validate_addr,
779*4882a593Smuzhiyun .ndo_set_mac_address = emac_set_mac_address,
780*4882a593Smuzhiyun #ifdef CONFIG_NET_POLL_CONTROLLER
781*4882a593Smuzhiyun .ndo_poll_controller = emac_poll_controller,
782*4882a593Smuzhiyun #endif
783*4882a593Smuzhiyun };
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun /* Search EMAC board, allocate space and register it
786*4882a593Smuzhiyun */
emac_probe(struct platform_device * pdev)787*4882a593Smuzhiyun static int emac_probe(struct platform_device *pdev)
788*4882a593Smuzhiyun {
789*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
790*4882a593Smuzhiyun struct emac_board_info *db;
791*4882a593Smuzhiyun struct net_device *ndev;
792*4882a593Smuzhiyun int ret = 0;
793*4882a593Smuzhiyun const char *mac_addr;
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun ndev = alloc_etherdev(sizeof(struct emac_board_info));
796*4882a593Smuzhiyun if (!ndev) {
797*4882a593Smuzhiyun dev_err(&pdev->dev, "could not allocate device.\n");
798*4882a593Smuzhiyun return -ENOMEM;
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun SET_NETDEV_DEV(ndev, &pdev->dev);
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun db = netdev_priv(ndev);
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun db->dev = &pdev->dev;
806*4882a593Smuzhiyun db->ndev = ndev;
807*4882a593Smuzhiyun db->pdev = pdev;
808*4882a593Smuzhiyun db->msg_enable = netif_msg_init(debug, EMAC_DEFAULT_MSG_ENABLE);
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun spin_lock_init(&db->lock);
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun db->membase = of_iomap(np, 0);
813*4882a593Smuzhiyun if (!db->membase) {
814*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to remap registers\n");
815*4882a593Smuzhiyun ret = -ENOMEM;
816*4882a593Smuzhiyun goto out;
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun /* fill in parameters for net-dev structure */
820*4882a593Smuzhiyun ndev->base_addr = (unsigned long)db->membase;
821*4882a593Smuzhiyun ndev->irq = irq_of_parse_and_map(np, 0);
822*4882a593Smuzhiyun if (ndev->irq == -ENXIO) {
823*4882a593Smuzhiyun netdev_err(ndev, "No irq resource\n");
824*4882a593Smuzhiyun ret = ndev->irq;
825*4882a593Smuzhiyun goto out_iounmap;
826*4882a593Smuzhiyun }
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun db->clk = devm_clk_get(&pdev->dev, NULL);
829*4882a593Smuzhiyun if (IS_ERR(db->clk)) {
830*4882a593Smuzhiyun ret = PTR_ERR(db->clk);
831*4882a593Smuzhiyun goto out_dispose_mapping;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun ret = clk_prepare_enable(db->clk);
835*4882a593Smuzhiyun if (ret) {
836*4882a593Smuzhiyun dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret);
837*4882a593Smuzhiyun goto out_dispose_mapping;
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun ret = sunxi_sram_claim(&pdev->dev);
841*4882a593Smuzhiyun if (ret) {
842*4882a593Smuzhiyun dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
843*4882a593Smuzhiyun goto out_clk_disable_unprepare;
844*4882a593Smuzhiyun }
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun db->phy_node = of_parse_phandle(np, "phy-handle", 0);
847*4882a593Smuzhiyun if (!db->phy_node)
848*4882a593Smuzhiyun db->phy_node = of_parse_phandle(np, "phy", 0);
849*4882a593Smuzhiyun if (!db->phy_node) {
850*4882a593Smuzhiyun dev_err(&pdev->dev, "no associated PHY\n");
851*4882a593Smuzhiyun ret = -ENODEV;
852*4882a593Smuzhiyun goto out_release_sram;
853*4882a593Smuzhiyun }
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun /* Read MAC-address from DT */
856*4882a593Smuzhiyun mac_addr = of_get_mac_address(np);
857*4882a593Smuzhiyun if (!IS_ERR(mac_addr))
858*4882a593Smuzhiyun ether_addr_copy(ndev->dev_addr, mac_addr);
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun /* Check if the MAC address is valid, if not get a random one */
861*4882a593Smuzhiyun if (!is_valid_ether_addr(ndev->dev_addr)) {
862*4882a593Smuzhiyun eth_hw_addr_random(ndev);
863*4882a593Smuzhiyun dev_warn(&pdev->dev, "using random MAC address %pM\n",
864*4882a593Smuzhiyun ndev->dev_addr);
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun db->emacrx_completed_flag = 1;
868*4882a593Smuzhiyun emac_powerup(ndev);
869*4882a593Smuzhiyun emac_reset(db);
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun ndev->netdev_ops = &emac_netdev_ops;
872*4882a593Smuzhiyun ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
873*4882a593Smuzhiyun ndev->ethtool_ops = &emac_ethtool_ops;
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun platform_set_drvdata(pdev, ndev);
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun /* Carrier starts down, phylib will bring it up */
878*4882a593Smuzhiyun netif_carrier_off(ndev);
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun ret = register_netdev(ndev);
881*4882a593Smuzhiyun if (ret) {
882*4882a593Smuzhiyun dev_err(&pdev->dev, "Registering netdev failed!\n");
883*4882a593Smuzhiyun ret = -ENODEV;
884*4882a593Smuzhiyun goto out_release_sram;
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun dev_info(&pdev->dev, "%s: at %p, IRQ %d MAC: %pM\n",
888*4882a593Smuzhiyun ndev->name, db->membase, ndev->irq, ndev->dev_addr);
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun return 0;
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun out_release_sram:
893*4882a593Smuzhiyun sunxi_sram_release(&pdev->dev);
894*4882a593Smuzhiyun out_clk_disable_unprepare:
895*4882a593Smuzhiyun clk_disable_unprepare(db->clk);
896*4882a593Smuzhiyun out_dispose_mapping:
897*4882a593Smuzhiyun irq_dispose_mapping(ndev->irq);
898*4882a593Smuzhiyun out_iounmap:
899*4882a593Smuzhiyun iounmap(db->membase);
900*4882a593Smuzhiyun out:
901*4882a593Smuzhiyun dev_err(db->dev, "not found (%d).\n", ret);
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun free_netdev(ndev);
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun return ret;
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun
emac_remove(struct platform_device * pdev)908*4882a593Smuzhiyun static int emac_remove(struct platform_device *pdev)
909*4882a593Smuzhiyun {
910*4882a593Smuzhiyun struct net_device *ndev = platform_get_drvdata(pdev);
911*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(ndev);
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun unregister_netdev(ndev);
914*4882a593Smuzhiyun sunxi_sram_release(&pdev->dev);
915*4882a593Smuzhiyun clk_disable_unprepare(db->clk);
916*4882a593Smuzhiyun irq_dispose_mapping(ndev->irq);
917*4882a593Smuzhiyun iounmap(db->membase);
918*4882a593Smuzhiyun free_netdev(ndev);
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun dev_dbg(&pdev->dev, "released and freed device\n");
921*4882a593Smuzhiyun return 0;
922*4882a593Smuzhiyun }
923*4882a593Smuzhiyun
emac_suspend(struct platform_device * dev,pm_message_t state)924*4882a593Smuzhiyun static int emac_suspend(struct platform_device *dev, pm_message_t state)
925*4882a593Smuzhiyun {
926*4882a593Smuzhiyun struct net_device *ndev = platform_get_drvdata(dev);
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun netif_carrier_off(ndev);
929*4882a593Smuzhiyun netif_device_detach(ndev);
930*4882a593Smuzhiyun emac_shutdown(ndev);
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun return 0;
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun
emac_resume(struct platform_device * dev)935*4882a593Smuzhiyun static int emac_resume(struct platform_device *dev)
936*4882a593Smuzhiyun {
937*4882a593Smuzhiyun struct net_device *ndev = platform_get_drvdata(dev);
938*4882a593Smuzhiyun struct emac_board_info *db = netdev_priv(ndev);
939*4882a593Smuzhiyun
940*4882a593Smuzhiyun emac_reset(db);
941*4882a593Smuzhiyun emac_init_device(ndev);
942*4882a593Smuzhiyun netif_device_attach(ndev);
943*4882a593Smuzhiyun
944*4882a593Smuzhiyun return 0;
945*4882a593Smuzhiyun }
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun static const struct of_device_id emac_of_match[] = {
948*4882a593Smuzhiyun {.compatible = "allwinner,sun4i-a10-emac",},
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun /* Deprecated */
951*4882a593Smuzhiyun {.compatible = "allwinner,sun4i-emac",},
952*4882a593Smuzhiyun {},
953*4882a593Smuzhiyun };
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, emac_of_match);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun static struct platform_driver emac_driver = {
958*4882a593Smuzhiyun .driver = {
959*4882a593Smuzhiyun .name = "sun4i-emac",
960*4882a593Smuzhiyun .of_match_table = emac_of_match,
961*4882a593Smuzhiyun },
962*4882a593Smuzhiyun .probe = emac_probe,
963*4882a593Smuzhiyun .remove = emac_remove,
964*4882a593Smuzhiyun .suspend = emac_suspend,
965*4882a593Smuzhiyun .resume = emac_resume,
966*4882a593Smuzhiyun };
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun module_platform_driver(emac_driver);
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun MODULE_AUTHOR("Stefan Roese <sr@denx.de>");
971*4882a593Smuzhiyun MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
972*4882a593Smuzhiyun MODULE_DESCRIPTION("Allwinner A10 emac network driver");
973*4882a593Smuzhiyun MODULE_LICENSE("GPL");
974