提交 7dd6a2aa 编写于 作者: G Greg Ungerer 提交者: Linus Torvalds

[PATCH] m68knommu: ColdFire FEC eth driver improvements

A few improvements to the Freescale/ColdFire FEC driver:

. some formatting cleanups
. add support for the FEC device in the ColdFire 523x processor family
. add support for MAC address setting on MOD5272 and M5272C3 boards
. don't re-read the PHY status register many times
. ack status interrupt before reading status register
. move printing init message to after full init (so that the
  ethX name is filled out for printing)

Some parts of this patch submitted by Philippe De Muyter <phdm@macqel.be>
Signed-off-by: NGreg Ungerer <gerg@uclinux.com>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 2af6921f
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* describes connections using the internal parallel port I/O, which * describes connections using the internal parallel port I/O, which
* is basically all of Port D. * is basically all of Port D.
* *
* Right now, I am very watseful with the buffers. I allocate memory * Right now, I am very wasteful with the buffers. I allocate memory
* pages and then divide them into 2K frame buffers. This way I know I * pages and then divide them into 2K frame buffers. This way I know I
* have buffers large enough to hold one frame within one buffer descriptor. * have buffers large enough to hold one frame within one buffer descriptor.
* Once I get this working, I will use 64 or 128 byte CPM buffers, which * Once I get this working, I will use 64 or 128 byte CPM buffers, which
...@@ -19,7 +19,10 @@ ...@@ -19,7 +19,10 @@
* Copyright (c) 2000 Ericsson Radio Systems AB. * Copyright (c) 2000 Ericsson Radio Systems AB.
* *
* Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282. * Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282.
* Copyrught (c) 2001-2004 Greg Ungerer (gerg@snapgear.com) * Copyright (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
*
* Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
* Copyright (c) 2004-2005 Macq Electronique SA.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -46,7 +49,8 @@ ...@@ -46,7 +49,8 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#if defined(CONFIG_M527x) || defined(CONFIG_M5272) || defined(CONFIG_M528x) #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
defined(CONFIG_M5272) || defined(CONFIG_M528x)
#include <asm/coldfire.h> #include <asm/coldfire.h>
#include <asm/mcfsim.h> #include <asm/mcfsim.h>
#include "fec.h" #include "fec.h"
...@@ -71,7 +75,7 @@ static unsigned int fec_hw[] = { ...@@ -71,7 +75,7 @@ static unsigned int fec_hw[] = {
#elif defined(CONFIG_M527x) #elif defined(CONFIG_M527x)
(MCF_MBAR + 0x1000), (MCF_MBAR + 0x1000),
(MCF_MBAR + 0x1800), (MCF_MBAR + 0x1800),
#elif defined(CONFIG_M528x) #elif defined(CONFIG_M523x) || defined(CONFIG_M528x)
(MCF_MBAR + 0x1000), (MCF_MBAR + 0x1000),
#else #else
&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
...@@ -94,12 +98,14 @@ static unsigned char fec_mac_default[] = { ...@@ -94,12 +98,14 @@ static unsigned char fec_mac_default[] = {
#define FEC_FLASHMAC 0xffe04000 #define FEC_FLASHMAC 0xffe04000
#elif defined(CONFIG_CANCam) #elif defined(CONFIG_CANCam)
#define FEC_FLASHMAC 0xf0020000 #define FEC_FLASHMAC 0xf0020000
#elif defined (CONFIG_M5272C3)
#define FEC_FLASHMAC (0xffe04000 + 4)
#elif defined(CONFIG_MOD5272)
#define FEC_FLASHMAC 0xffc0406b
#else #else
#define FEC_FLASHMAC 0 #define FEC_FLASHMAC 0
#endif #endif
unsigned char *fec_flashmac = (unsigned char *) FEC_FLASHMAC;
/* Forward declarations of some structures to support different PHYs /* Forward declarations of some structures to support different PHYs
*/ */
...@@ -158,7 +164,7 @@ typedef struct { ...@@ -158,7 +164,7 @@ typedef struct {
* size bits. Other FEC hardware does not, so we need to take that into * size bits. Other FEC hardware does not, so we need to take that into
* account when setting it. * account when setting it.
*/ */
#if defined(CONFIG_M527x) || defined(CONFIG_M528x) #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
#else #else
#define OPT_FRAME_SIZE 0 #define OPT_FRAME_SIZE 0
...@@ -196,7 +202,7 @@ struct fec_enet_private { ...@@ -196,7 +202,7 @@ struct fec_enet_private {
uint phy_id_done; uint phy_id_done;
uint phy_status; uint phy_status;
uint phy_speed; uint phy_speed;
phy_info_t *phy; phy_info_t const *phy;
struct work_struct phy_task; struct work_struct phy_task;
uint sequence_done; uint sequence_done;
...@@ -209,7 +215,6 @@ struct fec_enet_private { ...@@ -209,7 +215,6 @@ struct fec_enet_private {
int link; int link;
int old_link; int old_link;
int full_duplex; int full_duplex;
unsigned char mac_addr[ETH_ALEN];
}; };
static int fec_enet_open(struct net_device *dev); static int fec_enet_open(struct net_device *dev);
...@@ -237,10 +242,10 @@ typedef struct mii_list { ...@@ -237,10 +242,10 @@ typedef struct mii_list {
} mii_list_t; } mii_list_t;
#define NMII 20 #define NMII 20
mii_list_t mii_cmds[NMII]; static mii_list_t mii_cmds[NMII];
mii_list_t *mii_free; static mii_list_t *mii_free;
mii_list_t *mii_head; static mii_list_t *mii_head;
mii_list_t *mii_tail; static mii_list_t *mii_tail;
static int mii_queue(struct net_device *dev, int request, static int mii_queue(struct net_device *dev, int request,
void (*func)(uint, struct net_device *)); void (*func)(uint, struct net_device *));
...@@ -425,7 +430,7 @@ fec_timeout(struct net_device *dev) ...@@ -425,7 +430,7 @@ fec_timeout(struct net_device *dev)
} }
} }
#endif #endif
fec_restart(dev, 0); fec_restart(dev, fep->full_duplex);
netif_wake_queue(dev); netif_wake_queue(dev);
} }
...@@ -757,45 +762,52 @@ static void mii_parse_sr(uint mii_reg, struct net_device *dev) ...@@ -757,45 +762,52 @@ static void mii_parse_sr(uint mii_reg, struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status); volatile uint *s = &(fep->phy_status);
uint status;
*s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC); status = *s & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
if (mii_reg & 0x0004) if (mii_reg & 0x0004)
*s |= PHY_STAT_LINK; status |= PHY_STAT_LINK;
if (mii_reg & 0x0010) if (mii_reg & 0x0010)
*s |= PHY_STAT_FAULT; status |= PHY_STAT_FAULT;
if (mii_reg & 0x0020) if (mii_reg & 0x0020)
*s |= PHY_STAT_ANC; status |= PHY_STAT_ANC;
*s = status;
} }
static void mii_parse_cr(uint mii_reg, struct net_device *dev) static void mii_parse_cr(uint mii_reg, struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status); volatile uint *s = &(fep->phy_status);
uint status;
*s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP); status = *s & ~(PHY_CONF_ANE | PHY_CONF_LOOP);
if (mii_reg & 0x1000) if (mii_reg & 0x1000)
*s |= PHY_CONF_ANE; status |= PHY_CONF_ANE;
if (mii_reg & 0x4000) if (mii_reg & 0x4000)
*s |= PHY_CONF_LOOP; status |= PHY_CONF_LOOP;
*s = status;
} }
static void mii_parse_anar(uint mii_reg, struct net_device *dev) static void mii_parse_anar(uint mii_reg, struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status); volatile uint *s = &(fep->phy_status);
uint status;
*s &= ~(PHY_CONF_SPMASK); status = *s & ~(PHY_CONF_SPMASK);
if (mii_reg & 0x0020) if (mii_reg & 0x0020)
*s |= PHY_CONF_10HDX; status |= PHY_CONF_10HDX;
if (mii_reg & 0x0040) if (mii_reg & 0x0040)
*s |= PHY_CONF_10FDX; status |= PHY_CONF_10FDX;
if (mii_reg & 0x0080) if (mii_reg & 0x0080)
*s |= PHY_CONF_100HDX; status |= PHY_CONF_100HDX;
if (mii_reg & 0x00100) if (mii_reg & 0x00100)
*s |= PHY_CONF_100FDX; status |= PHY_CONF_100FDX;
*s = status;
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
...@@ -811,37 +823,34 @@ static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev) ...@@ -811,37 +823,34 @@ static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status); volatile uint *s = &(fep->phy_status);
uint status;
*s &= ~(PHY_STAT_SPMASK); status = *s & ~(PHY_STAT_SPMASK);
if (mii_reg & 0x0800) { if (mii_reg & 0x0800) {
if (mii_reg & 0x1000) if (mii_reg & 0x1000)
*s |= PHY_STAT_100FDX; status |= PHY_STAT_100FDX;
else else
*s |= PHY_STAT_100HDX; status |= PHY_STAT_100HDX;
} else { } else {
if (mii_reg & 0x1000) if (mii_reg & 0x1000)
*s |= PHY_STAT_10FDX; status |= PHY_STAT_10FDX;
else else
*s |= PHY_STAT_10HDX; status |= PHY_STAT_10HDX;
} }
*s = status;
} }
static phy_info_t phy_info_lxt970 = { static phy_cmd_t const phy_cmd_lxt970_config[] = {
0x07810000,
"LXT970",
(const phy_cmd_t []) { /* config */
{ mk_mii_read(MII_REG_CR), mii_parse_cr }, { mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar }, { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* startup - enable interrupts */ static phy_cmd_t const phy_cmd_lxt970_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_LXT970_IER, 0x0002), NULL }, { mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* ack_int */ static phy_cmd_t const phy_cmd_lxt970_ack_int[] = {
/* read SR and ISR to acknowledge */ /* read SR and ISR to acknowledge */
{ mk_mii_read(MII_REG_SR), mii_parse_sr }, { mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_read(MII_LXT970_ISR), NULL }, { mk_mii_read(MII_LXT970_ISR), NULL },
...@@ -849,11 +858,18 @@ static phy_info_t phy_info_lxt970 = { ...@@ -849,11 +858,18 @@ static phy_info_t phy_info_lxt970 = {
/* find out the current status */ /* find out the current status */
{ mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr }, { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* shutdown - disable interrupts */ static phy_cmd_t const phy_cmd_lxt970_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_LXT970_IER, 0x0000), NULL }, { mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
{ mk_mii_end, } { mk_mii_end, }
}, };
static phy_info_t const phy_info_lxt970 = {
.id = 0x07810000,
.name = "LXT970",
.config = phy_cmd_lxt970_config,
.startup = phy_cmd_lxt970_startup,
.ack_int = phy_cmd_lxt970_ack_int,
.shutdown = phy_cmd_lxt970_shutdown
}; };
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
...@@ -878,45 +894,44 @@ static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev) ...@@ -878,45 +894,44 @@ static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status); volatile uint *s = &(fep->phy_status);
uint status;
*s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC); status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
if (mii_reg & 0x0400) { if (mii_reg & 0x0400) {
fep->link = 1; fep->link = 1;
*s |= PHY_STAT_LINK; status |= PHY_STAT_LINK;
} else { } else {
fep->link = 0; fep->link = 0;
} }
if (mii_reg & 0x0080) if (mii_reg & 0x0080)
*s |= PHY_STAT_ANC; status |= PHY_STAT_ANC;
if (mii_reg & 0x4000) { if (mii_reg & 0x4000) {
if (mii_reg & 0x0200) if (mii_reg & 0x0200)
*s |= PHY_STAT_100FDX; status |= PHY_STAT_100FDX;
else else
*s |= PHY_STAT_100HDX; status |= PHY_STAT_100HDX;
} else { } else {
if (mii_reg & 0x0200) if (mii_reg & 0x0200)
*s |= PHY_STAT_10FDX; status |= PHY_STAT_10FDX;
else else
*s |= PHY_STAT_10HDX; status |= PHY_STAT_10HDX;
} }
if (mii_reg & 0x0008) if (mii_reg & 0x0008)
*s |= PHY_STAT_FAULT; status |= PHY_STAT_FAULT;
}
static phy_info_t phy_info_lxt971 = { *s = status;
0x0001378e, }
"LXT971",
(const phy_cmd_t []) { /* config */ static phy_cmd_t const phy_cmd_lxt971_config[] = {
/* limit to 10MBit because my protorype board /* limit to 10MBit because my prototype board
* doesn't work with 100. */ * doesn't work with 100. */
{ mk_mii_read(MII_REG_CR), mii_parse_cr }, { mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar }, { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 }, { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* startup - enable interrupts */ static phy_cmd_t const phy_cmd_lxt971_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_LXT971_IER, 0x00f2), NULL }, { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */ { mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */
...@@ -925,19 +940,26 @@ static phy_info_t phy_info_lxt971 = { ...@@ -925,19 +940,26 @@ static phy_info_t phy_info_lxt971 = {
* read here to get a valid value in ack_int */ * read here to get a valid value in ack_int */
{ mk_mii_read(MII_REG_SR), mii_parse_sr }, { mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* ack_int */ static phy_cmd_t const phy_cmd_lxt971_ack_int[] = {
/* acknowledge the int before reading status ! */
{ mk_mii_read(MII_LXT971_ISR), NULL },
/* find out the current status */ /* find out the current status */
{ mk_mii_read(MII_REG_SR), mii_parse_sr }, { mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 }, { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
/* we only need to read ISR to acknowledge */
{ mk_mii_read(MII_LXT971_ISR), NULL },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* shutdown - disable interrupts */ static phy_cmd_t const phy_cmd_lxt971_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_LXT971_IER, 0x0000), NULL }, { mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
{ mk_mii_end, } { mk_mii_end, }
}, };
static phy_info_t const phy_info_lxt971 = {
.id = 0x0001378e,
.name = "LXT971",
.config = phy_cmd_lxt971_config,
.startup = phy_cmd_lxt971_startup,
.ack_int = phy_cmd_lxt971_ack_int,
.shutdown = phy_cmd_lxt971_shutdown
}; };
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
...@@ -956,22 +978,21 @@ static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev) ...@@ -956,22 +978,21 @@ static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status); volatile uint *s = &(fep->phy_status);
uint status;
*s &= ~(PHY_STAT_SPMASK); status = *s & ~(PHY_STAT_SPMASK);
switch((mii_reg >> 2) & 7) { switch((mii_reg >> 2) & 7) {
case 1: *s |= PHY_STAT_10HDX; break; case 1: status |= PHY_STAT_10HDX; break;
case 2: *s |= PHY_STAT_100HDX; break; case 2: status |= PHY_STAT_100HDX; break;
case 5: *s |= PHY_STAT_10FDX; break; case 5: status |= PHY_STAT_10FDX; break;
case 6: *s |= PHY_STAT_100FDX; break; case 6: status |= PHY_STAT_100FDX; break;
}
} }
static phy_info_t phy_info_qs6612 = { *s = status;
0x00181440, }
"QS6612",
static phy_cmd_t const phy_cmd_qs6612_config[] = {
(const phy_cmd_t []) { /* config */
/* The PHY powers up isolated on the RPX, /* The PHY powers up isolated on the RPX,
* so send a command to allow operation. * so send a command to allow operation.
*/ */
...@@ -981,13 +1002,13 @@ static phy_info_t phy_info_qs6612 = { ...@@ -981,13 +1002,13 @@ static phy_info_t phy_info_qs6612 = {
{ mk_mii_read(MII_REG_CR), mii_parse_cr }, { mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar }, { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* startup - enable interrupts */ static phy_cmd_t const phy_cmd_qs6612_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_QS6612_IMR, 0x003a), NULL }, { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* ack_int */ static phy_cmd_t const phy_cmd_qs6612_ack_int[] = {
/* we need to read ISR, SR and ANER to acknowledge */ /* we need to read ISR, SR and ANER to acknowledge */
{ mk_mii_read(MII_QS6612_ISR), NULL }, { mk_mii_read(MII_QS6612_ISR), NULL },
{ mk_mii_read(MII_REG_SR), mii_parse_sr }, { mk_mii_read(MII_REG_SR), mii_parse_sr },
...@@ -996,11 +1017,18 @@ static phy_info_t phy_info_qs6612 = { ...@@ -996,11 +1017,18 @@ static phy_info_t phy_info_qs6612 = {
/* read pcr to get info */ /* read pcr to get info */
{ mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr }, { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* shutdown - disable interrupts */ static phy_cmd_t const phy_cmd_qs6612_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_QS6612_IMR, 0x0000), NULL }, { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
{ mk_mii_end, } { mk_mii_end, }
}, };
static phy_info_t const phy_info_qs6612 = {
.id = 0x00181440,
.name = "QS6612",
.config = phy_cmd_qs6612_config,
.startup = phy_cmd_qs6612_startup,
.ack_int = phy_cmd_qs6612_ack_int,
.shutdown = phy_cmd_qs6612_shutdown
}; };
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
...@@ -1020,49 +1048,54 @@ static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev) ...@@ -1020,49 +1048,54 @@ static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status); volatile uint *s = &(fep->phy_status);
uint status;
*s &= ~(PHY_STAT_SPMASK | PHY_STAT_ANC); status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
if (mii_reg & 0x0080) if (mii_reg & 0x0080)
*s |= PHY_STAT_ANC; status |= PHY_STAT_ANC;
if (mii_reg & 0x0400) if (mii_reg & 0x0400)
*s |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX); status |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
else else
*s |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX); status |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
*s = status;
} }
static phy_info_t phy_info_am79c874 = { static phy_cmd_t const phy_cmd_am79c874_config[] = {
0x00022561,
"AM79C874",
(const phy_cmd_t []) { /* config */
/* limit to 10MBit because my protorype board
* doesn't work with 100. */
{ mk_mii_read(MII_REG_CR), mii_parse_cr }, { mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar }, { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr }, { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* startup - enable interrupts */ static phy_cmd_t const phy_cmd_am79c874_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL }, { mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_read(MII_REG_SR), mii_parse_sr }, { mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* ack_int */ static phy_cmd_t const phy_cmd_am79c874_ack_int[] = {
/* find out the current status */ /* find out the current status */
{ mk_mii_read(MII_REG_SR), mii_parse_sr }, { mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr }, { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
/* we only need to read ISR to acknowledge */ /* we only need to read ISR to acknowledge */
{ mk_mii_read(MII_AM79C874_ICSR), NULL }, { mk_mii_read(MII_AM79C874_ICSR), NULL },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* shutdown - disable interrupts */ static phy_cmd_t const phy_cmd_am79c874_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL }, { mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL },
{ mk_mii_end, } { mk_mii_end, }
}, };
static phy_info_t const phy_info_am79c874 = {
.id = 0x00022561,
.name = "AM79C874",
.config = phy_cmd_am79c874_config,
.startup = phy_cmd_am79c874_startup,
.ack_int = phy_cmd_am79c874_ack_int,
.shutdown = phy_cmd_am79c874_shutdown
}; };
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* Kendin KS8721BL phy */ /* Kendin KS8721BL phy */
...@@ -1072,37 +1105,40 @@ static phy_info_t phy_info_am79c874 = { ...@@ -1072,37 +1105,40 @@ static phy_info_t phy_info_am79c874 = {
#define MII_KS8721BL_ICSR 22 #define MII_KS8721BL_ICSR 22
#define MII_KS8721BL_PHYCR 31 #define MII_KS8721BL_PHYCR 31
static phy_info_t phy_info_ks8721bl = { static phy_cmd_t const phy_cmd_ks8721bl_config[] = {
0x00022161,
"KS8721BL",
(const phy_cmd_t []) { /* config */
{ mk_mii_read(MII_REG_CR), mii_parse_cr }, { mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar }, { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* startup */ static phy_cmd_t const phy_cmd_ks8721bl_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL }, { mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_read(MII_REG_SR), mii_parse_sr }, { mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* ack_int */ static phy_cmd_t const phy_cmd_ks8721bl_ack_int[] = {
/* find out the current status */ /* find out the current status */
{ mk_mii_read(MII_REG_SR), mii_parse_sr }, { mk_mii_read(MII_REG_SR), mii_parse_sr },
/* we only need to read ISR to acknowledge */ /* we only need to read ISR to acknowledge */
{ mk_mii_read(MII_KS8721BL_ICSR), NULL }, { mk_mii_read(MII_KS8721BL_ICSR), NULL },
{ mk_mii_end, } { mk_mii_end, }
}, };
(const phy_cmd_t []) { /* shutdown */ static phy_cmd_t const phy_cmd_ks8721bl_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL }, { mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL },
{ mk_mii_end, } { mk_mii_end, }
}, };
static phy_info_t const phy_info_ks8721bl = {
.id = 0x00022161,
.name = "KS8721BL",
.config = phy_cmd_ks8721bl_config,
.startup = phy_cmd_ks8721bl_startup,
.ack_int = phy_cmd_ks8721bl_ack_int,
.shutdown = phy_cmd_ks8721bl_shutdown
}; };
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static phy_info_t *phy_info[] = { static phy_info_t const * const phy_info[] = {
&phy_info_lxt970, &phy_info_lxt970,
&phy_info_lxt971, &phy_info_lxt971,
&phy_info_qs6612, &phy_info_qs6612,
...@@ -1129,16 +1165,23 @@ mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs); ...@@ -1129,16 +1165,23 @@ mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs);
static void __inline__ fec_request_intrs(struct net_device *dev) static void __inline__ fec_request_intrs(struct net_device *dev)
{ {
volatile unsigned long *icrp; volatile unsigned long *icrp;
static const struct idesc {
char *name;
unsigned short irq;
irqreturn_t (*handler)(int, void *, struct pt_regs *);
} *idp, id[] = {
{ "fec(RX)", 86, fec_enet_interrupt },
{ "fec(TX)", 87, fec_enet_interrupt },
{ "fec(OTHER)", 88, fec_enet_interrupt },
{ "fec(MII)", 66, mii_link_interrupt },
{ NULL },
};
/* Setup interrupt handlers. */ /* Setup interrupt handlers. */
if (request_irq(86, fec_enet_interrupt, 0, "fec(RX)", dev) != 0) for (idp = id; idp->name; idp++) {
printk("FEC: Could not allocate FEC(RC) IRQ(86)!\n"); if (request_irq(idp->irq, idp->handler, 0, idp->name, dev) != 0)
if (request_irq(87, fec_enet_interrupt, 0, "fec(TX)", dev) != 0) printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, idp->irq);
printk("FEC: Could not allocate FEC(RC) IRQ(87)!\n"); }
if (request_irq(88, fec_enet_interrupt, 0, "fec(OTHER)", dev) != 0)
printk("FEC: Could not allocate FEC(OTHER) IRQ(88)!\n");
if (request_irq(66, mii_link_interrupt, 0, "fec(MII)", dev) != 0)
printk("FEC: Could not allocate MII IRQ(66)!\n");
/* Unmask interrupt at ColdFire 5272 SIM */ /* Unmask interrupt at ColdFire 5272 SIM */
icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3); icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3);
...@@ -1169,17 +1212,16 @@ static void __inline__ fec_get_mac(struct net_device *dev) ...@@ -1169,17 +1212,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
volatile fec_t *fecp; volatile fec_t *fecp;
unsigned char *iap, tmpaddr[6]; unsigned char *iap, tmpaddr[ETH_ALEN];
int i;
fecp = fep->hwp; fecp = fep->hwp;
if (fec_flashmac) { if (FEC_FLASHMAC) {
/* /*
* Get MAC address from FLASH. * Get MAC address from FLASH.
* If it is all 1's or 0's, use the default. * If it is all 1's or 0's, use the default.
*/ */
iap = fec_flashmac; iap = (unsigned char *)FEC_FLASHMAC;
if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
(iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
iap = fec_mac_default; iap = fec_mac_default;
...@@ -1192,14 +1234,11 @@ static void __inline__ fec_get_mac(struct net_device *dev) ...@@ -1192,14 +1234,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
iap = &tmpaddr[0]; iap = &tmpaddr[0];
} }
for (i=0; i<ETH_ALEN; i++) memcpy(dev->dev_addr, iap, ETH_ALEN);
dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
/* Adjust MAC if using default MAC address */ /* Adjust MAC if using default MAC address */
if (iap == fec_mac_default) { if (iap == fec_mac_default)
dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] = dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
iap[ETH_ALEN-1] + fep->index;
}
} }
static void __inline__ fec_enable_phy_intr(void) static void __inline__ fec_enable_phy_intr(void)
...@@ -1234,48 +1273,44 @@ static void __inline__ fec_uncache(unsigned long addr) ...@@ -1234,48 +1273,44 @@ static void __inline__ fec_uncache(unsigned long addr)
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
#elif defined(CONFIG_M527x) || defined(CONFIG_M528x) #elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
/* /*
* Code specific to Coldfire 5270/5271/5274/5275 and 5280/5282 setups. * Code specific to Coldfire 5230/5231/5232/5234/5235,
* the 5270/5271/5274/5275 and 5280/5282 setups.
*/ */
static void __inline__ fec_request_intrs(struct net_device *dev) static void __inline__ fec_request_intrs(struct net_device *dev)
{ {
struct fec_enet_private *fep; struct fec_enet_private *fep;
int b; int b;
static const struct idesc {
char *name;
unsigned short irq;
} *idp, id[] = {
{ "fec(TXF)", 23 },
{ "fec(TXB)", 24 },
{ "fec(TXFIFO)", 25 },
{ "fec(TXCR)", 26 },
{ "fec(RXF)", 27 },
{ "fec(RXB)", 28 },
{ "fec(MII)", 29 },
{ "fec(LC)", 30 },
{ "fec(HBERR)", 31 },
{ "fec(GRA)", 32 },
{ "fec(EBERR)", 33 },
{ "fec(BABT)", 34 },
{ "fec(BABR)", 35 },
{ NULL },
};
fep = netdev_priv(dev); fep = netdev_priv(dev);
b = (fep->index) ? 128 : 64; b = (fep->index) ? 128 : 64;
/* Setup interrupt handlers. */ /* Setup interrupt handlers. */
if (request_irq(b+23, fec_enet_interrupt, 0, "fec(TXF)", dev) != 0) for (idp = id; idp->name; idp++) {
printk("FEC: Could not allocate FEC(TXF) IRQ(%d+23)!\n", b); if (request_irq(b+idp->irq, fec_enet_interrupt, 0, idp->name, dev) != 0)
if (request_irq(b+24, fec_enet_interrupt, 0, "fec(TXB)", dev) != 0) printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq);
printk("FEC: Could not allocate FEC(TXB) IRQ(%d+24)!\n", b); }
if (request_irq(b+25, fec_enet_interrupt, 0, "fec(TXFIFO)", dev) != 0)
printk("FEC: Could not allocate FEC(TXFIFO) IRQ(%d+25)!\n", b);
if (request_irq(b+26, fec_enet_interrupt, 0, "fec(TXCR)", dev) != 0)
printk("FEC: Could not allocate FEC(TXCR) IRQ(%d+26)!\n", b);
if (request_irq(b+27, fec_enet_interrupt, 0, "fec(RXF)", dev) != 0)
printk("FEC: Could not allocate FEC(RXF) IRQ(%d+27)!\n", b);
if (request_irq(b+28, fec_enet_interrupt, 0, "fec(RXB)", dev) != 0)
printk("FEC: Could not allocate FEC(RXB) IRQ(%d+28)!\n", b);
if (request_irq(b+29, fec_enet_interrupt, 0, "fec(MII)", dev) != 0)
printk("FEC: Could not allocate FEC(MII) IRQ(%d+29)!\n", b);
if (request_irq(b+30, fec_enet_interrupt, 0, "fec(LC)", dev) != 0)
printk("FEC: Could not allocate FEC(LC) IRQ(%d+30)!\n", b);
if (request_irq(b+31, fec_enet_interrupt, 0, "fec(HBERR)", dev) != 0)
printk("FEC: Could not allocate FEC(HBERR) IRQ(%d+31)!\n", b);
if (request_irq(b+32, fec_enet_interrupt, 0, "fec(GRA)", dev) != 0)
printk("FEC: Could not allocate FEC(GRA) IRQ(%d+32)!\n", b);
if (request_irq(b+33, fec_enet_interrupt, 0, "fec(EBERR)", dev) != 0)
printk("FEC: Could not allocate FEC(EBERR) IRQ(%d+33)!\n", b);
if (request_irq(b+34, fec_enet_interrupt, 0, "fec(BABT)", dev) != 0)
printk("FEC: Could not allocate FEC(BABT) IRQ(%d+34)!\n", b);
if (request_irq(b+35, fec_enet_interrupt, 0, "fec(BABR)", dev) != 0)
printk("FEC: Could not allocate FEC(BABR) IRQ(%d+35)!\n", b);
/* Unmask interrupts at ColdFire 5280/5282 interrupt controller */ /* Unmask interrupts at ColdFire 5280/5282 interrupt controller */
{ {
...@@ -1300,11 +1335,13 @@ static void __inline__ fec_request_intrs(struct net_device *dev) ...@@ -1300,11 +1335,13 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
#if defined(CONFIG_M528x) #if defined(CONFIG_M528x)
/* Set up gpio outputs for MII lines */ /* Set up gpio outputs for MII lines */
{ {
volatile unsigned short *gpio_paspar; volatile u16 *gpio_paspar;
volatile u8 *gpio_pehlpar;
gpio_paspar = (volatile unsigned short *) (MCF_IPSBAR + gpio_paspar = (volatile u16 *) (MCF_IPSBAR + 0x100056);
0x100056); gpio_pehlpar = (volatile u16 *) (MCF_IPSBAR + 0x100058);
*gpio_paspar = 0x0f00; *gpio_paspar |= 0x0f00;
*gpio_pehlpar = 0xc0;
} }
#endif #endif
} }
...@@ -1331,17 +1368,16 @@ static void __inline__ fec_get_mac(struct net_device *dev) ...@@ -1331,17 +1368,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
volatile fec_t *fecp; volatile fec_t *fecp;
unsigned char *iap, tmpaddr[6]; unsigned char *iap, tmpaddr[ETH_ALEN];
int i;
fecp = fep->hwp; fecp = fep->hwp;
if (fec_flashmac) { if (FEC_FLASHMAC) {
/* /*
* Get MAC address from FLASH. * Get MAC address from FLASH.
* If it is all 1's or 0's, use the default. * If it is all 1's or 0's, use the default.
*/ */
iap = fec_flashmac; iap = FEC_FLASHMAC;
if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
(iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
iap = fec_mac_default; iap = fec_mac_default;
...@@ -1354,14 +1390,11 @@ static void __inline__ fec_get_mac(struct net_device *dev) ...@@ -1354,14 +1390,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
iap = &tmpaddr[0]; iap = &tmpaddr[0];
} }
for (i=0; i<ETH_ALEN; i++) memcpy(dev->dev_addr, iap, ETH_ALEN);
dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
/* Adjust MAC if using default MAC address */ /* Adjust MAC if using default MAC address */
if (iap == fec_mac_default) { if (iap == fec_mac_default)
dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] = dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
iap[ETH_ALEN-1] + fep->index;
}
} }
static void __inline__ fec_enable_phy_intr(void) static void __inline__ fec_enable_phy_intr(void)
...@@ -1392,7 +1425,7 @@ static void __inline__ fec_uncache(unsigned long addr) ...@@ -1392,7 +1425,7 @@ static void __inline__ fec_uncache(unsigned long addr)
#else #else
/* /*
* Code sepcific to the MPC860T setup. * Code specific to the MPC860T setup.
*/ */
static void __inline__ fec_request_intrs(struct net_device *dev) static void __inline__ fec_request_intrs(struct net_device *dev)
{ {
...@@ -1424,13 +1457,10 @@ static void __inline__ fec_request_intrs(struct net_device *dev) ...@@ -1424,13 +1457,10 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
static void __inline__ fec_get_mac(struct net_device *dev) static void __inline__ fec_get_mac(struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev);
unsigned char *iap, tmpaddr[6];
bd_t *bd; bd_t *bd;
int i;
iap = bd->bi_enetaddr;
bd = (bd_t *)__res; bd = (bd_t *)__res;
memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
#ifdef CONFIG_RPXCLASSIC #ifdef CONFIG_RPXCLASSIC
/* The Embedded Planet boards have only one MAC address in /* The Embedded Planet boards have only one MAC address in
...@@ -1439,14 +1469,8 @@ static void __inline__ fec_get_mac(struct net_device *dev) ...@@ -1439,14 +1469,8 @@ static void __inline__ fec_get_mac(struct net_device *dev)
* the address bits above something that would have (up to * the address bits above something that would have (up to
* now) been allocated. * now) been allocated.
*/ */
for (i=0; i<6; i++) dev->dev_adrd[3] |= 0x80;
tmpaddr[i] = *iap++;
tmpaddr[3] |= 0x80;
iap = tmpaddr;
#endif #endif
for (i=0; i<6; i++)
dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
} }
static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
...@@ -1556,7 +1580,7 @@ static void mii_display_status(struct net_device *dev) ...@@ -1556,7 +1580,7 @@ static void mii_display_status(struct net_device *dev)
static void mii_display_config(struct net_device *dev) static void mii_display_config(struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status); uint status = fep->phy_status;
/* /*
** When we get here, phy_task is already removed from ** When we get here, phy_task is already removed from
...@@ -1565,23 +1589,23 @@ static void mii_display_config(struct net_device *dev) ...@@ -1565,23 +1589,23 @@ static void mii_display_config(struct net_device *dev)
fep->mii_phy_task_queued = 0; fep->mii_phy_task_queued = 0;
printk("%s: config: auto-negotiation ", dev->name); printk("%s: config: auto-negotiation ", dev->name);
if (*s & PHY_CONF_ANE) if (status & PHY_CONF_ANE)
printk("on"); printk("on");
else else
printk("off"); printk("off");
if (*s & PHY_CONF_100FDX) if (status & PHY_CONF_100FDX)
printk(", 100FDX"); printk(", 100FDX");
if (*s & PHY_CONF_100HDX) if (status & PHY_CONF_100HDX)
printk(", 100HDX"); printk(", 100HDX");
if (*s & PHY_CONF_10FDX) if (status & PHY_CONF_10FDX)
printk(", 10FDX"); printk(", 10FDX");
if (*s & PHY_CONF_10HDX) if (status & PHY_CONF_10HDX)
printk(", 10HDX"); printk(", 10HDX");
if (!(*s & PHY_CONF_SPMASK)) if (!(status & PHY_CONF_SPMASK))
printk(", No speed/duplex selected?"); printk(", No speed/duplex selected?");
if (*s & PHY_CONF_LOOP) if (status & PHY_CONF_LOOP)
printk(", loopback enabled"); printk(", loopback enabled");
printk(".\n"); printk(".\n");
...@@ -1639,7 +1663,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev) ...@@ -1639,7 +1663,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
schedule_work(&fep->phy_task); schedule_work(&fep->phy_task);
} }
/* mii_queue_config is called in user context from fec_enet_open */ /* mii_queue_config is called in interrupt context from fec_enet_mii */
static void mii_queue_config(uint mii_reg, struct net_device *dev) static void mii_queue_config(uint mii_reg, struct net_device *dev)
{ {
struct fec_enet_private *fep = netdev_priv(dev); struct fec_enet_private *fep = netdev_priv(dev);
...@@ -1652,14 +1676,14 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev) ...@@ -1652,14 +1676,14 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev)
schedule_work(&fep->phy_task); schedule_work(&fep->phy_task);
} }
phy_cmd_t const phy_cmd_relink[] = {
{ mk_mii_read(MII_REG_CR), mii_queue_relink },
phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink }, { mk_mii_end, }
{ mk_mii_end, } }; };
phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config }, phy_cmd_t const phy_cmd_config[] = {
{ mk_mii_end, } }; { mk_mii_read(MII_REG_CR), mii_queue_config },
{ mk_mii_end, }
};
/* Read remainder of PHY ID. /* Read remainder of PHY ID.
*/ */
...@@ -1897,17 +1921,15 @@ static void set_multicast_list(struct net_device *dev) ...@@ -1897,17 +1921,15 @@ static void set_multicast_list(struct net_device *dev)
static void static void
fec_set_mac_address(struct net_device *dev) fec_set_mac_address(struct net_device *dev)
{ {
struct fec_enet_private *fep;
volatile fec_t *fecp; volatile fec_t *fecp;
fep = netdev_priv(dev); fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp;
fecp = fep->hwp;
/* Set station address. */ /* Set station address. */
fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) | fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
(fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24); (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24);
fecp->fec_addr_high = (fep->mac_addr[5] << 16) | fecp->fec_addr_high = (dev->dev_addr[5] << 16) |
(fep->mac_addr[4] << 24); (dev->dev_addr[4] << 24);
} }
...@@ -1943,7 +1965,7 @@ int __init fec_enet_init(struct net_device *dev) ...@@ -1943,7 +1965,7 @@ int __init fec_enet_init(struct net_device *dev)
udelay(10); udelay(10);
/* Clear and enable interrupts */ /* Clear and enable interrupts */
fecp->fec_ievent = 0xffc0; fecp->fec_ievent = 0xffc00000;
fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
fecp->fec_hash_table_high = 0; fecp->fec_hash_table_high = 0;
...@@ -2063,11 +2085,6 @@ int __init fec_enet_init(struct net_device *dev) ...@@ -2063,11 +2085,6 @@ int __init fec_enet_init(struct net_device *dev)
/* setup MII interface */ /* setup MII interface */
fec_set_mii(dev, fep); fec_set_mii(dev, fep);
printk("%s: FEC ENET Version 0.2, ", dev->name);
for (i=0; i<5; i++)
printk("%02x:", dev->dev_addr[i]);
printk("%02x\n", dev->dev_addr[5]);
/* Queue up command to detect the PHY and initialize the /* Queue up command to detect the PHY and initialize the
* remainder of the interface. * remainder of the interface.
*/ */
...@@ -2106,18 +2123,12 @@ fec_restart(struct net_device *dev, int duplex) ...@@ -2106,18 +2123,12 @@ fec_restart(struct net_device *dev, int duplex)
/* Clear any outstanding interrupt. /* Clear any outstanding interrupt.
*/ */
fecp->fec_ievent = 0xffc0; fecp->fec_ievent = 0xffc00000;
fec_enable_phy_intr(); fec_enable_phy_intr();
/* Set station address. /* Set station address.
*/ */
fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) | fec_set_mac_address(dev);
(fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
(fep->mac_addr[4] << 24);
for (i=0; i<ETH_ALEN; i++)
dev->dev_addr[i] = fep->mac_addr[i];
/* Reset all multicast. /* Reset all multicast.
*/ */
...@@ -2215,7 +2226,7 @@ fec_stop(struct net_device *dev) ...@@ -2215,7 +2226,7 @@ fec_stop(struct net_device *dev)
fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */ fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */
while(!(fecp->fec_ievent & 0x10000000)); while(!(fecp->fec_ievent & FEC_ENET_GRA));
/* Whack a reset. We should wait for this. /* Whack a reset. We should wait for this.
*/ */
...@@ -2234,7 +2245,9 @@ fec_stop(struct net_device *dev) ...@@ -2234,7 +2245,9 @@ fec_stop(struct net_device *dev)
static int __init fec_enet_module_init(void) static int __init fec_enet_module_init(void)
{ {
struct net_device *dev; struct net_device *dev;
int i, err; int i, j, err;
printk("FEC ENET Version 0.2\n");
for (i = 0; (i < FEC_MAX_PORTS); i++) { for (i = 0; (i < FEC_MAX_PORTS); i++) {
dev = alloc_etherdev(sizeof(struct fec_enet_private)); dev = alloc_etherdev(sizeof(struct fec_enet_private));
...@@ -2250,6 +2263,11 @@ static int __init fec_enet_module_init(void) ...@@ -2250,6 +2263,11 @@ static int __init fec_enet_module_init(void)
free_netdev(dev); free_netdev(dev);
return -EIO; return -EIO;
} }
printk("%s: ethernet ", dev->name);
for (j = 0; (j < 5); j++)
printk("%02x:", dev->dev_addr[j]);
printk("%02x\n", dev->dev_addr[5]);
} }
return 0; return 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册