diff options
author | Anatolij Gustschin <agust@denx.de> | 2010-02-26 07:00:48 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-27 05:34:35 -0500 |
commit | 60ab4361adc188fb47da1c4892cc7a2bb621efef (patch) | |
tree | 7949c204769f3bf400f9c4806082a122bc6e8e79 | |
parent | fcb6a1c83e48c30ff99624e9c46ce301707ede05 (diff) |
fs_enet: Add support for MPC512x to fs_enet driver
Extend the fs_enet driver to support MPC512x FEC.
Enable it with CONFIG_FS_ENET_MPC5121_FEC option.
Signed-off-by: John Rigby <jcrigby@gmail.com>
Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/fs_enet/Kconfig | 10 | ||||
-rw-r--r-- | drivers/net/fs_enet/fs_enet-main.c | 7 | ||||
-rw-r--r-- | drivers/net/fs_enet/fs_enet.h | 49 | ||||
-rw-r--r-- | drivers/net/fs_enet/mac-fec.c | 46 | ||||
-rw-r--r-- | drivers/net/fs_enet/mii-fec.c | 4 |
5 files changed, 95 insertions, 21 deletions
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig index 562ea68ed99b..fc073b5a38c7 100644 --- a/drivers/net/fs_enet/Kconfig +++ b/drivers/net/fs_enet/Kconfig | |||
@@ -1,9 +1,13 @@ | |||
1 | config FS_ENET | 1 | config FS_ENET |
2 | tristate "Freescale Ethernet Driver" | 2 | tristate "Freescale Ethernet Driver" |
3 | depends on CPM1 || CPM2 | 3 | depends on CPM1 || CPM2 || PPC_MPC512x |
4 | select MII | 4 | select MII |
5 | select PHYLIB | 5 | select PHYLIB |
6 | 6 | ||
7 | config FS_ENET_MPC5121_FEC | ||
8 | def_bool y if (FS_ENET && PPC_MPC512x) | ||
9 | select FS_ENET_HAS_FEC | ||
10 | |||
7 | config FS_ENET_HAS_SCC | 11 | config FS_ENET_HAS_SCC |
8 | bool "Chip has an SCC usable for ethernet" | 12 | bool "Chip has an SCC usable for ethernet" |
9 | depends on FS_ENET && (CPM1 || CPM2) | 13 | depends on FS_ENET && (CPM1 || CPM2) |
@@ -16,13 +20,13 @@ config FS_ENET_HAS_FCC | |||
16 | 20 | ||
17 | config FS_ENET_HAS_FEC | 21 | config FS_ENET_HAS_FEC |
18 | bool "Chip has an FEC usable for ethernet" | 22 | bool "Chip has an FEC usable for ethernet" |
19 | depends on FS_ENET && CPM1 | 23 | depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC) |
20 | select FS_ENET_MDIO_FEC | 24 | select FS_ENET_MDIO_FEC |
21 | default y | 25 | default y |
22 | 26 | ||
23 | config FS_ENET_MDIO_FEC | 27 | config FS_ENET_MDIO_FEC |
24 | tristate "MDIO driver for FEC" | 28 | tristate "MDIO driver for FEC" |
25 | depends on FS_ENET && CPM1 | 29 | depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC) |
26 | 30 | ||
27 | config FS_ENET_MDIO_FCC | 31 | config FS_ENET_MDIO_FCC |
28 | tristate "MDIO driver for FCC" | 32 | tristate "MDIO driver for FCC" |
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index c34a7e0a28ed..4297021214d1 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c | |||
@@ -1094,11 +1094,18 @@ static struct of_device_id fs_enet_match[] = { | |||
1094 | }, | 1094 | }, |
1095 | #endif | 1095 | #endif |
1096 | #ifdef CONFIG_FS_ENET_HAS_FEC | 1096 | #ifdef CONFIG_FS_ENET_HAS_FEC |
1097 | #ifdef CONFIG_FS_ENET_MPC5121_FEC | ||
1098 | { | ||
1099 | .compatible = "fsl,mpc5121-fec", | ||
1100 | .data = (void *)&fs_fec_ops, | ||
1101 | }, | ||
1102 | #else | ||
1097 | { | 1103 | { |
1098 | .compatible = "fsl,pq1-fec-enet", | 1104 | .compatible = "fsl,pq1-fec-enet", |
1099 | .data = (void *)&fs_fec_ops, | 1105 | .data = (void *)&fs_fec_ops, |
1100 | }, | 1106 | }, |
1101 | #endif | 1107 | #endif |
1108 | #endif | ||
1102 | {} | 1109 | {} |
1103 | }; | 1110 | }; |
1104 | MODULE_DEVICE_TABLE(of, fs_enet_match); | 1111 | MODULE_DEVICE_TABLE(of, fs_enet_match); |
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index ef01e09781a5..1ece4b1a689e 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h | |||
@@ -13,9 +13,56 @@ | |||
13 | 13 | ||
14 | #ifdef CONFIG_CPM1 | 14 | #ifdef CONFIG_CPM1 |
15 | #include <asm/cpm1.h> | 15 | #include <asm/cpm1.h> |
16 | #endif | ||
17 | |||
18 | #if defined(CONFIG_FS_ENET_HAS_FEC) | ||
19 | #include <asm/cpm.h> | ||
20 | |||
21 | #if defined(CONFIG_FS_ENET_MPC5121_FEC) | ||
22 | /* MPC5121 FEC has different register layout */ | ||
23 | struct fec { | ||
24 | u32 fec_reserved0; | ||
25 | u32 fec_ievent; /* Interrupt event reg */ | ||
26 | u32 fec_imask; /* Interrupt mask reg */ | ||
27 | u32 fec_reserved1; | ||
28 | u32 fec_r_des_active; /* Receive descriptor reg */ | ||
29 | u32 fec_x_des_active; /* Transmit descriptor reg */ | ||
30 | u32 fec_reserved2[3]; | ||
31 | u32 fec_ecntrl; /* Ethernet control reg */ | ||
32 | u32 fec_reserved3[6]; | ||
33 | u32 fec_mii_data; /* MII manage frame reg */ | ||
34 | u32 fec_mii_speed; /* MII speed control reg */ | ||
35 | u32 fec_reserved4[7]; | ||
36 | u32 fec_mib_ctrlstat; /* MIB control/status reg */ | ||
37 | u32 fec_reserved5[7]; | ||
38 | u32 fec_r_cntrl; /* Receive control reg */ | ||
39 | u32 fec_reserved6[15]; | ||
40 | u32 fec_x_cntrl; /* Transmit Control reg */ | ||
41 | u32 fec_reserved7[7]; | ||
42 | u32 fec_addr_low; /* Low 32bits MAC address */ | ||
43 | u32 fec_addr_high; /* High 16bits MAC address */ | ||
44 | u32 fec_opd; /* Opcode + Pause duration */ | ||
45 | u32 fec_reserved8[10]; | ||
46 | u32 fec_hash_table_high; /* High 32bits hash table */ | ||
47 | u32 fec_hash_table_low; /* Low 32bits hash table */ | ||
48 | u32 fec_grp_hash_table_high; /* High 32bits hash table */ | ||
49 | u32 fec_grp_hash_table_low; /* Low 32bits hash table */ | ||
50 | u32 fec_reserved9[7]; | ||
51 | u32 fec_x_wmrk; /* FIFO transmit water mark */ | ||
52 | u32 fec_reserved10; | ||
53 | u32 fec_r_bound; /* FIFO receive bound reg */ | ||
54 | u32 fec_r_fstart; /* FIFO receive start reg */ | ||
55 | u32 fec_reserved11[11]; | ||
56 | u32 fec_r_des_start; /* Receive descriptor ring */ | ||
57 | u32 fec_x_des_start; /* Transmit descriptor ring */ | ||
58 | u32 fec_r_buff_size; /* Maximum receive buff size */ | ||
59 | u32 fec_reserved12[26]; | ||
60 | u32 fec_dma_control; /* DMA Endian and other ctrl */ | ||
61 | }; | ||
62 | #endif | ||
16 | 63 | ||
17 | struct fec_info { | 64 | struct fec_info { |
18 | fec_t __iomem *fecp; | 65 | struct fec __iomem *fecp; |
19 | u32 mii_speed; | 66 | u32 mii_speed; |
20 | }; | 67 | }; |
21 | #endif | 68 | #endif |
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 8a632f668c1f..cd2c6cca5f24 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c | |||
@@ -80,7 +80,7 @@ | |||
80 | */ | 80 | */ |
81 | #define FEC_RESET_DELAY 50 | 81 | #define FEC_RESET_DELAY 50 |
82 | 82 | ||
83 | static int whack_reset(fec_t __iomem *fecp) | 83 | static int whack_reset(struct fec __iomem *fecp) |
84 | { | 84 | { |
85 | int i; | 85 | int i; |
86 | 86 | ||
@@ -168,7 +168,7 @@ static void cleanup_data(struct net_device *dev) | |||
168 | static void set_promiscuous_mode(struct net_device *dev) | 168 | static void set_promiscuous_mode(struct net_device *dev) |
169 | { | 169 | { |
170 | struct fs_enet_private *fep = netdev_priv(dev); | 170 | struct fs_enet_private *fep = netdev_priv(dev); |
171 | fec_t __iomem *fecp = fep->fec.fecp; | 171 | struct fec __iomem *fecp = fep->fec.fecp; |
172 | 172 | ||
173 | FS(fecp, r_cntrl, FEC_RCNTRL_PROM); | 173 | FS(fecp, r_cntrl, FEC_RCNTRL_PROM); |
174 | } | 174 | } |
@@ -216,7 +216,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac) | |||
216 | static void set_multicast_finish(struct net_device *dev) | 216 | static void set_multicast_finish(struct net_device *dev) |
217 | { | 217 | { |
218 | struct fs_enet_private *fep = netdev_priv(dev); | 218 | struct fs_enet_private *fep = netdev_priv(dev); |
219 | fec_t __iomem *fecp = fep->fec.fecp; | 219 | struct fec __iomem *fecp = fep->fec.fecp; |
220 | 220 | ||
221 | /* if all multi or too many multicasts; just enable all */ | 221 | /* if all multi or too many multicasts; just enable all */ |
222 | if ((dev->flags & IFF_ALLMULTI) != 0 || | 222 | if ((dev->flags & IFF_ALLMULTI) != 0 || |
@@ -246,7 +246,7 @@ static void set_multicast_list(struct net_device *dev) | |||
246 | static void restart(struct net_device *dev) | 246 | static void restart(struct net_device *dev) |
247 | { | 247 | { |
248 | struct fs_enet_private *fep = netdev_priv(dev); | 248 | struct fs_enet_private *fep = netdev_priv(dev); |
249 | fec_t __iomem *fecp = fep->fec.fecp; | 249 | struct fec __iomem *fecp = fep->fec.fecp; |
250 | const struct fs_platform_info *fpi = fep->fpi; | 250 | const struct fs_platform_info *fpi = fep->fpi; |
251 | dma_addr_t rx_bd_base_phys, tx_bd_base_phys; | 251 | dma_addr_t rx_bd_base_phys, tx_bd_base_phys; |
252 | int r; | 252 | int r; |
@@ -280,7 +280,11 @@ static void restart(struct net_device *dev) | |||
280 | * Set maximum receive buffer size. | 280 | * Set maximum receive buffer size. |
281 | */ | 281 | */ |
282 | FW(fecp, r_buff_size, PKT_MAXBLR_SIZE); | 282 | FW(fecp, r_buff_size, PKT_MAXBLR_SIZE); |
283 | #ifdef CONFIG_FS_ENET_MPC5121_FEC | ||
284 | FW(fecp, r_cntrl, PKT_MAXBUF_SIZE << 16); | ||
285 | #else | ||
283 | FW(fecp, r_hash, PKT_MAXBUF_SIZE); | 286 | FW(fecp, r_hash, PKT_MAXBUF_SIZE); |
287 | #endif | ||
284 | 288 | ||
285 | /* get physical address */ | 289 | /* get physical address */ |
286 | rx_bd_base_phys = fep->ring_mem_addr; | 290 | rx_bd_base_phys = fep->ring_mem_addr; |
@@ -297,7 +301,11 @@ static void restart(struct net_device *dev) | |||
297 | /* | 301 | /* |
298 | * Enable big endian and don't care about SDMA FC. | 302 | * Enable big endian and don't care about SDMA FC. |
299 | */ | 303 | */ |
304 | #ifdef CONFIG_FS_ENET_MPC5121_FEC | ||
305 | FS(fecp, dma_control, 0xC0000000); | ||
306 | #else | ||
300 | FW(fecp, fun_code, 0x78000000); | 307 | FW(fecp, fun_code, 0x78000000); |
308 | #endif | ||
301 | 309 | ||
302 | /* | 310 | /* |
303 | * Set MII speed. | 311 | * Set MII speed. |
@@ -308,9 +316,17 @@ static void restart(struct net_device *dev) | |||
308 | * Clear any outstanding interrupt. | 316 | * Clear any outstanding interrupt. |
309 | */ | 317 | */ |
310 | FW(fecp, ievent, 0xffc0); | 318 | FW(fecp, ievent, 0xffc0); |
319 | #ifndef CONFIG_FS_ENET_MPC5121_FEC | ||
311 | FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29); | 320 | FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29); |
312 | 321 | ||
313 | FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ | 322 | FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ |
323 | #else | ||
324 | /* | ||
325 | * Only set MII mode - do not touch maximum frame length | ||
326 | * configured before. | ||
327 | */ | ||
328 | FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); | ||
329 | #endif | ||
314 | /* | 330 | /* |
315 | * adjust to duplex mode | 331 | * adjust to duplex mode |
316 | */ | 332 | */ |
@@ -339,7 +355,7 @@ static void stop(struct net_device *dev) | |||
339 | { | 355 | { |
340 | struct fs_enet_private *fep = netdev_priv(dev); | 356 | struct fs_enet_private *fep = netdev_priv(dev); |
341 | const struct fs_platform_info *fpi = fep->fpi; | 357 | const struct fs_platform_info *fpi = fep->fpi; |
342 | fec_t __iomem *fecp = fep->fec.fecp; | 358 | struct fec __iomem *fecp = fep->fec.fecp; |
343 | 359 | ||
344 | struct fec_info* feci= fep->phydev->bus->priv; | 360 | struct fec_info* feci= fep->phydev->bus->priv; |
345 | 361 | ||
@@ -375,7 +391,7 @@ static void stop(struct net_device *dev) | |||
375 | static void napi_clear_rx_event(struct net_device *dev) | 391 | static void napi_clear_rx_event(struct net_device *dev) |
376 | { | 392 | { |
377 | struct fs_enet_private *fep = netdev_priv(dev); | 393 | struct fs_enet_private *fep = netdev_priv(dev); |
378 | fec_t __iomem *fecp = fep->fec.fecp; | 394 | struct fec __iomem *fecp = fep->fec.fecp; |
379 | 395 | ||
380 | FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK); | 396 | FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK); |
381 | } | 397 | } |
@@ -383,7 +399,7 @@ static void napi_clear_rx_event(struct net_device *dev) | |||
383 | static void napi_enable_rx(struct net_device *dev) | 399 | static void napi_enable_rx(struct net_device *dev) |
384 | { | 400 | { |
385 | struct fs_enet_private *fep = netdev_priv(dev); | 401 | struct fs_enet_private *fep = netdev_priv(dev); |
386 | fec_t __iomem *fecp = fep->fec.fecp; | 402 | struct fec __iomem *fecp = fep->fec.fecp; |
387 | 403 | ||
388 | FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK); | 404 | FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK); |
389 | } | 405 | } |
@@ -391,7 +407,7 @@ static void napi_enable_rx(struct net_device *dev) | |||
391 | static void napi_disable_rx(struct net_device *dev) | 407 | static void napi_disable_rx(struct net_device *dev) |
392 | { | 408 | { |
393 | struct fs_enet_private *fep = netdev_priv(dev); | 409 | struct fs_enet_private *fep = netdev_priv(dev); |
394 | fec_t __iomem *fecp = fep->fec.fecp; | 410 | struct fec __iomem *fecp = fep->fec.fecp; |
395 | 411 | ||
396 | FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK); | 412 | FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK); |
397 | } | 413 | } |
@@ -399,7 +415,7 @@ static void napi_disable_rx(struct net_device *dev) | |||
399 | static void rx_bd_done(struct net_device *dev) | 415 | static void rx_bd_done(struct net_device *dev) |
400 | { | 416 | { |
401 | struct fs_enet_private *fep = netdev_priv(dev); | 417 | struct fs_enet_private *fep = netdev_priv(dev); |
402 | fec_t __iomem *fecp = fep->fec.fecp; | 418 | struct fec __iomem *fecp = fep->fec.fecp; |
403 | 419 | ||
404 | FW(fecp, r_des_active, 0x01000000); | 420 | FW(fecp, r_des_active, 0x01000000); |
405 | } | 421 | } |
@@ -407,7 +423,7 @@ static void rx_bd_done(struct net_device *dev) | |||
407 | static void tx_kickstart(struct net_device *dev) | 423 | static void tx_kickstart(struct net_device *dev) |
408 | { | 424 | { |
409 | struct fs_enet_private *fep = netdev_priv(dev); | 425 | struct fs_enet_private *fep = netdev_priv(dev); |
410 | fec_t __iomem *fecp = fep->fec.fecp; | 426 | struct fec __iomem *fecp = fep->fec.fecp; |
411 | 427 | ||
412 | FW(fecp, x_des_active, 0x01000000); | 428 | FW(fecp, x_des_active, 0x01000000); |
413 | } | 429 | } |
@@ -415,7 +431,7 @@ static void tx_kickstart(struct net_device *dev) | |||
415 | static u32 get_int_events(struct net_device *dev) | 431 | static u32 get_int_events(struct net_device *dev) |
416 | { | 432 | { |
417 | struct fs_enet_private *fep = netdev_priv(dev); | 433 | struct fs_enet_private *fep = netdev_priv(dev); |
418 | fec_t __iomem *fecp = fep->fec.fecp; | 434 | struct fec __iomem *fecp = fep->fec.fecp; |
419 | 435 | ||
420 | return FR(fecp, ievent) & FR(fecp, imask); | 436 | return FR(fecp, ievent) & FR(fecp, imask); |
421 | } | 437 | } |
@@ -423,7 +439,7 @@ static u32 get_int_events(struct net_device *dev) | |||
423 | static void clear_int_events(struct net_device *dev, u32 int_events) | 439 | static void clear_int_events(struct net_device *dev, u32 int_events) |
424 | { | 440 | { |
425 | struct fs_enet_private *fep = netdev_priv(dev); | 441 | struct fs_enet_private *fep = netdev_priv(dev); |
426 | fec_t __iomem *fecp = fep->fec.fecp; | 442 | struct fec __iomem *fecp = fep->fec.fecp; |
427 | 443 | ||
428 | FW(fecp, ievent, int_events); | 444 | FW(fecp, ievent, int_events); |
429 | } | 445 | } |
@@ -439,17 +455,17 @@ static int get_regs(struct net_device *dev, void *p, int *sizep) | |||
439 | { | 455 | { |
440 | struct fs_enet_private *fep = netdev_priv(dev); | 456 | struct fs_enet_private *fep = netdev_priv(dev); |
441 | 457 | ||
442 | if (*sizep < sizeof(fec_t)) | 458 | if (*sizep < sizeof(struct fec)) |
443 | return -EINVAL; | 459 | return -EINVAL; |
444 | 460 | ||
445 | memcpy_fromio(p, fep->fec.fecp, sizeof(fec_t)); | 461 | memcpy_fromio(p, fep->fec.fecp, sizeof(struct fec)); |
446 | 462 | ||
447 | return 0; | 463 | return 0; |
448 | } | 464 | } |
449 | 465 | ||
450 | static int get_regs_len(struct net_device *dev) | 466 | static int get_regs_len(struct net_device *dev) |
451 | { | 467 | { |
452 | return sizeof(fec_t); | 468 | return sizeof(struct fec); |
453 | } | 469 | } |
454 | 470 | ||
455 | static void tx_restart(struct net_device *dev) | 471 | static void tx_restart(struct net_device *dev) |
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index 96eba4280c5c..5944b65082cb 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c | |||
@@ -52,7 +52,7 @@ | |||
52 | static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) | 52 | static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) |
53 | { | 53 | { |
54 | struct fec_info* fec = bus->priv; | 54 | struct fec_info* fec = bus->priv; |
55 | fec_t __iomem *fecp = fec->fecp; | 55 | struct fec __iomem *fecp = fec->fecp; |
56 | int i, ret = -1; | 56 | int i, ret = -1; |
57 | 57 | ||
58 | BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); | 58 | BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); |
@@ -75,7 +75,7 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) | |||
75 | static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) | 75 | static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) |
76 | { | 76 | { |
77 | struct fec_info* fec = bus->priv; | 77 | struct fec_info* fec = bus->priv; |
78 | fec_t __iomem *fecp = fec->fecp; | 78 | struct fec __iomem *fecp = fec->fecp; |
79 | int i; | 79 | int i; |
80 | 80 | ||
81 | /* this must never happen */ | 81 | /* this must never happen */ |