Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
29e1846a
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
29e1846a
编写于
2月 15, 2011
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'fec' of
git://git.pengutronix.de/git/ukl/linux-2.6
上级
f39925db
cd1f402c
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
328 addition
and
325 deletion
+328
-325
drivers/net/Kconfig
drivers/net/Kconfig
+2
-1
drivers/net/fec.c
drivers/net/fec.c
+326
-324
未找到文件。
drivers/net/Kconfig
浏览文件 @
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
浏览文件 @
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
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录