Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
29e1846a
Commit
29e1846a
authored
Feb 15, 2011
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'fec' of
git://git.pengutronix.de/git/ukl/linux-2.6
parents
f39925db
cd1f402c
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
328 additions
and
325 deletions
+328
-325
drivers/net/Kconfig
drivers/net/Kconfig
+2
-1
drivers/net/fec.c
drivers/net/fec.c
+326
-324
No files found.
drivers/net/Kconfig
View file @
29e1846a
...
...
@@ -1944,7 +1944,8 @@ config 68360_ENET
config FEC
bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 || SOC_IMX28
IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC
default IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC if ARM
select PHYLIB
help
Say Y here if you want to use the built-in 10/100 Fast ethernet
...
...
drivers/net/fec.c
View file @
29e1846a
...
...
@@ -54,7 +54,7 @@
#include "fec.h"
#if defined(CONFIG_AR
CH_MXC) || defined(CONFIG_SOC_IMX28
)
#if defined(CONFIG_AR
M
)
#define FEC_ALIGNMENT 0xf
#else
#define FEC_ALIGNMENT 0x3
...
...
@@ -147,8 +147,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
* account when setting it.
*/
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
#else
#define OPT_FRAME_SIZE 0
...
...
@@ -183,7 +182,7 @@ struct fec_enet_private {
struct
bufdesc
*
rx_bd_base
;
struct
bufdesc
*
tx_bd_base
;
/* The next free ring entry */
struct
bufdesc
*
cur_rx
,
*
cur_tx
;
struct
bufdesc
*
cur_rx
,
*
cur_tx
;
/* The ring entries to be free()ed */
struct
bufdesc
*
dirty_tx
;
...
...
@@ -191,28 +190,21 @@ struct fec_enet_private {
/* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
spinlock_t
hw_lock
;
struct
platform_device
*
pdev
;
struct
platform_device
*
pdev
;
int
opened
;
/* Phylib and MDIO interface */
struct
mii_bus
*
mii_bus
;
struct
phy_device
*
phy_dev
;
int
mii_timeout
;
uint
phy_speed
;
struct
mii_bus
*
mii_bus
;
struct
phy_device
*
phy_dev
;
int
mii_timeout
;
uint
phy_speed
;
phy_interface_t
phy_interface
;
int
link
;
int
full_duplex
;
struct
completion
mdio_done
;
};
static
irqreturn_t
fec_enet_interrupt
(
int
irq
,
void
*
dev_id
);
static
void
fec_enet_tx
(
struct
net_device
*
dev
);
static
void
fec_enet_rx
(
struct
net_device
*
dev
);
static
int
fec_enet_close
(
struct
net_device
*
dev
);
static
void
fec_restart
(
struct
net_device
*
dev
,
int
duplex
);
static
void
fec_stop
(
struct
net_device
*
dev
);
/* FEC MII MMFR bits definition */
#define FEC_MMFR_ST (1 << 30)
#define FEC_MMFR_OP_READ (2 << 28)
...
...
@@ -239,9 +231,9 @@ static void *swap_buffer(void *bufaddr, int len)
}
static
netdev_tx_t
fec_enet_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
fec_enet_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
const
struct
platform_device_id
*
id_entry
=
platform_get_device_id
(
fep
->
pdev
);
struct
bufdesc
*
bdp
;
...
...
@@ -262,9 +254,9 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if
(
status
&
BD_ENET_TX_READY
)
{
/* Ooops. All transmit buffers are full. Bail out.
* This should not happen, since dev->tbusy should be set.
* This should not happen, since
n
dev->tbusy should be set.
*/
printk
(
"%s: tx queue full!.
\n
"
,
dev
->
name
);
printk
(
"%s: tx queue full!.
\n
"
,
n
dev
->
name
);
spin_unlock_irqrestore
(
&
fep
->
hw_lock
,
flags
);
return
NETDEV_TX_BUSY
;
}
...
...
@@ -284,7 +276,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if
(((
unsigned
long
)
bufaddr
)
&
FEC_ALIGNMENT
)
{
unsigned
int
index
;
index
=
bdp
-
fep
->
tx_bd_base
;
memcpy
(
fep
->
tx_bounce
[
index
],
(
void
*
)
skb
->
data
,
skb
->
len
);
memcpy
(
fep
->
tx_bounce
[
index
],
skb
->
data
,
skb
->
len
);
bufaddr
=
fep
->
tx_bounce
[
index
];
}
...
...
@@ -299,13 +291,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Save skb pointer */
fep
->
tx_skbuff
[
fep
->
skb_cur
]
=
skb
;
dev
->
stats
.
tx_bytes
+=
skb
->
len
;
n
dev
->
stats
.
tx_bytes
+=
skb
->
len
;
fep
->
skb_cur
=
(
fep
->
skb_cur
+
1
)
&
TX_RING_MOD_MASK
;
/* Push the data cache so the CPM does not get stale memory
* data.
*/
bdp
->
cbd_bufaddr
=
dma_map_single
(
&
dev
->
dev
,
bufaddr
,
bdp
->
cbd_bufaddr
=
dma_map_single
(
&
fep
->
p
dev
->
dev
,
bufaddr
,
FEC_ENET_TX_FRSIZE
,
DMA_TO_DEVICE
);
/* Send it on its way. Tell FEC it's ready, interrupt when done,
...
...
@@ -326,7 +318,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if
(
bdp
==
fep
->
dirty_tx
)
{
fep
->
tx_full
=
1
;
netif_stop_queue
(
dev
);
netif_stop_queue
(
n
dev
);
}
fep
->
cur_tx
=
bdp
;
...
...
@@ -336,62 +328,170 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
return
NETDEV_TX_OK
;
}
/* This function is called to start or restart the FEC during a link
* change. This only happens when switching between half and full
* duplex.
*/
static
void
fec_
timeout
(
struct
net_device
*
dev
)
fec_
restart
(
struct
net_device
*
ndev
,
int
duplex
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
ndev
);
const
struct
platform_device_id
*
id_entry
=
platform_get_device_id
(
fep
->
pdev
);
int
i
;
u32
temp_mac
[
2
];
u32
rcntl
=
OPT_FRAME_SIZE
|
0x04
;
dev
->
stats
.
tx_errors
++
;
/* Whack a reset. We should wait for this. */
writel
(
1
,
fep
->
hwp
+
FEC_ECNTRL
);
udelay
(
10
);
fec_restart
(
dev
,
fep
->
full_duplex
);
netif_wake_queue
(
dev
);
}
/*
* enet-mac reset will reset mac address registers too,
* so need to reconfigure it.
*/
if
(
id_entry
->
driver_data
&
FEC_QUIRK_ENET_MAC
)
{
memcpy
(
&
temp_mac
,
ndev
->
dev_addr
,
ETH_ALEN
);
writel
(
cpu_to_be32
(
temp_mac
[
0
]),
fep
->
hwp
+
FEC_ADDR_LOW
);
writel
(
cpu_to_be32
(
temp_mac
[
1
]),
fep
->
hwp
+
FEC_ADDR_HIGH
);
}
static
irqreturn_t
fec_enet_interrupt
(
int
irq
,
void
*
dev_id
)
{
struct
net_device
*
dev
=
dev_id
;
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
uint
int_events
;
irqreturn_t
ret
=
IRQ_NONE
;
/* Clear any outstanding interrupt. */
writel
(
0xffc00000
,
fep
->
hwp
+
FEC_IEVENT
);
do
{
int_events
=
readl
(
fep
->
hwp
+
FEC_IEVENT
);
writel
(
int_events
,
fep
->
hwp
+
FEC_IEVENT
);
/* Reset all multicast. */
writel
(
0
,
fep
->
hwp
+
FEC_GRP_HASH_TABLE_HIGH
);
writel
(
0
,
fep
->
hwp
+
FEC_GRP_HASH_TABLE_LOW
);
#ifndef CONFIG_M5272
writel
(
0
,
fep
->
hwp
+
FEC_HASH_TABLE_HIGH
);
writel
(
0
,
fep
->
hwp
+
FEC_HASH_TABLE_LOW
);
#endif
if
(
int_events
&
FEC_ENET_RXF
)
{
ret
=
IRQ_HANDLED
;
fec_enet_rx
(
dev
);
}
/* Set maximum receive buffer size. */
writel
(
PKT_MAXBLR_SIZE
,
fep
->
hwp
+
FEC_R_BUFF_SIZE
);
/* Transmit OK, or non-fatal error. Update the buffer
* descriptors. FEC handles all errors, we just discover
* them as part of the transmit process.
*/
if
(
int_events
&
FEC_ENET_TXF
)
{
ret
=
IRQ_HANDLED
;
fec_enet_tx
(
dev
);
/* Set receive and transmit descriptor base. */
writel
(
fep
->
bd_dma
,
fep
->
hwp
+
FEC_R_DES_START
);
writel
((
unsigned
long
)
fep
->
bd_dma
+
sizeof
(
struct
bufdesc
)
*
RX_RING_SIZE
,
fep
->
hwp
+
FEC_X_DES_START
);
fep
->
dirty_tx
=
fep
->
cur_tx
=
fep
->
tx_bd_base
;
fep
->
cur_rx
=
fep
->
rx_bd_base
;
/* Reset SKB transmit buffers. */
fep
->
skb_cur
=
fep
->
skb_dirty
=
0
;
for
(
i
=
0
;
i
<=
TX_RING_MOD_MASK
;
i
++
)
{
if
(
fep
->
tx_skbuff
[
i
])
{
dev_kfree_skb_any
(
fep
->
tx_skbuff
[
i
]);
fep
->
tx_skbuff
[
i
]
=
NULL
;
}
}
if
(
int_events
&
FEC_ENET_MII
)
{
ret
=
IRQ_HANDLED
;
complete
(
&
fep
->
mdio_done
);
/* Enable MII mode */
if
(
duplex
)
{
/* FD enable */
writel
(
0x04
,
fep
->
hwp
+
FEC_X_CNTRL
);
}
else
{
/* No Rcv on Xmit */
rcntl
|=
0x02
;
writel
(
0x0
,
fep
->
hwp
+
FEC_X_CNTRL
);
}
fep
->
full_duplex
=
duplex
;
/* Set MII speed */
writel
(
fep
->
phy_speed
,
fep
->
hwp
+
FEC_MII_SPEED
);
/*
* The phy interface and speed need to get configured
* differently on enet-mac.
*/
if
(
id_entry
->
driver_data
&
FEC_QUIRK_ENET_MAC
)
{
/* Enable flow control and length check */
rcntl
|=
0x40000000
|
0x00000020
;
/* MII or RMII */
if
(
fep
->
phy_interface
==
PHY_INTERFACE_MODE_RMII
)
rcntl
|=
(
1
<<
8
);
else
rcntl
&=
~
(
1
<<
8
);
/* 10M or 100M */
if
(
fep
->
phy_dev
&&
fep
->
phy_dev
->
speed
==
SPEED_100
)
rcntl
&=
~
(
1
<<
9
);
else
rcntl
|=
(
1
<<
9
);
}
else
{
#ifdef FEC_MIIGSK_ENR
if
(
fep
->
phy_interface
==
PHY_INTERFACE_MODE_RMII
)
{
/* disable the gasket and wait */
writel
(
0
,
fep
->
hwp
+
FEC_MIIGSK_ENR
);
while
(
readl
(
fep
->
hwp
+
FEC_MIIGSK_ENR
)
&
4
)
udelay
(
1
);
/*
* configure the gasket:
* RMII, 50 MHz, no loopback, no echo
*/
writel
(
1
,
fep
->
hwp
+
FEC_MIIGSK_CFGR
);
/* re-enable the gasket */
writel
(
2
,
fep
->
hwp
+
FEC_MIIGSK_ENR
);
}
}
while
(
int_events
);
#endif
}
writel
(
rcntl
,
fep
->
hwp
+
FEC_R_CNTRL
);
return
ret
;
/* And last, enable the transmit and receive processing */
writel
(
2
,
fep
->
hwp
+
FEC_ECNTRL
);
writel
(
0
,
fep
->
hwp
+
FEC_R_DES_ACTIVE
);
/* Enable interrupts we wish to service */
writel
(
FEC_DEFAULT_IMASK
,
fep
->
hwp
+
FEC_IMASK
);
}
static
void
fec_stop
(
struct
net_device
*
ndev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
ndev
);
/* We cannot expect a graceful transmit stop without link !!! */
if
(
fep
->
link
)
{
writel
(
1
,
fep
->
hwp
+
FEC_X_CNTRL
);
/* Graceful transmit stop */
udelay
(
10
);
if
(
!
(
readl
(
fep
->
hwp
+
FEC_IEVENT
)
&
FEC_ENET_GRA
))
printk
(
"fec_stop : Graceful transmit stop did not complete !
\n
"
);
}
/* Whack a reset. We should wait for this. */
writel
(
1
,
fep
->
hwp
+
FEC_ECNTRL
);
udelay
(
10
);
writel
(
fep
->
phy_speed
,
fep
->
hwp
+
FEC_MII_SPEED
);
writel
(
FEC_DEFAULT_IMASK
,
fep
->
hwp
+
FEC_IMASK
);
}
static
void
fec_enet_tx
(
struct
net_device
*
dev
)
fec_timeout
(
struct
net_device
*
ndev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
ndev
);
ndev
->
stats
.
tx_errors
++
;
fec_restart
(
ndev
,
fep
->
full_duplex
);
netif_wake_queue
(
ndev
);
}
static
void
fec_enet_tx
(
struct
net_device
*
ndev
)
{
struct
fec_enet_private
*
fep
;
struct
bufdesc
*
bdp
;
unsigned
short
status
;
struct
sk_buff
*
skb
;
fep
=
netdev_priv
(
dev
);
fep
=
netdev_priv
(
n
dev
);
spin_lock
(
&
fep
->
hw_lock
);
bdp
=
fep
->
dirty_tx
;
...
...
@@ -399,7 +499,8 @@ fec_enet_tx(struct net_device *dev)
if
(
bdp
==
fep
->
cur_tx
&&
fep
->
tx_full
==
0
)
break
;
dma_unmap_single
(
&
dev
->
dev
,
bdp
->
cbd_bufaddr
,
FEC_ENET_TX_FRSIZE
,
DMA_TO_DEVICE
);
dma_unmap_single
(
&
fep
->
pdev
->
dev
,
bdp
->
cbd_bufaddr
,
FEC_ENET_TX_FRSIZE
,
DMA_TO_DEVICE
);
bdp
->
cbd_bufaddr
=
0
;
skb
=
fep
->
tx_skbuff
[
fep
->
skb_dirty
];
...
...
@@ -407,19 +508,19 @@ fec_enet_tx(struct net_device *dev)
if
(
status
&
(
BD_ENET_TX_HB
|
BD_ENET_TX_LC
|
BD_ENET_TX_RL
|
BD_ENET_TX_UN
|
BD_ENET_TX_CSL
))
{
dev
->
stats
.
tx_errors
++
;
n
dev
->
stats
.
tx_errors
++
;
if
(
status
&
BD_ENET_TX_HB
)
/* No heartbeat */
dev
->
stats
.
tx_heartbeat_errors
++
;
n
dev
->
stats
.
tx_heartbeat_errors
++
;
if
(
status
&
BD_ENET_TX_LC
)
/* Late collision */
dev
->
stats
.
tx_window_errors
++
;
n
dev
->
stats
.
tx_window_errors
++
;
if
(
status
&
BD_ENET_TX_RL
)
/* Retrans limit */
dev
->
stats
.
tx_aborted_errors
++
;
n
dev
->
stats
.
tx_aborted_errors
++
;
if
(
status
&
BD_ENET_TX_UN
)
/* Underrun */
dev
->
stats
.
tx_fifo_errors
++
;
n
dev
->
stats
.
tx_fifo_errors
++
;
if
(
status
&
BD_ENET_TX_CSL
)
/* Carrier lost */
dev
->
stats
.
tx_carrier_errors
++
;
n
dev
->
stats
.
tx_carrier_errors
++
;
}
else
{
dev
->
stats
.
tx_packets
++
;
n
dev
->
stats
.
tx_packets
++
;
}
if
(
status
&
BD_ENET_TX_READY
)
...
...
@@ -429,7 +530,7 @@ fec_enet_tx(struct net_device *dev)
* but we eventually sent the packet OK.
*/
if
(
status
&
BD_ENET_TX_DEF
)
dev
->
stats
.
collisions
++
;
n
dev
->
stats
.
collisions
++
;
/* Free the sk buffer associated with this last transmit */
dev_kfree_skb_any
(
skb
);
...
...
@@ -446,8 +547,8 @@ fec_enet_tx(struct net_device *dev)
*/
if
(
fep
->
tx_full
)
{
fep
->
tx_full
=
0
;
if
(
netif_queue_stopped
(
dev
))
netif_wake_queue
(
dev
);
if
(
netif_queue_stopped
(
n
dev
))
netif_wake_queue
(
n
dev
);
}
}
fep
->
dirty_tx
=
bdp
;
...
...
@@ -461,9 +562,9 @@ fec_enet_tx(struct net_device *dev)
* effectively tossing the packet.
*/
static
void
fec_enet_rx
(
struct
net_device
*
dev
)
fec_enet_rx
(
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
const
struct
platform_device_id
*
id_entry
=
platform_get_device_id
(
fep
->
pdev
);
struct
bufdesc
*
bdp
;
...
...
@@ -497,17 +598,17 @@ fec_enet_rx(struct net_device *dev)
/* Check for errors. */
if
(
status
&
(
BD_ENET_RX_LG
|
BD_ENET_RX_SH
|
BD_ENET_RX_NO
|
BD_ENET_RX_CR
|
BD_ENET_RX_OV
))
{
dev
->
stats
.
rx_errors
++
;
n
dev
->
stats
.
rx_errors
++
;
if
(
status
&
(
BD_ENET_RX_LG
|
BD_ENET_RX_SH
))
{
/* Frame too long or too short. */
dev
->
stats
.
rx_length_errors
++
;
n
dev
->
stats
.
rx_length_errors
++
;
}
if
(
status
&
BD_ENET_RX_NO
)
/* Frame alignment */
dev
->
stats
.
rx_frame_errors
++
;
n
dev
->
stats
.
rx_frame_errors
++
;
if
(
status
&
BD_ENET_RX_CR
)
/* CRC Error */
dev
->
stats
.
rx_crc_errors
++
;
n
dev
->
stats
.
rx_crc_errors
++
;
if
(
status
&
BD_ENET_RX_OV
)
/* FIFO overrun */
dev
->
stats
.
rx_fifo_errors
++
;
n
dev
->
stats
.
rx_fifo_errors
++
;
}
/* Report late collisions as a frame error.
...
...
@@ -515,19 +616,19 @@ fec_enet_rx(struct net_device *dev)
* have in the buffer. So, just drop this frame on the floor.
*/
if
(
status
&
BD_ENET_RX_CL
)
{
dev
->
stats
.
rx_errors
++
;
dev
->
stats
.
rx_frame_errors
++
;
n
dev
->
stats
.
rx_errors
++
;
n
dev
->
stats
.
rx_frame_errors
++
;
goto
rx_processing_done
;
}
/* Process the incoming frame. */
dev
->
stats
.
rx_packets
++
;
n
dev
->
stats
.
rx_packets
++
;
pkt_len
=
bdp
->
cbd_datlen
;
dev
->
stats
.
rx_bytes
+=
pkt_len
;
n
dev
->
stats
.
rx_bytes
+=
pkt_len
;
data
=
(
__u8
*
)
__va
(
bdp
->
cbd_bufaddr
);
dma_unmap_single
(
NULL
,
bdp
->
cbd_bufaddr
,
bdp
->
cbd_datlen
,
DMA_FROM_DEVICE
);
dma_unmap_single
(
&
fep
->
pdev
->
dev
,
bdp
->
cbd_bufaddr
,
FEC_ENET_TX_FRSIZE
,
DMA_FROM_DEVICE
);
if
(
id_entry
->
driver_data
&
FEC_QUIRK_SWAP_FRAME
)
swap_buffer
(
data
,
pkt_len
);
...
...
@@ -541,18 +642,18 @@ fec_enet_rx(struct net_device *dev)
if
(
unlikely
(
!
skb
))
{
printk
(
"%s: Memory squeeze, dropping packet.
\n
"
,
dev
->
name
);
dev
->
stats
.
rx_dropped
++
;
n
dev
->
name
);
n
dev
->
stats
.
rx_dropped
++
;
}
else
{
skb_reserve
(
skb
,
NET_IP_ALIGN
);
skb_put
(
skb
,
pkt_len
-
4
);
/* Make room */
skb_copy_to_linear_data
(
skb
,
data
,
pkt_len
-
4
);
skb
->
protocol
=
eth_type_trans
(
skb
,
dev
);
skb
->
protocol
=
eth_type_trans
(
skb
,
n
dev
);
netif_rx
(
skb
);
}
bdp
->
cbd_bufaddr
=
dma_map_single
(
NULL
,
data
,
bdp
->
cbd_datlen
,
DMA_FROM_DEVICE
);
bdp
->
cbd_bufaddr
=
dma_map_single
(
&
fep
->
pdev
->
dev
,
data
,
FEC_ENET_TX_FRSIZE
,
DMA_FROM_DEVICE
);
rx_processing_done:
/* Clear the status flags for this buffer */
status
&=
~
BD_ENET_RX_STATS
;
...
...
@@ -577,10 +678,47 @@ fec_enet_rx(struct net_device *dev)
spin_unlock
(
&
fep
->
hw_lock
);
}
static
irqreturn_t
fec_enet_interrupt
(
int
irq
,
void
*
dev_id
)
{
struct
net_device
*
ndev
=
dev_id
;
struct
fec_enet_private
*
fep
=
netdev_priv
(
ndev
);
uint
int_events
;
irqreturn_t
ret
=
IRQ_NONE
;
do
{
int_events
=
readl
(
fep
->
hwp
+
FEC_IEVENT
);
writel
(
int_events
,
fep
->
hwp
+
FEC_IEVENT
);
if
(
int_events
&
FEC_ENET_RXF
)
{
ret
=
IRQ_HANDLED
;
fec_enet_rx
(
ndev
);
}
/* Transmit OK, or non-fatal error. Update the buffer
* descriptors. FEC handles all errors, we just discover
* them as part of the transmit process.
*/
if
(
int_events
&
FEC_ENET_TXF
)
{
ret
=
IRQ_HANDLED
;
fec_enet_tx
(
ndev
);
}
if
(
int_events
&
FEC_ENET_MII
)
{
ret
=
IRQ_HANDLED
;
complete
(
&
fep
->
mdio_done
);
}
}
while
(
int_events
);
return
ret
;
}
/* ------------------------------------------------------------------------- */
static
void
__inline__
fec_get_mac
(
struct
net_device
*
dev
)
static
void
__inline__
fec_get_mac
(
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
struct
fec_platform_data
*
pdata
=
fep
->
pdev
->
dev
.
platform_data
;
unsigned
char
*
iap
,
tmpaddr
[
ETH_ALEN
];
...
...
@@ -616,11 +754,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
iap
=
&
tmpaddr
[
0
];
}
memcpy
(
dev
->
dev_addr
,
iap
,
ETH_ALEN
);
memcpy
(
n
dev
->
dev_addr
,
iap
,
ETH_ALEN
);
/* Adjust MAC if using macaddr */
if
(
iap
==
macaddr
)
dev
->
dev_addr
[
ETH_ALEN
-
1
]
=
macaddr
[
ETH_ALEN
-
1
]
+
fep
->
pdev
->
id
;
n
dev
->
dev_addr
[
ETH_ALEN
-
1
]
=
macaddr
[
ETH_ALEN
-
1
]
+
fep
->
pdev
->
id
;
}
/* ------------------------------------------------------------------------- */
...
...
@@ -628,9 +766,9 @@ static void __inline__ fec_get_mac(struct net_device *dev)
/*
* Phy section
*/
static
void
fec_enet_adjust_link
(
struct
net_device
*
dev
)
static
void
fec_enet_adjust_link
(
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
struct
phy_device
*
phy_dev
=
fep
->
phy_dev
;
unsigned
long
flags
;
...
...
@@ -647,7 +785,7 @@ static void fec_enet_adjust_link(struct net_device *dev)
/* Duplex link change */
if
(
phy_dev
->
link
)
{
if
(
fep
->
full_duplex
!=
phy_dev
->
duplex
)
{
fec_restart
(
dev
,
phy_dev
->
duplex
);
fec_restart
(
n
dev
,
phy_dev
->
duplex
);
status_change
=
1
;
}
}
...
...
@@ -656,9 +794,9 @@ static void fec_enet_adjust_link(struct net_device *dev)
if
(
phy_dev
->
link
!=
fep
->
link
)
{
fep
->
link
=
phy_dev
->
link
;
if
(
phy_dev
->
link
)
fec_restart
(
dev
,
phy_dev
->
duplex
);
fec_restart
(
n
dev
,
phy_dev
->
duplex
);
else
fec_stop
(
dev
);
fec_stop
(
n
dev
);
status_change
=
1
;
}
...
...
@@ -727,9 +865,9 @@ static int fec_enet_mdio_reset(struct mii_bus *bus)
return
0
;
}
static
int
fec_enet_mii_probe
(
struct
net_device
*
dev
)
static
int
fec_enet_mii_probe
(
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
struct
phy_device
*
phy_dev
=
NULL
;
char
mdio_bus_id
[
MII_BUS_ID_SIZE
];
char
phy_name
[
MII_BUS_ID_SIZE
+
3
];
...
...
@@ -754,16 +892,16 @@ static int fec_enet_mii_probe(struct net_device *dev)
if
(
phy_id
>=
PHY_MAX_ADDR
)
{
printk
(
KERN_INFO
"%s: no PHY, assuming direct connection "
"to switch
\n
"
,
dev
->
name
);
"to switch
\n
"
,
n
dev
->
name
);
strncpy
(
mdio_bus_id
,
"0"
,
MII_BUS_ID_SIZE
);
phy_id
=
0
;
}
snprintf
(
phy_name
,
MII_BUS_ID_SIZE
,
PHY_ID_FMT
,
mdio_bus_id
,
phy_id
);
phy_dev
=
phy_connect
(
dev
,
phy_name
,
&
fec_enet_adjust_link
,
0
,
phy_dev
=
phy_connect
(
n
dev
,
phy_name
,
&
fec_enet_adjust_link
,
0
,
PHY_INTERFACE_MODE_MII
);
if
(
IS_ERR
(
phy_dev
))
{
printk
(
KERN_ERR
"%s: could not attach to PHY
\n
"
,
dev
->
name
);
printk
(
KERN_ERR
"%s: could not attach to PHY
\n
"
,
n
dev
->
name
);
return
PTR_ERR
(
phy_dev
);
}
...
...
@@ -776,7 +914,7 @@ static int fec_enet_mii_probe(struct net_device *dev)
fep
->
full_duplex
=
0
;
printk
(
KERN_INFO
"%s: Freescale FEC PHY driver [%s] "
"(mii_bus:phy_addr=%s, irq=%d)
\n
"
,
dev
->
name
,
"(mii_bus:phy_addr=%s, irq=%d)
\n
"
,
n
dev
->
name
,
fep
->
phy_dev
->
drv
->
name
,
dev_name
(
&
fep
->
phy_dev
->
dev
),
fep
->
phy_dev
->
irq
);
...
...
@@ -786,8 +924,8 @@ static int fec_enet_mii_probe(struct net_device *dev)
static
int
fec_enet_mii_init
(
struct
platform_device
*
pdev
)
{
static
struct
mii_bus
*
fec0_mii_bus
;
struct
net_device
*
dev
=
platform_get_drvdata
(
pdev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
net_device
*
n
dev
=
platform_get_drvdata
(
pdev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
const
struct
platform_device_id
*
id_entry
=
platform_get_device_id
(
fep
->
pdev
);
int
err
=
-
ENXIO
,
i
;
...
...
@@ -845,7 +983,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
for
(
i
=
0
;
i
<
PHY_MAX_ADDR
;
i
++
)
fep
->
mii_bus
->
irq
[
i
]
=
PHY_POLL
;
platform_set_drvdata
(
dev
,
fep
->
mii_bus
);
platform_set_drvdata
(
n
dev
,
fep
->
mii_bus
);
if
(
mdiobus_register
(
fep
->
mii_bus
))
goto
err_out_free_mdio_irq
;
...
...
@@ -873,10 +1011,10 @@ static void fec_enet_mii_remove(struct fec_enet_private *fep)
mdiobus_free
(
fep
->
mii_bus
);
}
static
int
fec_enet_get_settings
(
struct
net_device
*
dev
,
static
int
fec_enet_get_settings
(
struct
net_device
*
n
dev
,
struct
ethtool_cmd
*
cmd
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
struct
phy_device
*
phydev
=
fep
->
phy_dev
;
if
(
!
phydev
)
...
...
@@ -885,10 +1023,10 @@ static int fec_enet_get_settings(struct net_device *dev,
return
phy_ethtool_gset
(
phydev
,
cmd
);
}
static
int
fec_enet_set_settings
(
struct
net_device
*
dev
,
static
int
fec_enet_set_settings
(
struct
net_device
*
n
dev
,
struct
ethtool_cmd
*
cmd
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
struct
phy_device
*
phydev
=
fep
->
phy_dev
;
if
(
!
phydev
)
...
...
@@ -897,14 +1035,14 @@ static int fec_enet_set_settings(struct net_device *dev,
return
phy_ethtool_sset
(
phydev
,
cmd
);
}
static
void
fec_enet_get_drvinfo
(
struct
net_device
*
dev
,
static
void
fec_enet_get_drvinfo
(
struct
net_device
*
n
dev
,
struct
ethtool_drvinfo
*
info
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
strcpy
(
info
->
driver
,
fep
->
pdev
->
dev
.
driver
->
name
);
strcpy
(
info
->
version
,
"Revision: 1.0"
);
strcpy
(
info
->
bus_info
,
dev_name
(
&
dev
->
dev
));
strcpy
(
info
->
bus_info
,
dev_name
(
&
n
dev
->
dev
));
}
static
struct
ethtool_ops
fec_enet_ethtool_ops
=
{
...
...
@@ -914,12 +1052,12 @@ static struct ethtool_ops fec_enet_ethtool_ops = {
.
get_link
=
ethtool_op_get_link
,
};
static
int
fec_enet_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
static
int
fec_enet_ioctl
(
struct
net_device
*
n
dev
,
struct
ifreq
*
rq
,
int
cmd
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
struct
phy_device
*
phydev
=
fep
->
phy_dev
;
if
(
!
netif_running
(
dev
))
if
(
!
netif_running
(
n
dev
))
return
-
EINVAL
;
if
(
!
phydev
)
...
...
@@ -928,9 +1066,9 @@ static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return
phy_mii_ioctl
(
phydev
,
rq
,
cmd
);
}
static
void
fec_enet_free_buffers
(
struct
net_device
*
dev
)
static
void
fec_enet_free_buffers
(
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
int
i
;
struct
sk_buff
*
skb
;
struct
bufdesc
*
bdp
;
...
...
@@ -940,7 +1078,7 @@ static void fec_enet_free_buffers(struct net_device *dev)
skb
=
fep
->
rx_skbuff
[
i
];
if
(
bdp
->
cbd_bufaddr
)
dma_unmap_single
(
&
dev
->
dev
,
bdp
->
cbd_bufaddr
,
dma_unmap_single
(
&
fep
->
p
dev
->
dev
,
bdp
->
cbd_bufaddr
,
FEC_ENET_RX_FRSIZE
,
DMA_FROM_DEVICE
);
if
(
skb
)
dev_kfree_skb
(
skb
);
...
...
@@ -952,9 +1090,9 @@ static void fec_enet_free_buffers(struct net_device *dev)
kfree
(
fep
->
tx_bounce
[
i
]);
}
static
int
fec_enet_alloc_buffers
(
struct
net_device
*
dev
)
static
int
fec_enet_alloc_buffers
(
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
int
i
;
struct
sk_buff
*
skb
;
struct
bufdesc
*
bdp
;
...
...
@@ -963,12 +1101,12 @@ static int fec_enet_alloc_buffers(struct net_device *dev)
for
(
i
=
0
;
i
<
RX_RING_SIZE
;
i
++
)
{
skb
=
dev_alloc_skb
(
FEC_ENET_RX_FRSIZE
);
if
(
!
skb
)
{
fec_enet_free_buffers
(
dev
);
fec_enet_free_buffers
(
n
dev
);
return
-
ENOMEM
;
}
fep
->
rx_skbuff
[
i
]
=
skb
;
bdp
->
cbd_bufaddr
=
dma_map_single
(
&
dev
->
dev
,
skb
->
data
,
bdp
->
cbd_bufaddr
=
dma_map_single
(
&
fep
->
p
dev
->
dev
,
skb
->
data
,
FEC_ENET_RX_FRSIZE
,
DMA_FROM_DEVICE
);
bdp
->
cbd_sc
=
BD_ENET_RX_EMPTY
;
bdp
++
;
...
...
@@ -995,45 +1133,47 @@ static int fec_enet_alloc_buffers(struct net_device *dev)
}
static
int
fec_enet_open
(
struct
net_device
*
dev
)
fec_enet_open
(
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
int
ret
;
/* I should reset the ring buffers here, but I don't yet know
* a simple way to do that.
*/
ret
=
fec_enet_alloc_buffers
(
dev
);
ret
=
fec_enet_alloc_buffers
(
n
dev
);
if
(
ret
)
return
ret
;
/* Probe and connect to PHY when open the interface */
ret
=
fec_enet_mii_probe
(
dev
);
ret
=
fec_enet_mii_probe
(
n
dev
);
if
(
ret
)
{
fec_enet_free_buffers
(
dev
);
fec_enet_free_buffers
(
n
dev
);
return
ret
;
}
phy_start
(
fep
->
phy_dev
);
netif_start_queue
(
dev
);
netif_start_queue
(
n
dev
);
fep
->
opened
=
1
;
return
0
;
}
static
int
fec_enet_close
(
struct
net_device
*
dev
)
fec_enet_close
(
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
/* Don't know what to do yet. */
fep
->
opened
=
0
;
netif_stop_queue
(
dev
);
fec_stop
(
dev
);
netif_stop_queue
(
n
dev
);
fec_stop
(
n
dev
);
if
(
fep
->
phy_dev
)
if
(
fep
->
phy_dev
)
{
phy_stop
(
fep
->
phy_dev
);
phy_disconnect
(
fep
->
phy_dev
);
}
fec_enet_free_buffers
(
dev
);
fec_enet_free_buffers
(
n
dev
);
return
0
;
}
...
...
@@ -1051,14 +1191,14 @@ fec_enet_close(struct net_device *dev)
#define HASH_BITS 6
/* #bits in hash */
#define CRC32_POLY 0xEDB88320
static
void
set_multicast_list
(
struct
net_device
*
dev
)
static
void
set_multicast_list
(
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
struct
netdev_hw_addr
*
ha
;
unsigned
int
i
,
bit
,
data
,
crc
,
tmp
;
unsigned
char
hash
;
if
(
dev
->
flags
&
IFF_PROMISC
)
{
if
(
n
dev
->
flags
&
IFF_PROMISC
)
{
tmp
=
readl
(
fep
->
hwp
+
FEC_R_CNTRL
);
tmp
|=
0x8
;
writel
(
tmp
,
fep
->
hwp
+
FEC_R_CNTRL
);
...
...
@@ -1069,7 +1209,7 @@ static void set_multicast_list(struct net_device *dev)
tmp
&=
~
0x8
;
writel
(
tmp
,
fep
->
hwp
+
FEC_R_CNTRL
);
if
(
dev
->
flags
&
IFF_ALLMULTI
)
{
if
(
n
dev
->
flags
&
IFF_ALLMULTI
)
{
/* Catch all multicast addresses, so set the
* filter to all 1's
*/
...
...
@@ -1084,7 +1224,7 @@ static void set_multicast_list(struct net_device *dev)
writel
(
0
,
fep
->
hwp
+
FEC_GRP_HASH_TABLE_HIGH
);
writel
(
0
,
fep
->
hwp
+
FEC_GRP_HASH_TABLE_LOW
);
netdev_for_each_mc_addr
(
ha
,
dev
)
{
netdev_for_each_mc_addr
(
ha
,
n
dev
)
{
/* Only support group multicast for now */
if
(
!
(
ha
->
addr
[
0
]
&
1
))
continue
;
...
...
@@ -1092,7 +1232,7 @@ static void set_multicast_list(struct net_device *dev)
/* calculate crc32 value of mac address */
crc
=
0xffffffff
;
for
(
i
=
0
;
i
<
dev
->
addr_len
;
i
++
)
{
for
(
i
=
0
;
i
<
n
dev
->
addr_len
;
i
++
)
{
data
=
ha
->
addr
[
i
];
for
(
bit
=
0
;
bit
<
8
;
bit
++
,
data
>>=
1
)
{
crc
=
(
crc
>>
1
)
^
...
...
@@ -1119,20 +1259,20 @@ static void set_multicast_list(struct net_device *dev)
/* Set a MAC change in hardware. */
static
int
fec_set_mac_address
(
struct
net_device
*
dev
,
void
*
p
)
fec_set_mac_address
(
struct
net_device
*
n
dev
,
void
*
p
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
struct
sockaddr
*
addr
=
p
;
if
(
!
is_valid_ether_addr
(
addr
->
sa_data
))
return
-
EADDRNOTAVAIL
;
memcpy
(
dev
->
dev_addr
,
addr
->
sa_data
,
dev
->
addr_len
);
memcpy
(
ndev
->
dev_addr
,
addr
->
sa_data
,
n
dev
->
addr_len
);
writel
(
dev
->
dev_addr
[
3
]
|
(
dev
->
dev_addr
[
2
]
<<
8
)
|
(
dev
->
dev_addr
[
1
]
<<
16
)
|
(
dev
->
dev_addr
[
0
]
<<
24
),
writel
(
ndev
->
dev_addr
[
3
]
|
(
n
dev
->
dev_addr
[
2
]
<<
8
)
|
(
ndev
->
dev_addr
[
1
]
<<
16
)
|
(
n
dev
->
dev_addr
[
0
]
<<
24
),
fep
->
hwp
+
FEC_ADDR_LOW
);
writel
((
dev
->
dev_addr
[
5
]
<<
16
)
|
(
dev
->
dev_addr
[
4
]
<<
24
),
writel
((
ndev
->
dev_addr
[
5
]
<<
16
)
|
(
n
dev
->
dev_addr
[
4
]
<<
24
),
fep
->
hwp
+
FEC_ADDR_HIGH
);
return
0
;
}
...
...
@@ -1146,16 +1286,16 @@ static const struct net_device_ops fec_netdev_ops = {
.
ndo_validate_addr
=
eth_validate_addr
,
.
ndo_tx_timeout
=
fec_timeout
,
.
ndo_set_mac_address
=
fec_set_mac_address
,
.
ndo_do_ioctl
=
fec_enet_ioctl
,
.
ndo_do_ioctl
=
fec_enet_ioctl
,
};
/*
* XXX: We need to clean up on failure exits here.
*
*/
static
int
fec_enet_init
(
struct
net_device
*
dev
)
static
int
fec_enet_init
(
struct
net_device
*
n
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
n
dev
);
struct
bufdesc
*
cbd_base
;
struct
bufdesc
*
bdp
;
int
i
;
...
...
@@ -1170,20 +1310,19 @@ static int fec_enet_init(struct net_device *dev)
spin_lock_init
(
&
fep
->
hw_lock
);
fep
->
hwp
=
(
void
__iomem
*
)
dev
->
base_addr
;
fep
->
netdev
=
dev
;
fep
->
netdev
=
ndev
;
/* Get the Ethernet address */
fec_get_mac
(
dev
);
fec_get_mac
(
n
dev
);
/* Set receive and transmit descriptor base. */
fep
->
rx_bd_base
=
cbd_base
;
fep
->
tx_bd_base
=
cbd_base
+
RX_RING_SIZE
;
/* The FEC Ethernet specific entries in the device structure */
dev
->
watchdog_timeo
=
TX_TIMEOUT
;
dev
->
netdev_ops
=
&
fec_netdev_ops
;
dev
->
ethtool_ops
=
&
fec_enet_ethtool_ops
;
n
dev
->
watchdog_timeo
=
TX_TIMEOUT
;
n
dev
->
netdev_ops
=
&
fec_netdev_ops
;
n
dev
->
ethtool_ops
=
&
fec_enet_ethtool_ops
;
/* Initialize the receive buffer descriptors. */
bdp
=
fep
->
rx_bd_base
;
...
...
@@ -1212,152 +1351,11 @@ static int fec_enet_init(struct net_device *dev)
bdp
--
;
bdp
->
cbd_sc
|=
BD_SC_WRAP
;
fec_restart
(
dev
,
0
);
fec_restart
(
n
dev
,
0
);
return
0
;
}
/* This function is called to start or restart the FEC during a link
* change. This only happens when switching between half and full
* duplex.
*/
static
void
fec_restart
(
struct
net_device
*
dev
,
int
duplex
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
const
struct
platform_device_id
*
id_entry
=
platform_get_device_id
(
fep
->
pdev
);
int
i
;
u32
val
,
temp_mac
[
2
];
/* Whack a reset. We should wait for this. */
writel
(
1
,
fep
->
hwp
+
FEC_ECNTRL
);
udelay
(
10
);
/*
* enet-mac reset will reset mac address registers too,
* so need to reconfigure it.
*/
if
(
id_entry
->
driver_data
&
FEC_QUIRK_ENET_MAC
)
{
memcpy
(
&
temp_mac
,
dev
->
dev_addr
,
ETH_ALEN
);
writel
(
cpu_to_be32
(
temp_mac
[
0
]),
fep
->
hwp
+
FEC_ADDR_LOW
);
writel
(
cpu_to_be32
(
temp_mac
[
1
]),
fep
->
hwp
+
FEC_ADDR_HIGH
);
}
/* Clear any outstanding interrupt. */
writel
(
0xffc00000
,
fep
->
hwp
+
FEC_IEVENT
);
/* Reset all multicast. */
writel
(
0
,
fep
->
hwp
+
FEC_GRP_HASH_TABLE_HIGH
);
writel
(
0
,
fep
->
hwp
+
FEC_GRP_HASH_TABLE_LOW
);
#ifndef CONFIG_M5272
writel
(
0
,
fep
->
hwp
+
FEC_HASH_TABLE_HIGH
);
writel
(
0
,
fep
->
hwp
+
FEC_HASH_TABLE_LOW
);
#endif
/* Set maximum receive buffer size. */
writel
(
PKT_MAXBLR_SIZE
,
fep
->
hwp
+
FEC_R_BUFF_SIZE
);
/* Set receive and transmit descriptor base. */
writel
(
fep
->
bd_dma
,
fep
->
hwp
+
FEC_R_DES_START
);
writel
((
unsigned
long
)
fep
->
bd_dma
+
sizeof
(
struct
bufdesc
)
*
RX_RING_SIZE
,
fep
->
hwp
+
FEC_X_DES_START
);
fep
->
dirty_tx
=
fep
->
cur_tx
=
fep
->
tx_bd_base
;
fep
->
cur_rx
=
fep
->
rx_bd_base
;
/* Reset SKB transmit buffers. */
fep
->
skb_cur
=
fep
->
skb_dirty
=
0
;
for
(
i
=
0
;
i
<=
TX_RING_MOD_MASK
;
i
++
)
{
if
(
fep
->
tx_skbuff
[
i
])
{
dev_kfree_skb_any
(
fep
->
tx_skbuff
[
i
]);
fep
->
tx_skbuff
[
i
]
=
NULL
;
}
}
/* Enable MII mode */
if
(
duplex
)
{
/* MII enable / FD enable */
writel
(
OPT_FRAME_SIZE
|
0x04
,
fep
->
hwp
+
FEC_R_CNTRL
);
writel
(
0x04
,
fep
->
hwp
+
FEC_X_CNTRL
);
}
else
{
/* MII enable / No Rcv on Xmit */
writel
(
OPT_FRAME_SIZE
|
0x06
,
fep
->
hwp
+
FEC_R_CNTRL
);
writel
(
0x0
,
fep
->
hwp
+
FEC_X_CNTRL
);
}
fep
->
full_duplex
=
duplex
;
/* Set MII speed */
writel
(
fep
->
phy_speed
,
fep
->
hwp
+
FEC_MII_SPEED
);
/*
* The phy interface and speed need to get configured
* differently on enet-mac.
*/
if
(
id_entry
->
driver_data
&
FEC_QUIRK_ENET_MAC
)
{
val
=
readl
(
fep
->
hwp
+
FEC_R_CNTRL
);
/* MII or RMII */
if
(
fep
->
phy_interface
==
PHY_INTERFACE_MODE_RMII
)
val
|=
(
1
<<
8
);
else
val
&=
~
(
1
<<
8
);
/* 10M or 100M */
if
(
fep
->
phy_dev
&&
fep
->
phy_dev
->
speed
==
SPEED_100
)
val
&=
~
(
1
<<
9
);
else
val
|=
(
1
<<
9
);
writel
(
val
,
fep
->
hwp
+
FEC_R_CNTRL
);
}
else
{
#ifdef FEC_MIIGSK_ENR
if
(
fep
->
phy_interface
==
PHY_INTERFACE_MODE_RMII
)
{
/* disable the gasket and wait */
writel
(
0
,
fep
->
hwp
+
FEC_MIIGSK_ENR
);
while
(
readl
(
fep
->
hwp
+
FEC_MIIGSK_ENR
)
&
4
)
udelay
(
1
);
/*
* configure the gasket:
* RMII, 50 MHz, no loopback, no echo
*/
writel
(
1
,
fep
->
hwp
+
FEC_MIIGSK_CFGR
);
/* re-enable the gasket */
writel
(
2
,
fep
->
hwp
+
FEC_MIIGSK_ENR
);
}
#endif
}
/* And last, enable the transmit and receive processing */
writel
(
2
,
fep
->
hwp
+
FEC_ECNTRL
);
writel
(
0
,
fep
->
hwp
+
FEC_R_DES_ACTIVE
);
/* Enable interrupts we wish to service */
writel
(
FEC_DEFAULT_IMASK
,
fep
->
hwp
+
FEC_IMASK
);
}
static
void
fec_stop
(
struct
net_device
*
dev
)
{
struct
fec_enet_private
*
fep
=
netdev_priv
(
dev
);
/* We cannot expect a graceful transmit stop without link !!! */
if
(
fep
->
link
)
{
writel
(
1
,
fep
->
hwp
+
FEC_X_CNTRL
);
/* Graceful transmit stop */
udelay
(
10
);
if
(
!
(
readl
(
fep
->
hwp
+
FEC_IEVENT
)
&
FEC_ENET_GRA
))
printk
(
"fec_stop : Graceful transmit stop did not complete !
\n
"
);
}
/* Whack a reset. We should wait for this. */
writel
(
1
,
fep
->
hwp
+
FEC_ECNTRL
);
udelay
(
10
);
writel
(
fep
->
phy_speed
,
fep
->
hwp
+
FEC_MII_SPEED
);
writel
(
FEC_DEFAULT_IMASK
,
fep
->
hwp
+
FEC_IMASK
);
}
static
int
__devinit
fec_probe
(
struct
platform_device
*
pdev
)
{
...
...
@@ -1377,19 +1375,20 @@ fec_probe(struct platform_device *pdev)
/* Init network device */
ndev
=
alloc_etherdev
(
sizeof
(
struct
fec_enet_private
));
if
(
!
ndev
)
return
-
ENOMEM
;
if
(
!
ndev
)
{
ret
=
-
ENOMEM
;
goto
failed_alloc_etherdev
;
}
SET_NETDEV_DEV
(
ndev
,
&
pdev
->
dev
);
/* setup board info structure */
fep
=
netdev_priv
(
ndev
);
memset
(
fep
,
0
,
sizeof
(
*
fep
));
ndev
->
base_addr
=
(
unsigned
long
)
ioremap
(
r
->
start
,
resource_size
(
r
));
fep
->
hwp
=
ioremap
(
r
->
start
,
resource_size
(
r
));
fep
->
pdev
=
pdev
;
if
(
!
ndev
->
base_addr
)
{
if
(
!
fep
->
hwp
)
{
ret
=
-
ENOMEM
;
goto
failed_ioremap
;
}
...
...
@@ -1407,10 +1406,9 @@ fec_probe(struct platform_device *pdev)
break
;
ret
=
request_irq
(
irq
,
fec_enet_interrupt
,
IRQF_DISABLED
,
pdev
->
name
,
ndev
);
if
(
ret
)
{
while
(
i
>=
0
)
{
while
(
--
i
>=
0
)
{
irq
=
platform_get_irq
(
pdev
,
i
);
free_irq
(
irq
,
ndev
);
i
--
;
}
goto
failed_irq
;
}
...
...
@@ -1453,9 +1451,11 @@ fec_probe(struct platform_device *pdev)
free_irq
(
irq
,
ndev
);
}
failed_irq:
iounmap
(
(
void
__iomem
*
)
ndev
->
base_addr
);
iounmap
(
fep
->
hwp
);
failed_ioremap:
free_netdev
(
ndev
);
failed_alloc_etherdev:
release_mem_region
(
r
->
start
,
resource_size
(
r
));
return
ret
;
}
...
...
@@ -1465,16 +1465,22 @@ fec_drv_remove(struct platform_device *pdev)
{
struct
net_device
*
ndev
=
platform_get_drvdata
(
pdev
);
struct
fec_enet_private
*
fep
=
netdev_priv
(
ndev
);
platform_set_drvdata
(
pdev
,
NULL
);
struct
resource
*
r
;
fec_stop
(
ndev
);
fec_enet_mii_remove
(
fep
);
clk_disable
(
fep
->
clk
);
clk_put
(
fep
->
clk
);
iounmap
(
(
void
__iomem
*
)
ndev
->
base_addr
);
iounmap
(
fep
->
hwp
);
unregister_netdev
(
ndev
);
free_netdev
(
ndev
);
r
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
BUG_ON
(
!
r
);
release_mem_region
(
r
->
start
,
resource_size
(
r
));
platform_set_drvdata
(
pdev
,
NULL
);
return
0
;
}
...
...
@@ -1483,16 +1489,14 @@ static int
fec_suspend
(
struct
device
*
dev
)
{
struct
net_device
*
ndev
=
dev_get_drvdata
(
dev
);
struct
fec_enet_private
*
fep
;
struct
fec_enet_private
*
fep
=
netdev_priv
(
ndev
)
;
if
(
ndev
)
{
fep
=
netdev_priv
(
ndev
);
if
(
netif_running
(
ndev
))
{
fec_stop
(
ndev
);
netif_device_detach
(
ndev
);
}
clk_disable
(
fep
->
clk
);
if
(
netif_running
(
ndev
))
{
fec_stop
(
ndev
);
netif_device_detach
(
ndev
);
}
clk_disable
(
fep
->
clk
);
return
0
;
}
...
...
@@ -1500,16 +1504,14 @@ static int
fec_resume
(
struct
device
*
dev
)
{
struct
net_device
*
ndev
=
dev_get_drvdata
(
dev
);
struct
fec_enet_private
*
fep
;
struct
fec_enet_private
*
fep
=
netdev_priv
(
ndev
)
;
if
(
ndev
)
{
fep
=
netdev_priv
(
ndev
);
clk_enable
(
fep
->
clk
);
if
(
netif_running
(
ndev
))
{
fec_restart
(
ndev
,
fep
->
full_duplex
);
netif_device_attach
(
ndev
);
}
clk_enable
(
fep
->
clk
);
if
(
netif_running
(
ndev
))
{
fec_restart
(
ndev
,
fep
->
full_duplex
);
netif_device_attach
(
ndev
);
}
return
0
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment