* [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial @ 2013-03-27 12:09 Joseph CHANG 2013-03-27 12:09 ` [PATCH 2/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial patch2 Joseph CHANG 2013-03-27 13:14 ` [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial Denis Kirjanov 0 siblings, 2 replies; 4+ messages in thread From: Joseph CHANG @ 2013-03-27 12:09 UTC (permalink / raw) To: David S. Miller, Bill Pemberton, Matthew Leach, Greg Kroah-Hartman, Joseph CHANG, Jiri Pirko, netdev Cc: linux-kernel, Joseph CHANG Fixing bug for DM9000B(DSP) which is a DSP revision! 3rd trial. Tested to Davicom DM9000 series include DM9000E(analog), DM9000A(analog), DM9000B(DSP), and DM9000C(DSP) in X86 and ARM Embedded Linux these years. Signed-off-by: Joseph CHANG <josright123@gmail.com> --- drivers/net/ethernet/davicom/dm9000.c | 219 +++++++++++++++++---------------- drivers/net/ethernet/davicom/dm9000.h | 11 ++- 2 files changed, 124 insertions(+), 106 deletions(-) diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 8cdf025..9dd4bd6 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -47,7 +47,7 @@ #define DM9000_PHY 0x40 /* PHY address 0x01 */ #define CARDNAME "dm9000" -#define DRV_VERSION "1.31" +#define DRV_VERSION "1.39" /* * Transmit timeout, default 5 seconds. @@ -257,6 +257,109 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count) tmp = readl(reg); } +/* + * Sleep, either by using msleep() or if we are suspending, then + * use mdelay() to sleep. + */ +static void dm9000_msleep(board_info_t *db, unsigned int ms) +{ + if (db->in_suspend) + mdelay(ms); + else + msleep(ms); +} + +/* + * Read a word from phyxcer + */ +static int +dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) +{ + board_info_t *db = netdev_priv(dev); + unsigned long flags; + unsigned int reg_save; + int ret; + + mutex_lock(&db->addr_lock); + + spin_lock_irqsave(&db->lock,flags); + + /* Save previous register address */ + reg_save = readb(db->io_addr); + + /* Fill the phyxcer register into REG_0C */ + iow(db, DM9000_EPAR, DM9000_PHY | reg); + + iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read command */ + + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock,flags); + + dm9000_msleep(db, 1); /* Wait read complete */ + + spin_lock_irqsave(&db->lock,flags); + reg_save = readb(db->io_addr); + + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ + + /* The read data keeps on REG_0D & REG_0E */ + ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); + + /* restore the previous address */ + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock,flags); + + mutex_unlock(&db->addr_lock); + + dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); + return ret; +} + +/* + * Write a word to phyxcer + */ +static void +dm9000_phy_write(struct net_device *dev, + int phyaddr_unused, int reg, int value) +{ + board_info_t *db = netdev_priv(dev); + unsigned long flags; + unsigned long reg_save; + + dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); + mutex_lock(&db->addr_lock); + + spin_lock_irqsave(&db->lock,flags); + + /* Save previous register address */ + reg_save = readb(db->io_addr); + + /* Fill the phyxcer register into REG_0C */ + iow(db, DM9000_EPAR, DM9000_PHY | reg); + + /* Fill the written data into REG_0D & REG_0E */ + iow(db, DM9000_EPDRL, value); + iow(db, DM9000_EPDRH, value >> 8); + + iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write command */ + + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock, flags); + + dm9000_msleep(db, 1); /* Wait write complete */ + + spin_lock_irqsave(&db->lock,flags); + reg_save = readb(db->io_addr); + + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ + + /* restore the previous address */ + writeb(reg_save, db->io_addr); + + spin_unlock_irqrestore(&db->lock, flags); + mutex_unlock(&db->addr_lock); +} + /* dm9000_set_io * * select the specified set of io routines to use with the @@ -795,6 +898,8 @@ dm9000_init_dm9000(struct net_device *dev) iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ + dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */ + ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0; /* if wol is needed, then always set NCR_WAKEEN otherwise we end @@ -830,6 +935,8 @@ dm9000_init_dm9000(struct net_device *dev) db->tx_pkt_cnt = 0; db->queue_pkt_len = 0; dev->trans_start = jiffies; + + dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */ } /* Our watchdog timed out. Called by the networking layer */ @@ -1201,109 +1308,6 @@ dm9000_open(struct net_device *dev) return 0; } -/* - * Sleep, either by using msleep() or if we are suspending, then - * use mdelay() to sleep. - */ -static void dm9000_msleep(board_info_t *db, unsigned int ms) -{ - if (db->in_suspend) - mdelay(ms); - else - msleep(ms); -} - -/* - * Read a word from phyxcer - */ -static int -dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) -{ - board_info_t *db = netdev_priv(dev); - unsigned long flags; - unsigned int reg_save; - int ret; - - mutex_lock(&db->addr_lock); - - spin_lock_irqsave(&db->lock,flags); - - /* Save previous register address */ - reg_save = readb(db->io_addr); - - /* Fill the phyxcer register into REG_0C */ - iow(db, DM9000_EPAR, DM9000_PHY | reg); - - iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read command */ - - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); - - dm9000_msleep(db, 1); /* Wait read complete */ - - spin_lock_irqsave(&db->lock,flags); - reg_save = readb(db->io_addr); - - iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ - - /* The read data keeps on REG_0D & REG_0E */ - ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); - - /* restore the previous address */ - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); - - mutex_unlock(&db->addr_lock); - - dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); - return ret; -} - -/* - * Write a word to phyxcer - */ -static void -dm9000_phy_write(struct net_device *dev, - int phyaddr_unused, int reg, int value) -{ - board_info_t *db = netdev_priv(dev); - unsigned long flags; - unsigned long reg_save; - - dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); - mutex_lock(&db->addr_lock); - - spin_lock_irqsave(&db->lock,flags); - - /* Save previous register address */ - reg_save = readb(db->io_addr); - - /* Fill the phyxcer register into REG_0C */ - iow(db, DM9000_EPAR, DM9000_PHY | reg); - - /* Fill the written data into REG_0D & REG_0E */ - iow(db, DM9000_EPDRL, value); - iow(db, DM9000_EPDRH, value >> 8); - - iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write command */ - - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock, flags); - - dm9000_msleep(db, 1); /* Wait write complete */ - - spin_lock_irqsave(&db->lock,flags); - reg_save = readb(db->io_addr); - - iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ - - /* restore the previous address */ - writeb(reg_save, db->io_addr); - - spin_unlock_irqrestore(&db->lock, flags); - mutex_unlock(&db->addr_lock); -} - static void dm9000_shutdown(struct net_device *dev) { @@ -1502,7 +1506,12 @@ dm9000_probe(struct platform_device *pdev) db->flags |= DM9000_PLATF_SIMPLE_PHY; #endif - dm9000_reset(db); + /* Fixing bug on dm9000_probe, takeover dm9000_reset(db), + * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo + * while probe stage. + */ + + iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST); /* try multiple times, DM9000 sometimes gets the read wrong */ for (i = 0; i < 8; i++) { diff --git a/drivers/net/ethernet/davicom/dm9000.h b/drivers/net/ethernet/davicom/dm9000.h index 55688bd..9ce058a 100644 --- a/drivers/net/ethernet/davicom/dm9000.h +++ b/drivers/net/ethernet/davicom/dm9000.h @@ -69,7 +69,9 @@ #define NCR_WAKEEN (1<<6) #define NCR_FCOL (1<<4) #define NCR_FDX (1<<3) -#define NCR_LBK (3<<1) + +#define NCR_RESERVED (3<<1) +#define NCR_MAC_LBK (1<<1) #define NCR_RST (1<<0) #define NSR_SPEED (1<<7) @@ -167,5 +169,12 @@ #define ISR_LNKCHNG (1<<5) #define ISR_UNDERRUN (1<<4) +/* Davicom MII registers. + */ + +#define MII_DM_DSPCR 0x1b /* DSP Control Register */ + +#define DSPCR_INIT_PARAM 0xE100 /* DSP init parameter */ + #endif /* _DM9000X_H_ */ -- 1.7.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial patch2 2013-03-27 12:09 [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial Joseph CHANG @ 2013-03-27 12:09 ` Joseph CHANG 2013-03-27 13:14 ` [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial Denis Kirjanov 1 sibling, 0 replies; 4+ messages in thread From: Joseph CHANG @ 2013-03-27 12:09 UTC (permalink / raw) To: David S. Miller, Bill Pemberton, Matthew Leach, Greg Kroah-Hartman, Joseph CHANG, Jiri Pirko, netdev Cc: linux-kernel, Joseph CHANG Fixing bug for DM9000B(DSP) patch2 Tested to Davicom DM9000E, DM9000A, DM9000B(DSP), and DM9000C(DSP) patch2 Signed-off-by: Joseph CHANG <josright123@gmail.com> --- drivers/net/ethernet/davicom/dm9000.c | 26 ++++++++++++-------------- 1 files changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 9dd4bd6..a5cd4ad 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -269,9 +269,7 @@ static void dm9000_msleep(board_info_t *db, unsigned int ms) msleep(ms); } -/* - * Read a word from phyxcer - */ +/* Read a word from phyxcer */ static int dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) { @@ -282,7 +280,7 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) mutex_lock(&db->addr_lock); - spin_lock_irqsave(&db->lock,flags); + spin_lock_irqsave(&db->lock, flags); /* Save previous register address */ reg_save = readb(db->io_addr); @@ -290,14 +288,15 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) /* Fill the phyxcer register into REG_0C */ iow(db, DM9000_EPAR, DM9000_PHY | reg); - iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read command */ + /* Issue phyxcer read command */ + iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); + spin_unlock_irqrestore(&db->lock, flags); dm9000_msleep(db, 1); /* Wait read complete */ - spin_lock_irqsave(&db->lock,flags); + spin_lock_irqsave(&db->lock, flags); reg_save = readb(db->io_addr); iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ @@ -307,7 +306,7 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) /* restore the previous address */ writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); + spin_unlock_irqrestore(&db->lock, flags); mutex_unlock(&db->addr_lock); @@ -315,9 +314,7 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) return ret; } -/* - * Write a word to phyxcer - */ +/* Write a word to phyxcer */ static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value) @@ -329,7 +326,7 @@ dm9000_phy_write(struct net_device *dev, dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); mutex_lock(&db->addr_lock); - spin_lock_irqsave(&db->lock,flags); + spin_lock_irqsave(&db->lock, flags); /* Save previous register address */ reg_save = readb(db->io_addr); @@ -341,14 +338,15 @@ dm9000_phy_write(struct net_device *dev, iow(db, DM9000_EPDRL, value); iow(db, DM9000_EPDRH, value >> 8); - iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write command */ + /* Issue phyxcer write command */ + iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); writeb(reg_save, db->io_addr); spin_unlock_irqrestore(&db->lock, flags); dm9000_msleep(db, 1); /* Wait write complete */ - spin_lock_irqsave(&db->lock,flags); + spin_lock_irqsave(&db->lock, flags); reg_save = readb(db->io_addr); iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ -- 1.7.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial 2013-03-27 12:09 [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial Joseph CHANG 2013-03-27 12:09 ` [PATCH 2/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial patch2 Joseph CHANG @ 2013-03-27 13:14 ` Denis Kirjanov 2013-03-28 2:50 ` Joseph Chang 1 sibling, 1 reply; 4+ messages in thread From: Denis Kirjanov @ 2013-03-27 13:14 UTC (permalink / raw) To: Joseph CHANG Cc: David S. Miller, Bill Pemberton, Matthew Leach, Greg Kroah-Hartman, Joseph CHANG, Jiri Pirko, netdev, linux-kernel It's not clear from your log what was wrong with the driver. Could you please update the log message. On 3/27/13, Joseph CHANG <josright123@gmail.com> wrote: > Fixing bug for DM9000B(DSP) which is a DSP revision! 3rd trial. > > Tested to Davicom DM9000 series include DM9000E(analog), > DM9000A(analog), DM9000B(DSP), and DM9000C(DSP) in X86 and > ARM Embedded Linux these years. > > Signed-off-by: Joseph CHANG <josright123@gmail.com> > --- > drivers/net/ethernet/davicom/dm9000.c | 219 > +++++++++++++++++---------------- > drivers/net/ethernet/davicom/dm9000.h | 11 ++- > 2 files changed, 124 insertions(+), 106 deletions(-) > > diff --git a/drivers/net/ethernet/davicom/dm9000.c > b/drivers/net/ethernet/davicom/dm9000.c > index 8cdf025..9dd4bd6 100644 > --- a/drivers/net/ethernet/davicom/dm9000.c > +++ b/drivers/net/ethernet/davicom/dm9000.c > @@ -47,7 +47,7 @@ > #define DM9000_PHY 0x40 /* PHY address 0x01 */ > > #define CARDNAME "dm9000" > -#define DRV_VERSION "1.31" > +#define DRV_VERSION "1.39" > > /* > * Transmit timeout, default 5 seconds. > @@ -257,6 +257,109 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, > int count) > tmp = readl(reg); > } > > +/* > + * Sleep, either by using msleep() or if we are suspending, then > + * use mdelay() to sleep. > + */ > +static void dm9000_msleep(board_info_t *db, unsigned int ms) > +{ > + if (db->in_suspend) > + mdelay(ms); > + else > + msleep(ms); > +} > + > +/* > + * Read a word from phyxcer > + */ > +static int > +dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) > +{ > + board_info_t *db = netdev_priv(dev); > + unsigned long flags; > + unsigned int reg_save; > + int ret; > + > + mutex_lock(&db->addr_lock); > + > + spin_lock_irqsave(&db->lock,flags); > + > + /* Save previous register address */ > + reg_save = readb(db->io_addr); > + > + /* Fill the phyxcer register into REG_0C */ > + iow(db, DM9000_EPAR, DM9000_PHY | reg); > + > + iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read > command */ > + > + writeb(reg_save, db->io_addr); > + spin_unlock_irqrestore(&db->lock,flags); > + > + dm9000_msleep(db, 1); /* Wait read complete */ > + > + spin_lock_irqsave(&db->lock,flags); > + reg_save = readb(db->io_addr); > + > + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ > + > + /* The read data keeps on REG_0D & REG_0E */ > + ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); > + > + /* restore the previous address */ > + writeb(reg_save, db->io_addr); > + spin_unlock_irqrestore(&db->lock,flags); > + > + mutex_unlock(&db->addr_lock); > + > + dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); > + return ret; > +} > + > +/* > + * Write a word to phyxcer > + */ > +static void > +dm9000_phy_write(struct net_device *dev, > + int phyaddr_unused, int reg, int value) > +{ > + board_info_t *db = netdev_priv(dev); > + unsigned long flags; > + unsigned long reg_save; > + > + dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); > + mutex_lock(&db->addr_lock); > + > + spin_lock_irqsave(&db->lock,flags); > + > + /* Save previous register address */ > + reg_save = readb(db->io_addr); > + > + /* Fill the phyxcer register into REG_0C */ > + iow(db, DM9000_EPAR, DM9000_PHY | reg); > + > + /* Fill the written data into REG_0D & REG_0E */ > + iow(db, DM9000_EPDRL, value); > + iow(db, DM9000_EPDRH, value >> 8); > + > + iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write > command */ > + > + writeb(reg_save, db->io_addr); > + spin_unlock_irqrestore(&db->lock, flags); > + > + dm9000_msleep(db, 1); /* Wait write complete */ > + > + spin_lock_irqsave(&db->lock,flags); > + reg_save = readb(db->io_addr); > + > + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ > + > + /* restore the previous address */ > + writeb(reg_save, db->io_addr); > + > + spin_unlock_irqrestore(&db->lock, flags); > + mutex_unlock(&db->addr_lock); > +} > + > /* dm9000_set_io > * > * select the specified set of io routines to use with the > @@ -795,6 +898,8 @@ dm9000_init_dm9000(struct net_device *dev) > > iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ > > + dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */ > + > ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0; > > /* if wol is needed, then always set NCR_WAKEEN otherwise we end > @@ -830,6 +935,8 @@ dm9000_init_dm9000(struct net_device *dev) > db->tx_pkt_cnt = 0; > db->queue_pkt_len = 0; > dev->trans_start = jiffies; > + > + dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */ > } > > /* Our watchdog timed out. Called by the networking layer */ > @@ -1201,109 +1308,6 @@ dm9000_open(struct net_device *dev) > return 0; > } > > -/* > - * Sleep, either by using msleep() or if we are suspending, then > - * use mdelay() to sleep. > - */ > -static void dm9000_msleep(board_info_t *db, unsigned int ms) > -{ > - if (db->in_suspend) > - mdelay(ms); > - else > - msleep(ms); > -} > - > -/* > - * Read a word from phyxcer > - */ > -static int > -dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) > -{ > - board_info_t *db = netdev_priv(dev); > - unsigned long flags; > - unsigned int reg_save; > - int ret; > - > - mutex_lock(&db->addr_lock); > - > - spin_lock_irqsave(&db->lock,flags); > - > - /* Save previous register address */ > - reg_save = readb(db->io_addr); > - > - /* Fill the phyxcer register into REG_0C */ > - iow(db, DM9000_EPAR, DM9000_PHY | reg); > - > - iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read > command */ > - > - writeb(reg_save, db->io_addr); > - spin_unlock_irqrestore(&db->lock,flags); > - > - dm9000_msleep(db, 1); /* Wait read complete */ > - > - spin_lock_irqsave(&db->lock,flags); > - reg_save = readb(db->io_addr); > - > - iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ > - > - /* The read data keeps on REG_0D & REG_0E */ > - ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); > - > - /* restore the previous address */ > - writeb(reg_save, db->io_addr); > - spin_unlock_irqrestore(&db->lock,flags); > - > - mutex_unlock(&db->addr_lock); > - > - dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); > - return ret; > -} > - > -/* > - * Write a word to phyxcer > - */ > -static void > -dm9000_phy_write(struct net_device *dev, > - int phyaddr_unused, int reg, int value) > -{ > - board_info_t *db = netdev_priv(dev); > - unsigned long flags; > - unsigned long reg_save; > - > - dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); > - mutex_lock(&db->addr_lock); > - > - spin_lock_irqsave(&db->lock,flags); > - > - /* Save previous register address */ > - reg_save = readb(db->io_addr); > - > - /* Fill the phyxcer register into REG_0C */ > - iow(db, DM9000_EPAR, DM9000_PHY | reg); > - > - /* Fill the written data into REG_0D & REG_0E */ > - iow(db, DM9000_EPDRL, value); > - iow(db, DM9000_EPDRH, value >> 8); > - > - iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write > command */ > - > - writeb(reg_save, db->io_addr); > - spin_unlock_irqrestore(&db->lock, flags); > - > - dm9000_msleep(db, 1); /* Wait write complete */ > - > - spin_lock_irqsave(&db->lock,flags); > - reg_save = readb(db->io_addr); > - > - iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ > - > - /* restore the previous address */ > - writeb(reg_save, db->io_addr); > - > - spin_unlock_irqrestore(&db->lock, flags); > - mutex_unlock(&db->addr_lock); > -} > - > static void > dm9000_shutdown(struct net_device *dev) > { > @@ -1502,7 +1506,12 @@ dm9000_probe(struct platform_device *pdev) > db->flags |= DM9000_PLATF_SIMPLE_PHY; > #endif > > - dm9000_reset(db); > + /* Fixing bug on dm9000_probe, takeover dm9000_reset(db), > + * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo > + * while probe stage. > + */ > + > + iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST); > > /* try multiple times, DM9000 sometimes gets the read wrong */ > for (i = 0; i < 8; i++) { > diff --git a/drivers/net/ethernet/davicom/dm9000.h > b/drivers/net/ethernet/davicom/dm9000.h > index 55688bd..9ce058a 100644 > --- a/drivers/net/ethernet/davicom/dm9000.h > +++ b/drivers/net/ethernet/davicom/dm9000.h > @@ -69,7 +69,9 @@ > #define NCR_WAKEEN (1<<6) > #define NCR_FCOL (1<<4) > #define NCR_FDX (1<<3) > -#define NCR_LBK (3<<1) > + > +#define NCR_RESERVED (3<<1) > +#define NCR_MAC_LBK (1<<1) > #define NCR_RST (1<<0) > > #define NSR_SPEED (1<<7) > @@ -167,5 +169,12 @@ > #define ISR_LNKCHNG (1<<5) > #define ISR_UNDERRUN (1<<4) > > +/* Davicom MII registers. > + */ > + > +#define MII_DM_DSPCR 0x1b /* DSP Control Register */ > + > +#define DSPCR_INIT_PARAM 0xE100 /* DSP init parameter */ > + > #endif /* _DM9000X_H_ */ > > -- > 1.7.1 > > -- > To unsubscribe from this list: send the line "unsubscribe netdev" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial 2013-03-27 13:14 ` [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial Denis Kirjanov @ 2013-03-28 2:50 ` Joseph Chang 0 siblings, 0 replies; 4+ messages in thread From: Joseph Chang @ 2013-03-28 2:50 UTC (permalink / raw) To: 'Denis Kirjanov', 'Joseph CHANG' Cc: 'David S. Miller', 'Bill Pemberton', 'Matthew Leach', 'Greg Kroah-Hartman', 'Joseph CHANG', 'Jiri Pirko', netdev, linux-kernel Dear Denis, Yes, I can tell more detail, Should I re-do the patch and submit again? I will revise the log as below: (Please help comment again, thanks.) - Fixing bug for DM9000B(DSP) which is a DSP revision! 3rd trial. - - The chip of DM9000B(DSP) is different in internal PHY compare to DM9000A(analog) and - DM9000E(analog). - This patch add a PHY RESET and a PHY INIT PARAMETER settings in - "dm9000_init_dm9000()", and - This patch change set DM9000_NCR by reset-bit to be set DM9000_NCR by reset-bit - conjunction with mac_loopback-bit in "dm9000_probe()". - The driver could get wrong DM9000B FIFO(internal) state during driver initialize, But not each - target board case, error rate is around 2%. - We patch the driver this way to solve this initial fatal issue. Best Regards, Joseph CHANG System Application Engineering Division Davicom Semiconductor, Inc. No. 6 Li-Hsin Rd. VI, Science-Based Park, Hsin-Chu, Taiwan. Tel: 886-3-5798797 Ex 8534 Fax: 886-3-5646929 Web: http://www.davicom.com.tw -----Original Message----- From: Denis Kirjanov [mailto:kda@linux-powerpc.org] Sent: Wednesday, March 27, 2013 9:14 PM To: Joseph CHANG Cc: David S. Miller; Bill Pemberton; Matthew Leach; Greg Kroah-Hartman; Joseph CHANG; Jiri Pirko; netdev@vger.kernel.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial It's not clear from your log what was wrong with the driver. Could you please update the log message. On 3/27/13, Joseph CHANG <josright123@gmail.com> wrote: > Fixing bug for DM9000B(DSP) which is a DSP revision! 3rd trial. > > Tested to Davicom DM9000 series include DM9000E(analog), > DM9000A(analog), DM9000B(DSP), and DM9000C(DSP) in X86 and > ARM Embedded Linux these years. > > Signed-off-by: Joseph CHANG <josright123@gmail.com> > --- > drivers/net/ethernet/davicom/dm9000.c | 219 > +++++++++++++++++---------------- > drivers/net/ethernet/davicom/dm9000.h | 11 ++- > 2 files changed, 124 insertions(+), 106 deletions(-) > > diff --git a/drivers/net/ethernet/davicom/dm9000.c > b/drivers/net/ethernet/davicom/dm9000.c > index 8cdf025..9dd4bd6 100644 > --- a/drivers/net/ethernet/davicom/dm9000.c > +++ b/drivers/net/ethernet/davicom/dm9000.c > @@ -47,7 +47,7 @@ > #define DM9000_PHY 0x40 /* PHY address 0x01 */ > > #define CARDNAME "dm9000" > -#define DRV_VERSION "1.31" > +#define DRV_VERSION "1.39" > > /* > * Transmit timeout, default 5 seconds. > @@ -257,6 +257,109 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, > int count) > tmp = readl(reg); > } > > +/* > + * Sleep, either by using msleep() or if we are suspending, then > + * use mdelay() to sleep. > + */ > +static void dm9000_msleep(board_info_t *db, unsigned int ms) > +{ > + if (db->in_suspend) > + mdelay(ms); > + else > + msleep(ms); > +} > + > +/* > + * Read a word from phyxcer > + */ > +static int > +dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) > +{ > + board_info_t *db = netdev_priv(dev); > + unsigned long flags; > + unsigned int reg_save; > + int ret; > + > + mutex_lock(&db->addr_lock); > + > + spin_lock_irqsave(&db->lock,flags); > + > + /* Save previous register address */ > + reg_save = readb(db->io_addr); > + > + /* Fill the phyxcer register into REG_0C */ > + iow(db, DM9000_EPAR, DM9000_PHY | reg); > + > + iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read > command */ > + > + writeb(reg_save, db->io_addr); > + spin_unlock_irqrestore(&db->lock,flags); > + > + dm9000_msleep(db, 1); /* Wait read complete */ > + > + spin_lock_irqsave(&db->lock,flags); > + reg_save = readb(db->io_addr); > + > + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ > + > + /* The read data keeps on REG_0D & REG_0E */ > + ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); > + > + /* restore the previous address */ > + writeb(reg_save, db->io_addr); > + spin_unlock_irqrestore(&db->lock,flags); > + > + mutex_unlock(&db->addr_lock); > + > + dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); > + return ret; > +} > + > +/* > + * Write a word to phyxcer > + */ > +static void > +dm9000_phy_write(struct net_device *dev, > + int phyaddr_unused, int reg, int value) > +{ > + board_info_t *db = netdev_priv(dev); > + unsigned long flags; > + unsigned long reg_save; > + > + dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); > + mutex_lock(&db->addr_lock); > + > + spin_lock_irqsave(&db->lock,flags); > + > + /* Save previous register address */ > + reg_save = readb(db->io_addr); > + > + /* Fill the phyxcer register into REG_0C */ > + iow(db, DM9000_EPAR, DM9000_PHY | reg); > + > + /* Fill the written data into REG_0D & REG_0E */ > + iow(db, DM9000_EPDRL, value); > + iow(db, DM9000_EPDRH, value >> 8); > + > + iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write > command */ > + > + writeb(reg_save, db->io_addr); > + spin_unlock_irqrestore(&db->lock, flags); > + > + dm9000_msleep(db, 1); /* Wait write complete */ > + > + spin_lock_irqsave(&db->lock,flags); > + reg_save = readb(db->io_addr); > + > + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ > + > + /* restore the previous address */ > + writeb(reg_save, db->io_addr); > + > + spin_unlock_irqrestore(&db->lock, flags); > + mutex_unlock(&db->addr_lock); > +} > + > /* dm9000_set_io > * > * select the specified set of io routines to use with the > @@ -795,6 +898,8 @@ dm9000_init_dm9000(struct net_device *dev) > > iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ > > + dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */ > + > ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0; > > /* if wol is needed, then always set NCR_WAKEEN otherwise we end > @@ -830,6 +935,8 @@ dm9000_init_dm9000(struct net_device *dev) > db->tx_pkt_cnt = 0; > db->queue_pkt_len = 0; > dev->trans_start = jiffies; > + > + dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */ > } > > /* Our watchdog timed out. Called by the networking layer */ > @@ -1201,109 +1308,6 @@ dm9000_open(struct net_device *dev) > return 0; > } > > -/* > - * Sleep, either by using msleep() or if we are suspending, then > - * use mdelay() to sleep. > - */ > -static void dm9000_msleep(board_info_t *db, unsigned int ms) > -{ > - if (db->in_suspend) > - mdelay(ms); > - else > - msleep(ms); > -} > - > -/* > - * Read a word from phyxcer > - */ > -static int > -dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) > -{ > - board_info_t *db = netdev_priv(dev); > - unsigned long flags; > - unsigned int reg_save; > - int ret; > - > - mutex_lock(&db->addr_lock); > - > - spin_lock_irqsave(&db->lock,flags); > - > - /* Save previous register address */ > - reg_save = readb(db->io_addr); > - > - /* Fill the phyxcer register into REG_0C */ > - iow(db, DM9000_EPAR, DM9000_PHY | reg); > - > - iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read > command */ > - > - writeb(reg_save, db->io_addr); > - spin_unlock_irqrestore(&db->lock,flags); > - > - dm9000_msleep(db, 1); /* Wait read complete */ > - > - spin_lock_irqsave(&db->lock,flags); > - reg_save = readb(db->io_addr); > - > - iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ > - > - /* The read data keeps on REG_0D & REG_0E */ > - ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); > - > - /* restore the previous address */ > - writeb(reg_save, db->io_addr); > - spin_unlock_irqrestore(&db->lock,flags); > - > - mutex_unlock(&db->addr_lock); > - > - dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); > - return ret; > -} > - > -/* > - * Write a word to phyxcer > - */ > -static void > -dm9000_phy_write(struct net_device *dev, > - int phyaddr_unused, int reg, int value) > -{ > - board_info_t *db = netdev_priv(dev); > - unsigned long flags; > - unsigned long reg_save; > - > - dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); > - mutex_lock(&db->addr_lock); > - > - spin_lock_irqsave(&db->lock,flags); > - > - /* Save previous register address */ > - reg_save = readb(db->io_addr); > - > - /* Fill the phyxcer register into REG_0C */ > - iow(db, DM9000_EPAR, DM9000_PHY | reg); > - > - /* Fill the written data into REG_0D & REG_0E */ > - iow(db, DM9000_EPDRL, value); > - iow(db, DM9000_EPDRH, value >> 8); > - > - iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write > command */ > - > - writeb(reg_save, db->io_addr); > - spin_unlock_irqrestore(&db->lock, flags); > - > - dm9000_msleep(db, 1); /* Wait write complete */ > - > - spin_lock_irqsave(&db->lock,flags); > - reg_save = readb(db->io_addr); > - > - iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ > - > - /* restore the previous address */ > - writeb(reg_save, db->io_addr); > - > - spin_unlock_irqrestore(&db->lock, flags); > - mutex_unlock(&db->addr_lock); > -} > - > static void > dm9000_shutdown(struct net_device *dev) > { > @@ -1502,7 +1506,12 @@ dm9000_probe(struct platform_device *pdev) > db->flags |= DM9000_PLATF_SIMPLE_PHY; > #endif > > - dm9000_reset(db); > + /* Fixing bug on dm9000_probe, takeover dm9000_reset(db), > + * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo > + * while probe stage. > + */ > + > + iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST); > > /* try multiple times, DM9000 sometimes gets the read wrong */ > for (i = 0; i < 8; i++) { > diff --git a/drivers/net/ethernet/davicom/dm9000.h > b/drivers/net/ethernet/davicom/dm9000.h > index 55688bd..9ce058a 100644 > --- a/drivers/net/ethernet/davicom/dm9000.h > +++ b/drivers/net/ethernet/davicom/dm9000.h > @@ -69,7 +69,9 @@ > #define NCR_WAKEEN (1<<6) > #define NCR_FCOL (1<<4) > #define NCR_FDX (1<<3) > -#define NCR_LBK (3<<1) > + > +#define NCR_RESERVED (3<<1) > +#define NCR_MAC_LBK (1<<1) > #define NCR_RST (1<<0) > > #define NSR_SPEED (1<<7) > @@ -167,5 +169,12 @@ > #define ISR_LNKCHNG (1<<5) > #define ISR_UNDERRUN (1<<4) > > +/* Davicom MII registers. > + */ > + > +#define MII_DM_DSPCR 0x1b /* DSP Control Register */ > + > +#define DSPCR_INIT_PARAM 0xE100 /* DSP init parameter */ > + > #endif /* _DM9000X_H_ */ > > -- > 1.7.1 > > -- > To unsubscribe from this list: send the line "unsubscribe netdev" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean. ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-03-28 2:51 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-03-27 12:09 [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial Joseph CHANG 2013-03-27 12:09 ` [PATCH 2/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial patch2 Joseph CHANG 2013-03-27 13:14 ` [PATCH 1/2] ethernet: dm9000 driver: davicom: upgrade driver: 3rd trial Denis Kirjanov 2013-03-28 2:50 ` Joseph Chang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).