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