* [patch 0/9] DM9000 updates for 2.6.27
@ 2008-06-15 23:26 Ben Dooks
2008-06-15 23:26 ` [patch 1/9] DM9000: Remove the 2 resources probe scheme Ben Dooks
` (8 more replies)
0 siblings, 9 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-15 23:26 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik
This set of updates adds support for the newer DM9000
compatible devices (DM9000A and DM9000B) and support
for faster link-status polling. It also has some source
cleanups and misc fixes.
I've included the DM9000 only part of Laurent's resource
fixes and a few tidyups resulting from these changes.
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 1/9] DM9000: Remove the 2 resources probe scheme.
2008-06-15 23:26 [patch 0/9] DM9000 updates for 2.6.27 Ben Dooks
@ 2008-06-15 23:26 ` Ben Dooks
2008-06-15 23:26 ` [patch 2/9] DM9000: Add support for DM9000A and DM9000B chips Ben Dooks
` (7 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-15 23:26 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik, Ben Dooks, Laurent Pinchart
[-- Attachment #1: thirdparty/dm9000-remove-2resources.patch --]
[-- Type: text/plain, Size: 4431 bytes --]
From: Laurent Pinchart <laurentp@cse-semaphore.com>
The dm9000 driver accepts either 2 or 3 resources to describe the platform
devices. The 2 resources case abuses the ioresource mechanism by passing
ioremap()ed memory through the platform device resources. This patch removes
that case and converts boards that were using it to the 3 resources scheme.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Laurent Pinchart <laurentp@cse-semaphore.com>
---
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 6bc8924..fca7831 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -528,7 +528,6 @@ dm9000_probe(struct platform_device *pdev)
struct board_info *db; /* Point a board information structure */
struct net_device *ndev;
const unsigned char *mac_src;
- unsigned long base;
int ret = 0;
int iosize;
int i;
@@ -561,78 +560,61 @@ dm9000_probe(struct platform_device *pdev)
if (pdev->num_resources < 2) {
ret = -ENODEV;
goto out;
- } else if (pdev->num_resources == 2) {
- base = pdev->resource[0].start;
-
- if (!request_mem_region(base, 4, ndev->name)) {
- ret = -EBUSY;
- goto out;
- }
-
- ndev->base_addr = base;
- ndev->irq = pdev->resource[1].start;
- db->io_addr = (void __iomem *)base;
- db->io_data = (void __iomem *)(base + 4);
+ }
- /* ensure at least we have a default set of IO routines */
- dm9000_set_io(db, 2);
+ db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- } else {
- db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-
- if (db->addr_res == NULL || db->data_res == NULL ||
- db->irq_res == NULL) {
- dev_err(db->dev, "insufficient resources\n");
- ret = -ENOENT;
- goto out;
- }
+ if (db->addr_res == NULL || db->data_res == NULL ||
+ db->irq_res == NULL) {
+ dev_err(db->dev, "insufficient resources\n");
+ ret = -ENOENT;
+ goto out;
+ }
- i = res_size(db->addr_res);
- db->addr_req = request_mem_region(db->addr_res->start, i,
- pdev->name);
+ iosize = res_size(db->addr_res);
+ db->addr_req = request_mem_region(db->addr_res->start, iosize,
+ pdev->name);
- if (db->addr_req == NULL) {
- dev_err(db->dev, "cannot claim address reg area\n");
- ret = -EIO;
- goto out;
- }
-
- db->io_addr = ioremap(db->addr_res->start, i);
+ if (db->addr_req == NULL) {
+ dev_err(db->dev, "cannot claim address reg area\n");
+ ret = -EIO;
+ goto out;
+ }
- if (db->io_addr == NULL) {
- dev_err(db->dev, "failed to ioremap address reg\n");
- ret = -EINVAL;
- goto out;
- }
+ db->io_addr = ioremap(db->addr_res->start, iosize);
- iosize = res_size(db->data_res);
- db->data_req = request_mem_region(db->data_res->start, iosize,
- pdev->name);
+ if (db->io_addr == NULL) {
+ dev_err(db->dev, "failed to ioremap address reg\n");
+ ret = -EINVAL;
+ goto out;
+ }
- if (db->data_req == NULL) {
- dev_err(db->dev, "cannot claim data reg area\n");
- ret = -EIO;
- goto out;
- }
+ iosize = res_size(db->data_res);
+ db->data_req = request_mem_region(db->data_res->start, iosize,
+ pdev->name);
- db->io_data = ioremap(db->data_res->start, iosize);
+ if (db->data_req == NULL) {
+ dev_err(db->dev, "cannot claim data reg area\n");
+ ret = -EIO;
+ goto out;
+ }
- if (db->io_data == NULL) {
- dev_err(db->dev,"failed to ioremap data reg\n");
- ret = -EINVAL;
- goto out;
- }
+ db->io_data = ioremap(db->data_res->start, iosize);
- /* fill in parameters for net-dev structure */
+ if (db->io_data == NULL) {
+ dev_err(db->dev,"failed to ioremap data reg\n");
+ ret = -EINVAL;
+ goto out;
+ }
- ndev->base_addr = (unsigned long)db->io_addr;
- ndev->irq = db->irq_res->start;
+ /* fill in parameters for net-dev structure */
+ ndev->base_addr = (unsigned long)db->io_addr;
+ ndev->irq = db->irq_res->start;
- /* ensure at least we have a default set of IO routines */
- dm9000_set_io(db, iosize);
- }
+ /* ensure at least we have a default set of IO routines */
+ dm9000_set_io(db, iosize);
/* check to see if anything is being over-ridden */
if (pdata != NULL) {
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [patch 2/9] DM9000: Add support for DM9000A and DM9000B chips
2008-06-15 23:26 [patch 0/9] DM9000 updates for 2.6.27 Ben Dooks
2008-06-15 23:26 ` [patch 1/9] DM9000: Remove the 2 resources probe scheme Ben Dooks
@ 2008-06-15 23:26 ` Ben Dooks
2008-06-15 23:26 ` [patch 3/9] DM9000: Cleanup source code Ben Dooks
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-15 23:26 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik, Ben Dooks
[-- Attachment #1: simtec/simtec-drivers-net-dm9000-support-dm9000ab.patch --]
[-- Type: text/plain, Size: 4974 bytes --]
Add support for both the DM9000A and DM9000B versions of
the DM9000 networking chip. This includes adding support
for the Link-Change IRQ which is used instead of polling
the PHY every 2 seconds.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Index: linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/net/dm9000.c 2008-06-15 22:52:15.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c 2008-06-15 22:52:19.000000000 +0100
@@ -85,6 +85,16 @@ MODULE_PARM_DESC(watchdog, "transmit tim
* these two devices.
*/
+/* The driver supports the original DM9000E, and now the two newer
+ * devices, DM9000A and DM9000B.
+ */
+
+enum dm9000_type {
+ TYPE_DM9000E, /* original DM9000 */
+ TYPE_DM9000A,
+ TYPE_DM9000B
+};
+
/* Structure/enum declaration ------------------------------- */
typedef struct board_info {
@@ -98,9 +108,11 @@ typedef struct board_info {
u16 dbug_cnt;
u8 io_mode; /* 0:word, 2:byte */
u8 phy_addr;
+ u8 imr_all;
unsigned int flags;
unsigned int in_suspend :1;
+ enum dm9000_type type;
int debug_level;
void (*inblk)(void __iomem *port, void *data, int length);
@@ -302,7 +314,8 @@ static void dm9000_set_io(struct board_i
static void dm9000_schedule_poll(board_info_t *db)
{
- schedule_delayed_work(&db->phy_poll, HZ * 2);
+ if (db->type == TYPE_DM9000E)
+ schedule_delayed_work(&db->phy_poll, HZ * 2);
}
/* Our watchdog timed out. Called by the networking layer */
@@ -516,6 +529,17 @@ dm9000_release_board(struct platform_dev
}
}
+static unsigned char dm9000_type_to_char(enum dm9000_type type)
+{
+ switch (type) {
+ case TYPE_DM9000E: return 'e';
+ case TYPE_DM9000A: return 'a';
+ case TYPE_DM9000B: return 'b';
+ }
+
+ return '?';
+}
+
#define res_size(_r) (((_r)->end - (_r)->start) + 1)
/*
@@ -665,6 +689,23 @@ dm9000_probe(struct platform_device *pde
goto out;
}
+ /* Identify what type of DM9000 we are working on */
+
+ id_val = ior(db, DM9000_CHIPR);
+ dev_dbg(db->dev, "dm9000 revision 0x%02x\n", id_val);
+
+ switch (id_val) {
+ case CHIPR_DM9000A:
+ db->type = TYPE_DM9000A;
+ break;
+ case CHIPR_DM9000B:
+ db->type = TYPE_DM9000B;
+ break;
+ default:
+ dev_dbg(db->dev, "ID %02x => defaulting to DM9000E\n", id_val);
+ db->type = TYPE_DM9000E;
+ }
+
/* from this point we assume that we have found a DM9000 */
/* driver system function */
@@ -715,8 +756,9 @@ dm9000_probe(struct platform_device *pde
if (ret == 0) {
DECLARE_MAC_BUF(mac);
- printk("%s: dm9000 at %p,%p IRQ %d MAC: %s (%s)\n",
- ndev->name, db->io_addr, db->io_data, ndev->irq,
+ printk("%s: dm9000%c at %p,%p IRQ %d MAC: %s (%s)\n",
+ ndev->name, dm9000_type_to_char(db->type),
+ db->io_addr, db->io_data, ndev->irq,
print_mac(mac, ndev->dev_addr), mac_src);
}
return 0;
@@ -778,6 +820,7 @@ static void
dm9000_init_dm9000(struct net_device *dev)
{
board_info_t *db = (board_info_t *) dev->priv;
+ unsigned int imr;
dm9000_dbg(db, 1, "entering %s\n", __func__);
@@ -804,8 +847,14 @@ dm9000_init_dm9000(struct net_device *de
/* Set address filter table */
dm9000_hash_table(dev);
+ imr = IMR_PAR | IMR_PTM | IMR_PRM;
+ if (db->type != TYPE_DM9000E)
+ imr |= IMR_LNKCHNG;
+
+ db->imr_all = imr;
+
/* Enable TX/RX interrupt mask */
- iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
+ iow(db, DM9000_IMR, imr);
/* Init Driver variable */
db->tx_pkt_cnt = 0;
@@ -962,8 +1011,15 @@ dm9000_interrupt(int irq, void *dev_id)
if (int_status & ISR_PTS)
dm9000_tx_done(dev, db);
+ if (db->type != TYPE_DM9000E) {
+ if (int_status & ISR_LNKCHNG) {
+ /* fire a link-change request */
+ schedule_delayed_work(&db->phy_poll, 1);
+ }
+ }
+
/* Re-enable interrupt mask */
- iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
+ iow(db, DM9000_IMR, db->imr_all);
/* Restore previous register address */
writeb(reg_save, db->io_addr);
Index: linux-2.6.26-rc6-quilt1/drivers/net/dm9000.h
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/net/dm9000.h 2008-06-15 22:50:45.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/net/dm9000.h 2008-06-15 22:52:19.000000000 +0100
@@ -45,6 +45,9 @@
#define DM9000_CHIPR 0x2C
#define DM9000_SMCR 0x2F
+#define CHIPR_DM9000A 0x19
+#define CHIPR_DM9000B 0x1B
+
#define DM9000_MRCMDX 0xF0
#define DM9000_MRCMD 0xF2
#define DM9000_MRRL 0xF4
@@ -131,5 +134,13 @@
#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */
#define DM9000_PKT_MAX 1536 /* Received packet max size */
+/* DM9000A / DM9000B definitions */
+
+#define IMR_LNKCHNG (1<<5)
+#define IMR_UNDERRUN (1<<4)
+
+#define ISR_LNKCHNG (1<<5)
+#define ISR_UNDERRUN (1<<4)
+
#endif /* _DM9000X_H_ */
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 3/9] DM9000: Cleanup source code
2008-06-15 23:26 [patch 0/9] DM9000 updates for 2.6.27 Ben Dooks
2008-06-15 23:26 ` [patch 1/9] DM9000: Remove the 2 resources probe scheme Ben Dooks
2008-06-15 23:26 ` [patch 2/9] DM9000: Add support for DM9000A and DM9000B chips Ben Dooks
@ 2008-06-15 23:26 ` Ben Dooks
2008-06-15 23:26 ` [patch 4/9] DM9000: Cleanup source code - remove forward declerations Ben Dooks
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-15 23:26 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik, Ben Dooks
[-- Attachment #1: simtec/simtec-drivers-net-dm9000-cleanups1.patch --]
[-- Type: text/plain, Size: 6797 bytes --]
Cleanup bits of the DM9000 driver to make the code
neater and easier to read. This is includes removing
some old definitions, re-indenting areas, etc.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Index: linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/net/dm9000.c 2008-06-15 22:52:31.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c 2008-06-15 23:14:39.000000000 +0100
@@ -44,9 +44,8 @@
#define DM9000_PHY 0x40 /* PHY address 0x01 */
-#define CARDNAME "dm9000"
-#define PFX CARDNAME ": "
-#define DRV_VERSION "1.30"
+#define CARDNAME "dm9000"
+#define DRV_VERSION "1.31"
#ifdef CONFIG_BLACKFIN
#define readsb insb
@@ -98,22 +97,23 @@ enum dm9000_type {
/* Structure/enum declaration ------------------------------- */
typedef struct board_info {
- void __iomem *io_addr; /* Register I/O base address */
- void __iomem *io_data; /* Data I/O address */
- u16 irq; /* IRQ */
-
- u16 tx_pkt_cnt;
- u16 queue_pkt_len;
- u16 queue_start_addr;
- u16 dbug_cnt;
- u8 io_mode; /* 0:word, 2:byte */
- u8 phy_addr;
- u8 imr_all;
- unsigned int flags;
- unsigned int in_suspend :1;
+ void __iomem *io_addr; /* Register I/O base address */
+ void __iomem *io_data; /* Data I/O address */
+ u16 irq; /* IRQ */
+
+ u16 tx_pkt_cnt;
+ u16 queue_pkt_len;
+ u16 queue_start_addr;
+ u16 dbug_cnt;
+ u8 io_mode; /* 0:word, 2:byte */
+ u8 phy_addr;
+ u8 imr_all;
+
+ unsigned int flags;
+ unsigned int in_suspend :1;
+ int debug_level;
enum dm9000_type type;
- int debug_level;
void (*inblk)(void __iomem *port, void *data, int length);
void (*outblk)(void __iomem *port, void *data, int length);
@@ -132,10 +132,10 @@ typedef struct board_info {
struct delayed_work phy_poll;
struct net_device *ndev;
- spinlock_t lock;
+ spinlock_t lock;
struct mii_if_info mii;
- u32 msg_enable;
+ u32 msg_enable;
} board_info_t;
/* debug code */
@@ -153,19 +153,16 @@ static inline board_info_t *to_dm9000_bo
}
/* function declaration ------------------------------------- */
-static int dm9000_probe(struct platform_device *);
static int dm9000_open(struct net_device *);
static int dm9000_start_xmit(struct sk_buff *, struct net_device *);
static int dm9000_stop(struct net_device *);
-static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
static void dm9000_init_dm9000(struct net_device *);
static irqreturn_t dm9000_interrupt(int, void *);
-static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg);
-static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
- int value);
+static int dm9000_phy_read(struct net_device *dev, int phy, int reg);
+static void dm9000_phy_write(struct net_device *dev, int phy, int reg, int v);
static void dm9000_read_eeprom(board_info_t *, int addr, u8 *to);
static void dm9000_write_eeprom(board_info_t *, int addr, u8 *dp);
@@ -505,12 +502,6 @@ dm9000_poll_work(struct work_struct *w)
static void
dm9000_release_board(struct platform_device *pdev, struct board_info *db)
{
- if (db->data_res == NULL) {
- if (db->addr_res != NULL)
- release_mem_region((unsigned long)db->io_addr, 4);
- return;
- }
-
/* unmap our resources */
iounmap(db->io_addr);
@@ -518,15 +509,11 @@ dm9000_release_board(struct platform_dev
/* release the resources */
- if (db->data_req != NULL) {
- release_resource(db->data_req);
- kfree(db->data_req);
- }
+ release_resource(db->data_req);
+ kfree(db->data_req);
- if (db->addr_req != NULL) {
- release_resource(db->addr_req);
- kfree(db->addr_req);
- }
+ release_resource(db->addr_req);
+ kfree(db->addr_req);
}
static unsigned char dm9000_type_to_char(enum dm9000_type type)
@@ -580,12 +567,6 @@ dm9000_probe(struct platform_device *pde
INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);
-
- if (pdev->num_resources < 2) {
- ret = -ENODEV;
- goto out;
- }
-
db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -671,7 +652,7 @@ dm9000_probe(struct platform_device *pde
dm9000_reset(db);
- /* try two times, DM9000 sometimes gets the first read wrong */
+ /* try multiple times, DM9000 sometimes gets the read wrong */
for (i = 0; i < 8; i++) {
id_val = ior(db, DM9000_VIDL);
id_val |= (u32)ior(db, DM9000_VIDH) << 8;
@@ -779,7 +760,7 @@ out:
static int
dm9000_open(struct net_device *dev)
{
- board_info_t *db = (board_info_t *) dev->priv;
+ board_info_t *db = dev->priv;
unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
if (netif_msg_ifup(db))
@@ -819,7 +800,7 @@ dm9000_open(struct net_device *dev)
static void
dm9000_init_dm9000(struct net_device *dev)
{
- board_info_t *db = (board_info_t *) dev->priv;
+ board_info_t *db = dev->priv;
unsigned int imr;
dm9000_dbg(db, 1, "entering %s\n", __func__);
@@ -870,7 +851,7 @@ static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
- board_info_t *db = (board_info_t *) dev->priv;
+ board_info_t *db = dev->priv;
dm9000_dbg(db, 3, "%s:\n", __func__);
@@ -913,7 +894,7 @@ dm9000_start_xmit(struct sk_buff *skb, s
static void
dm9000_shutdown(struct net_device *dev)
{
- board_info_t *db = (board_info_t *) dev->priv;
+ board_info_t *db = dev->priv;
/* RESET device */
dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
@@ -929,7 +910,7 @@ dm9000_shutdown(struct net_device *dev)
static int
dm9000_stop(struct net_device *ndev)
{
- board_info_t *db = (board_info_t *) ndev->priv;
+ board_info_t *db = ndev->priv;
if (netif_msg_ifdown(db))
dev_dbg(db->dev, "shutting down %s\n", ndev->name);
@@ -980,7 +961,7 @@ static irqreturn_t
dm9000_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- board_info_t *db = (board_info_t *) dev->priv;
+ board_info_t *db = dev->priv;
int int_status;
u8 reg_save;
@@ -1361,7 +1342,8 @@ dm9000_phy_read(struct net_device *dev,
* Write a word to phyxcer
*/
static void
-dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
+dm9000_phy_write(struct net_device *dev,
+ int phyaddr_unused, int reg, int value)
{
board_info_t *db = (board_info_t *) dev->priv;
unsigned long flags;
@@ -1470,7 +1452,7 @@ dm9000_init(void)
{
printk(KERN_INFO "%s Ethernet Driver, V%s\n", CARDNAME, DRV_VERSION);
- return platform_driver_register(&dm9000_driver); /* search board and register */
+ return platform_driver_register(&dm9000_driver);
}
static void __exit
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 4/9] DM9000: Cleanup source code - remove forward declerations
2008-06-15 23:26 [patch 0/9] DM9000 updates for 2.6.27 Ben Dooks
` (2 preceding siblings ...)
2008-06-15 23:26 ` [patch 3/9] DM9000: Cleanup source code Ben Dooks
@ 2008-06-15 23:26 ` Ben Dooks
2008-06-15 23:26 ` [patch 5/9] DM9000: Use NSR to determine link-status on internal PHY Ben Dooks
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-15 23:26 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik, Ben Dooks
[-- Attachment #1: simtec/simtec-drivers-net-dm9000-cleanups2.patch --]
[-- Type: text/plain, Size: 32590 bytes --]
Cleanup the source code by moving the code around to avoid
having to declare the functions before they are used.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Index: linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/net/dm9000.c 2008-06-15 23:15:39.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c 2008-06-15 23:28:03.000000000 +0100
@@ -152,23 +152,6 @@ static inline board_info_t *to_dm9000_bo
return dev->priv;
}
-/* function declaration ------------------------------------- */
-static int dm9000_open(struct net_device *);
-static int dm9000_start_xmit(struct sk_buff *, struct net_device *);
-static int dm9000_stop(struct net_device *);
-
-static void dm9000_init_dm9000(struct net_device *);
-
-static irqreturn_t dm9000_interrupt(int, void *);
-
-static int dm9000_phy_read(struct net_device *dev, int phy, int reg);
-static void dm9000_phy_write(struct net_device *dev, int phy, int reg, int v);
-
-static void dm9000_read_eeprom(board_info_t *, int addr, u8 *to);
-static void dm9000_write_eeprom(board_info_t *, int addr, u8 *dp);
-static void dm9000_rx(struct net_device *);
-static void dm9000_hash_table(struct net_device *);
-
/* DM9000 network board routine ---------------------------- */
static void
@@ -315,49 +298,129 @@ static void dm9000_schedule_poll(board_i
schedule_delayed_work(&db->phy_poll, HZ * 2);
}
-/* Our watchdog timed out. Called by the networking layer */
-static void dm9000_timeout(struct net_device *dev)
+static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+ board_info_t *dm = to_dm9000_board(dev);
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);
+}
+
+static unsigned int
+dm9000_read_locked(board_info_t *db, int reg)
{
- board_info_t *db = (board_info_t *) dev->priv;
- u8 reg_save;
unsigned long flags;
+ unsigned int ret;
- /* Save previous register address */
- reg_save = readb(db->io_addr);
- spin_lock_irqsave(&db->lock,flags);
+ spin_lock_irqsave(&db->lock, flags);
+ ret = ior(db, reg);
+ spin_unlock_irqrestore(&db->lock, flags);
- netif_stop_queue(dev);
- dm9000_reset(db);
- dm9000_init_dm9000(dev);
- /* We can accept TX packets again */
- dev->trans_start = jiffies;
- netif_wake_queue(dev);
+ return ret;
+}
- /* Restore previous register address */
- writeb(reg_save, db->io_addr);
- spin_unlock_irqrestore(&db->lock,flags);
+static int dm9000_wait_eeprom(board_info_t *db)
+{
+ unsigned int status;
+ int timeout = 8; /* wait max 8msec */
+
+ /* The DM9000 data sheets say we should be able to
+ * poll the ERRE bit in EPCR to wait for the EEPROM
+ * operation. From testing several chips, this bit
+ * does not seem to work.
+ *
+ * We attempt to use the bit, but fall back to the
+ * timeout (which is why we do not return an error
+ * on expiry) to say that the EEPROM operation has
+ * completed.
+ */
+
+ while (1) {
+ status = dm9000_read_locked(db, DM9000_EPCR);
+
+ if ((status & EPCR_ERRE) == 0)
+ break;
+
+ if (timeout-- < 0) {
+ dev_dbg(db->dev, "timeout waiting EEPROM\n");
+ break;
+ }
+ }
+
+ return 0;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
/*
- *Used by netconsole
+ * Read a word data from EEPROM
*/
-static void dm9000_poll_controller(struct net_device *dev)
+static void
+dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
{
- disable_irq(dev->irq);
- dm9000_interrupt(dev->irq,dev);
- enable_irq(dev->irq);
+ unsigned long flags;
+
+ if (db->flags & DM9000_PLATF_NO_EEPROM) {
+ to[0] = 0xff;
+ to[1] = 0xff;
+ return;
+ }
+
+ mutex_lock(&db->addr_lock);
+
+ spin_lock_irqsave(&db->lock, flags);
+
+ iow(db, DM9000_EPAR, offset);
+ iow(db, DM9000_EPCR, EPCR_ERPRR);
+
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ dm9000_wait_eeprom(db);
+
+ /* delay for at-least 150uS */
+ msleep(1);
+
+ spin_lock_irqsave(&db->lock, flags);
+
+ iow(db, DM9000_EPCR, 0x0);
+
+ to[0] = ior(db, DM9000_EPDRL);
+ to[1] = ior(db, DM9000_EPDRH);
+
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ mutex_unlock(&db->addr_lock);
}
-#endif
-static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+/*
+ * Write a word data to SROM
+ */
+static void
+dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
{
- board_info_t *dm = to_dm9000_board(dev);
+ unsigned long flags;
- if (!netif_running(dev))
- return -EINVAL;
+ if (db->flags & DM9000_PLATF_NO_EEPROM)
+ return;
- return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);
+ mutex_lock(&db->addr_lock);
+
+ spin_lock_irqsave(&db->lock, flags);
+ iow(db, DM9000_EPAR, offset);
+ iow(db, DM9000_EPDRH, data[1]);
+ iow(db, DM9000_EPDRL, data[0]);
+ iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ dm9000_wait_eeprom(db);
+
+ mdelay(1); /* wait at least 150uS to clear */
+
+ spin_lock_irqsave(&db->lock, flags);
+ iow(db, DM9000_EPCR, 0);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ mutex_unlock(&db->addr_lock);
}
/* ethtool ops */
@@ -527,294 +590,78 @@ static unsigned char dm9000_type_to_char
return '?';
}
-#define res_size(_r) (((_r)->end - (_r)->start) + 1)
-
/*
- * Search DM9000 board, allocate space and register it
+ * Set DM9000 multicast address
*/
-static int __devinit
-dm9000_probe(struct platform_device *pdev)
+static void
+dm9000_hash_table(struct net_device *dev)
{
- struct dm9000_plat_data *pdata = pdev->dev.platform_data;
- struct board_info *db; /* Point a board information structure */
- struct net_device *ndev;
- const unsigned char *mac_src;
- int ret = 0;
- int iosize;
- int i;
- u32 id_val;
-
- /* Init network device */
- ndev = alloc_etherdev(sizeof (struct board_info));
- if (!ndev) {
- dev_err(&pdev->dev, "could not allocate device.\n");
- return -ENOMEM;
- }
+ board_info_t *db = (board_info_t *) dev->priv;
+ struct dev_mc_list *mcptr = dev->mc_list;
+ int mc_cnt = dev->mc_count;
+ int i, oft;
+ u32 hash_val;
+ u16 hash_table[4];
+ u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
+ unsigned long flags;
- SET_NETDEV_DEV(ndev, &pdev->dev);
+ dm9000_dbg(db, 1, "entering %s\n", __func__);
- dev_dbg(&pdev->dev, "dm9000_probe()\n");
+ spin_lock_irqsave(&db->lock, flags);
- /* setup board info structure */
- db = (struct board_info *) ndev->priv;
- memset(db, 0, sizeof (*db));
+ for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
+ iow(db, oft, dev->dev_addr[i]);
- db->dev = &pdev->dev;
- db->ndev = ndev;
+ /* Clear Hash Table */
+ for (i = 0; i < 4; i++)
+ hash_table[i] = 0x0;
- spin_lock_init(&db->lock);
- mutex_init(&db->addr_lock);
+ /* broadcast address */
+ hash_table[3] = 0x8000;
- INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);
+ if (dev->flags & IFF_PROMISC)
+ rcr |= RCR_PRMSC;
- db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (dev->flags & IFF_ALLMULTI)
+ rcr |= RCR_ALL;
- if (db->addr_res == NULL || db->data_res == NULL ||
- db->irq_res == NULL) {
- dev_err(db->dev, "insufficient resources\n");
- ret = -ENOENT;
- goto out;
+ /* the multicast address in Hash Table : 64 bits */
+ for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
+ hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f;
+ hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
}
- iosize = res_size(db->addr_res);
- db->addr_req = request_mem_region(db->addr_res->start, iosize,
- pdev->name);
-
- if (db->addr_req == NULL) {
- dev_err(db->dev, "cannot claim address reg area\n");
- ret = -EIO;
- goto out;
+ /* Write the hash table to MAC MD table */
+ for (i = 0, oft = DM9000_MAR; i < 4; i++) {
+ iow(db, oft++, hash_table[i]);
+ iow(db, oft++, hash_table[i] >> 8);
}
- db->io_addr = ioremap(db->addr_res->start, iosize);
+ iow(db, DM9000_RCR, rcr);
+ spin_unlock_irqrestore(&db->lock, flags);
+}
- if (db->io_addr == NULL) {
- dev_err(db->dev, "failed to ioremap address reg\n");
- ret = -EINVAL;
- goto out;
- }
+/*
+ * Initilize dm9000 board
+ */
+static void
+dm9000_init_dm9000(struct net_device *dev)
+{
+ board_info_t *db = dev->priv;
+ unsigned int imr;
- iosize = res_size(db->data_res);
- db->data_req = request_mem_region(db->data_res->start, iosize,
- pdev->name);
+ dm9000_dbg(db, 1, "entering %s\n", __func__);
- if (db->data_req == NULL) {
- dev_err(db->dev, "cannot claim data reg area\n");
- ret = -EIO;
- goto out;
- }
+ /* I/O mode */
+ db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */
- db->io_data = ioremap(db->data_res->start, iosize);
+ /* GPIO0 on pre-activate PHY */
+ iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
+ iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */
+ iow(db, DM9000_GPR, 0); /* Enable PHY */
- if (db->io_data == NULL) {
- dev_err(db->dev,"failed to ioremap data reg\n");
- ret = -EINVAL;
- goto out;
- }
-
- /* fill in parameters for net-dev structure */
- ndev->base_addr = (unsigned long)db->io_addr;
- ndev->irq = db->irq_res->start;
-
- /* ensure at least we have a default set of IO routines */
- dm9000_set_io(db, iosize);
-
- /* check to see if anything is being over-ridden */
- if (pdata != NULL) {
- /* check to see if the driver wants to over-ride the
- * default IO width */
-
- if (pdata->flags & DM9000_PLATF_8BITONLY)
- dm9000_set_io(db, 1);
-
- if (pdata->flags & DM9000_PLATF_16BITONLY)
- dm9000_set_io(db, 2);
-
- if (pdata->flags & DM9000_PLATF_32BITONLY)
- dm9000_set_io(db, 4);
-
- /* check to see if there are any IO routine
- * over-rides */
-
- if (pdata->inblk != NULL)
- db->inblk = pdata->inblk;
-
- if (pdata->outblk != NULL)
- db->outblk = pdata->outblk;
-
- if (pdata->dumpblk != NULL)
- db->dumpblk = pdata->dumpblk;
-
- db->flags = pdata->flags;
- }
-
- dm9000_reset(db);
-
- /* try multiple times, DM9000 sometimes gets the read wrong */
- for (i = 0; i < 8; i++) {
- id_val = ior(db, DM9000_VIDL);
- id_val |= (u32)ior(db, DM9000_VIDH) << 8;
- id_val |= (u32)ior(db, DM9000_PIDL) << 16;
- id_val |= (u32)ior(db, DM9000_PIDH) << 24;
-
- if (id_val == DM9000_ID)
- break;
- dev_err(db->dev, "read wrong id 0x%08x\n", id_val);
- }
-
- if (id_val != DM9000_ID) {
- dev_err(db->dev, "wrong id: 0x%08x\n", id_val);
- ret = -ENODEV;
- goto out;
- }
-
- /* Identify what type of DM9000 we are working on */
-
- id_val = ior(db, DM9000_CHIPR);
- dev_dbg(db->dev, "dm9000 revision 0x%02x\n", id_val);
-
- switch (id_val) {
- case CHIPR_DM9000A:
- db->type = TYPE_DM9000A;
- break;
- case CHIPR_DM9000B:
- db->type = TYPE_DM9000B;
- break;
- default:
- dev_dbg(db->dev, "ID %02x => defaulting to DM9000E\n", id_val);
- db->type = TYPE_DM9000E;
- }
-
- /* from this point we assume that we have found a DM9000 */
-
- /* driver system function */
- ether_setup(ndev);
-
- ndev->open = &dm9000_open;
- ndev->hard_start_xmit = &dm9000_start_xmit;
- ndev->tx_timeout = &dm9000_timeout;
- ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
- ndev->stop = &dm9000_stop;
- ndev->set_multicast_list = &dm9000_hash_table;
- ndev->ethtool_ops = &dm9000_ethtool_ops;
- ndev->do_ioctl = &dm9000_ioctl;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
- ndev->poll_controller = &dm9000_poll_controller;
-#endif
-
- db->msg_enable = NETIF_MSG_LINK;
- db->mii.phy_id_mask = 0x1f;
- db->mii.reg_num_mask = 0x1f;
- db->mii.force_media = 0;
- db->mii.full_duplex = 0;
- db->mii.dev = ndev;
- db->mii.mdio_read = dm9000_phy_read;
- db->mii.mdio_write = dm9000_phy_write;
-
- mac_src = "eeprom";
-
- /* try reading the node address from the attached EEPROM */
- for (i = 0; i < 6; i += 2)
- dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);
-
- if (!is_valid_ether_addr(ndev->dev_addr)) {
- /* try reading from mac */
-
- mac_src = "chip";
- for (i = 0; i < 6; i++)
- ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
- }
-
- if (!is_valid_ether_addr(ndev->dev_addr))
- dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "
- "set using ifconfig\n", ndev->name);
-
- platform_set_drvdata(pdev, ndev);
- ret = register_netdev(ndev);
-
- if (ret == 0) {
- DECLARE_MAC_BUF(mac);
- printk("%s: dm9000%c at %p,%p IRQ %d MAC: %s (%s)\n",
- ndev->name, dm9000_type_to_char(db->type),
- db->io_addr, db->io_data, ndev->irq,
- print_mac(mac, ndev->dev_addr), mac_src);
- }
- return 0;
-
-out:
- dev_err(db->dev, "not found (%d).\n", ret);
-
- dm9000_release_board(pdev, db);
- free_netdev(ndev);
-
- return ret;
-}
-
-/*
- * Open the interface.
- * The interface is opened whenever "ifconfig" actives it.
- */
-static int
-dm9000_open(struct net_device *dev)
-{
- board_info_t *db = dev->priv;
- unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
-
- if (netif_msg_ifup(db))
- dev_dbg(db->dev, "enabling %s\n", dev->name);
-
- /* If there is no IRQ type specified, default to something that
- * may work, and tell the user that this is a problem */
-
- if (irqflags == IRQF_TRIGGER_NONE) {
- dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
- irqflags = DEFAULT_TRIGGER;
- }
-
- irqflags |= IRQF_SHARED;
-
- if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev))
- return -EAGAIN;
-
- /* Initialize DM9000 board */
- dm9000_reset(db);
- dm9000_init_dm9000(dev);
-
- /* Init driver variable */
- db->dbug_cnt = 0;
-
- mii_check_media(&db->mii, netif_msg_link(db), 1);
- netif_start_queue(dev);
-
- dm9000_schedule_poll(db);
-
- return 0;
-}
-
-/*
- * Initilize dm9000 board
- */
-static void
-dm9000_init_dm9000(struct net_device *dev)
-{
- board_info_t *db = dev->priv;
- unsigned int imr;
-
- dm9000_dbg(db, 1, "entering %s\n", __func__);
-
- /* I/O mode */
- db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */
-
- /* GPIO0 on pre-activate PHY */
- iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
- iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */
- iow(db, DM9000_GPR, 0); /* Enable PHY */
-
- if (db->flags & DM9000_PLATF_EXT_PHY)
- iow(db, DM9000_NCR, NCR_EXT_PHY);
+ if (db->flags & DM9000_PLATF_EXT_PHY)
+ iow(db, DM9000_NCR, NCR_EXT_PHY);
/* Program operating register */
iow(db, DM9000_TCR, 0); /* TX Polling clear */
@@ -843,6 +690,29 @@ dm9000_init_dm9000(struct net_device *de
dev->trans_start = 0;
}
+/* Our watchdog timed out. Called by the networking layer */
+static void dm9000_timeout(struct net_device *dev)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+ u8 reg_save;
+ unsigned long flags;
+
+ /* Save previous register address */
+ reg_save = readb(db->io_addr);
+ spin_lock_irqsave(&db->lock,flags);
+
+ netif_stop_queue(dev);
+ dm9000_reset(db);
+ dm9000_init_dm9000(dev);
+ /* We can accept TX packets again */
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+
+ /* Restore previous register address */
+ writeb(reg_save, db->io_addr);
+ spin_unlock_irqrestore(&db->lock,flags);
+}
+
/*
* Hardware start transmission.
* Send a packet to media from the upper layer.
@@ -891,60 +761,23 @@ dm9000_start_xmit(struct sk_buff *skb, s
return 0;
}
-static void
-dm9000_shutdown(struct net_device *dev)
-{
- board_info_t *db = dev->priv;
-
- /* RESET device */
- dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
- iow(db, DM9000_GPR, 0x01); /* Power-Down PHY */
- iow(db, DM9000_IMR, IMR_PAR); /* Disable all interrupt */
- iow(db, DM9000_RCR, 0x00); /* Disable RX */
-}
-
/*
- * Stop the interface.
- * The interface is stopped when it is brought.
+ * DM9000 interrupt handler
+ * receive the packet to upper layer, free the transmitted packet
*/
-static int
-dm9000_stop(struct net_device *ndev)
+
+static void
+dm9000_tx_done(struct net_device *dev, board_info_t * db)
{
- board_info_t *db = ndev->priv;
+ int tx_status = ior(db, DM9000_NSR); /* Got TX status */
- if (netif_msg_ifdown(db))
- dev_dbg(db->dev, "shutting down %s\n", ndev->name);
+ if (tx_status & (NSR_TX2END | NSR_TX1END)) {
+ /* One packet sent complete */
+ db->tx_pkt_cnt--;
+ dev->stats.tx_packets++;
- cancel_delayed_work_sync(&db->phy_poll);
-
- netif_stop_queue(ndev);
- netif_carrier_off(ndev);
-
- /* free interrupt */
- free_irq(ndev->irq, ndev);
-
- dm9000_shutdown(ndev);
-
- return 0;
-}
-
-/*
- * DM9000 interrupt handler
- * receive the packet to upper layer, free the transmitted packet
- */
-
-static void
-dm9000_tx_done(struct net_device *dev, board_info_t * db)
-{
- int tx_status = ior(db, DM9000_NSR); /* Got TX status */
-
- if (tx_status & (NSR_TX2END | NSR_TX1END)) {
- /* One packet sent complete */
- db->tx_pkt_cnt--;
- dev->stats.tx_packets++;
-
- if (netif_msg_tx_done(db))
- dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
+ if (netif_msg_tx_done(db))
+ dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
/* Queue packet check & send */
if (db->tx_pkt_cnt > 0) {
@@ -957,59 +790,6 @@ dm9000_tx_done(struct net_device *dev, b
}
}
-static irqreturn_t
-dm9000_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- board_info_t *db = dev->priv;
- int int_status;
- u8 reg_save;
-
- dm9000_dbg(db, 3, "entering %s\n", __func__);
-
- /* A real interrupt coming */
-
- spin_lock(&db->lock);
-
- /* Save previous register address */
- reg_save = readb(db->io_addr);
-
- /* Disable all interrupts */
- iow(db, DM9000_IMR, IMR_PAR);
-
- /* Got DM9000 interrupt status */
- int_status = ior(db, DM9000_ISR); /* Got ISR */
- iow(db, DM9000_ISR, int_status); /* Clear ISR status */
-
- if (netif_msg_intr(db))
- dev_dbg(db->dev, "interrupt status %02x\n", int_status);
-
- /* Received the coming packet */
- if (int_status & ISR_PRS)
- dm9000_rx(dev);
-
- /* Trnasmit Interrupt check */
- if (int_status & ISR_PTS)
- dm9000_tx_done(dev, db);
-
- if (db->type != TYPE_DM9000E) {
- if (int_status & ISR_LNKCHNG) {
- /* fire a link-change request */
- schedule_delayed_work(&db->phy_poll, 1);
- }
- }
-
- /* Re-enable interrupt mask */
- iow(db, DM9000_IMR, db->imr_all);
-
- /* Restore previous register address */
- writeb(reg_save, db->io_addr);
-
- spin_unlock(&db->lock);
-
- return IRQ_HANDLED;
-}
-
struct dm9000_rxhdr {
u8 RxPktReady;
u8 RxStatus;
@@ -1113,205 +893,144 @@ dm9000_rx(struct net_device *dev)
} while (rxbyte == DM9000_PKT_RDY);
}
-static unsigned int
-dm9000_read_locked(board_info_t *db, int reg)
+static irqreturn_t
+dm9000_interrupt(int irq, void *dev_id)
{
- unsigned long flags;
- unsigned int ret;
+ struct net_device *dev = dev_id;
+ board_info_t *db = dev->priv;
+ int int_status;
+ u8 reg_save;
- spin_lock_irqsave(&db->lock, flags);
- ret = ior(db, reg);
- spin_unlock_irqrestore(&db->lock, flags);
+ dm9000_dbg(db, 3, "entering %s\n", __func__);
- return ret;
-}
+ /* A real interrupt coming */
-static int dm9000_wait_eeprom(board_info_t *db)
-{
- unsigned int status;
- int timeout = 8; /* wait max 8msec */
+ spin_lock(&db->lock);
- /* The DM9000 data sheets say we should be able to
- * poll the ERRE bit in EPCR to wait for the EEPROM
- * operation. From testing several chips, this bit
- * does not seem to work.
- *
- * We attempt to use the bit, but fall back to the
- * timeout (which is why we do not return an error
- * on expiry) to say that the EEPROM operation has
- * completed.
- */
+ /* Save previous register address */
+ reg_save = readb(db->io_addr);
- while (1) {
- status = dm9000_read_locked(db, DM9000_EPCR);
+ /* Disable all interrupts */
+ iow(db, DM9000_IMR, IMR_PAR);
- if ((status & EPCR_ERRE) == 0)
- break;
+ /* Got DM9000 interrupt status */
+ int_status = ior(db, DM9000_ISR); /* Got ISR */
+ iow(db, DM9000_ISR, int_status); /* Clear ISR status */
- if (timeout-- < 0) {
- dev_dbg(db->dev, "timeout waiting EEPROM\n");
- break;
+ if (netif_msg_intr(db))
+ dev_dbg(db->dev, "interrupt status %02x\n", int_status);
+
+ /* Received the coming packet */
+ if (int_status & ISR_PRS)
+ dm9000_rx(dev);
+
+ /* Trnasmit Interrupt check */
+ if (int_status & ISR_PTS)
+ dm9000_tx_done(dev, db);
+
+ if (db->type != TYPE_DM9000E) {
+ if (int_status & ISR_LNKCHNG) {
+ /* fire a link-change request */
+ schedule_delayed_work(&db->phy_poll, 1);
}
}
- return 0;
+ /* Re-enable interrupt mask */
+ iow(db, DM9000_IMR, db->imr_all);
+
+ /* Restore previous register address */
+ writeb(reg_save, db->io_addr);
+
+ spin_unlock(&db->lock);
+
+ return IRQ_HANDLED;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
/*
- * Read a word data from EEPROM
+ *Used by netconsole
*/
-static void
-dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
+static void dm9000_poll_controller(struct net_device *dev)
{
- unsigned long flags;
-
- if (db->flags & DM9000_PLATF_NO_EEPROM) {
- to[0] = 0xff;
- to[1] = 0xff;
- return;
- }
-
- mutex_lock(&db->addr_lock);
+ disable_irq(dev->irq);
+ dm9000_interrupt(dev->irq,dev);
+ enable_irq(dev->irq);
+}
+#endif
- spin_lock_irqsave(&db->lock, flags);
+/*
+ * Open the interface.
+ * The interface is opened whenever "ifconfig" actives it.
+ */
+static int
+dm9000_open(struct net_device *dev)
+{
+ board_info_t *db = dev->priv;
+ unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
- iow(db, DM9000_EPAR, offset);
- iow(db, DM9000_EPCR, EPCR_ERPRR);
+ if (netif_msg_ifup(db))
+ dev_dbg(db->dev, "enabling %s\n", dev->name);
- spin_unlock_irqrestore(&db->lock, flags);
+ /* If there is no IRQ type specified, default to something that
+ * may work, and tell the user that this is a problem */
- dm9000_wait_eeprom(db);
+ if (irqflags == IRQF_TRIGGER_NONE) {
+ dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
+ irqflags = DEFAULT_TRIGGER;
+ }
+
+ irqflags |= IRQF_SHARED;
- /* delay for at-least 150uS */
- msleep(1);
+ if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev))
+ return -EAGAIN;
- spin_lock_irqsave(&db->lock, flags);
+ /* Initialize DM9000 board */
+ dm9000_reset(db);
+ dm9000_init_dm9000(dev);
- iow(db, DM9000_EPCR, 0x0);
+ /* Init driver variable */
+ db->dbug_cnt = 0;
- to[0] = ior(db, DM9000_EPDRL);
- to[1] = ior(db, DM9000_EPDRH);
+ mii_check_media(&db->mii, netif_msg_link(db), 1);
+ netif_start_queue(dev);
+
+ dm9000_schedule_poll(db);
- spin_unlock_irqrestore(&db->lock, flags);
+ return 0;
+}
- mutex_unlock(&db->addr_lock);
+/*
+ * 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);
}
/*
- * Write a word data to SROM
+ * Read a word from phyxcer
*/
-static void
-dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
+static int
+dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
{
+ board_info_t *db = (board_info_t *) dev->priv;
unsigned long flags;
-
- if (db->flags & DM9000_PLATF_NO_EEPROM)
- return;
+ unsigned int reg_save;
+ int ret;
mutex_lock(&db->addr_lock);
- spin_lock_irqsave(&db->lock, flags);
- iow(db, DM9000_EPAR, offset);
- iow(db, DM9000_EPDRH, data[1]);
- iow(db, DM9000_EPDRL, data[0]);
- iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
- spin_unlock_irqrestore(&db->lock, flags);
+ spin_lock_irqsave(&db->lock,flags);
- dm9000_wait_eeprom(db);
+ /* Save previous register address */
+ reg_save = readb(db->io_addr);
- mdelay(1); /* wait at least 150uS to clear */
-
- spin_lock_irqsave(&db->lock, flags);
- iow(db, DM9000_EPCR, 0);
- spin_unlock_irqrestore(&db->lock, flags);
-
- mutex_unlock(&db->addr_lock);
-}
-
-/*
- * Set DM9000 multicast address
- */
-static void
-dm9000_hash_table(struct net_device *dev)
-{
- board_info_t *db = (board_info_t *) dev->priv;
- struct dev_mc_list *mcptr = dev->mc_list;
- int mc_cnt = dev->mc_count;
- int i, oft;
- u32 hash_val;
- u16 hash_table[4];
- u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
- unsigned long flags;
-
- dm9000_dbg(db, 1, "entering %s\n", __func__);
-
- spin_lock_irqsave(&db->lock, flags);
-
- for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
- iow(db, oft, dev->dev_addr[i]);
-
- /* Clear Hash Table */
- for (i = 0; i < 4; i++)
- hash_table[i] = 0x0;
-
- /* broadcast address */
- hash_table[3] = 0x8000;
-
- if (dev->flags & IFF_PROMISC)
- rcr |= RCR_PRMSC;
-
- if (dev->flags & IFF_ALLMULTI)
- rcr |= RCR_ALL;
-
- /* the multicast address in Hash Table : 64 bits */
- for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
- hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f;
- hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
- }
-
- /* Write the hash table to MAC MD table */
- for (i = 0, oft = DM9000_MAR; i < 4; i++) {
- iow(db, oft++, hash_table[i]);
- iow(db, oft++, hash_table[i] >> 8);
- }
-
- iow(db, DM9000_RCR, rcr);
- spin_unlock_irqrestore(&db->lock, flags);
-}
-
-
-/*
- * 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 = (board_info_t *) dev->priv;
- 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);
+ /* Fill the phyxcer register into REG_0C */
+ iow(db, DM9000_EPAR, DM9000_PHY | reg);
iow(db, DM9000_EPCR, 0xc); /* Issue phyxcer read command */
@@ -1383,6 +1102,269 @@ dm9000_phy_write(struct net_device *dev,
mutex_unlock(&db->addr_lock);
}
+static void
+dm9000_shutdown(struct net_device *dev)
+{
+ board_info_t *db = dev->priv;
+
+ /* RESET device */
+ dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
+ iow(db, DM9000_GPR, 0x01); /* Power-Down PHY */
+ iow(db, DM9000_IMR, IMR_PAR); /* Disable all interrupt */
+ iow(db, DM9000_RCR, 0x00); /* Disable RX */
+}
+
+/*
+ * Stop the interface.
+ * The interface is stopped when it is brought.
+ */
+static int
+dm9000_stop(struct net_device *ndev)
+{
+ board_info_t *db = ndev->priv;
+
+ if (netif_msg_ifdown(db))
+ dev_dbg(db->dev, "shutting down %s\n", ndev->name);
+
+ cancel_delayed_work_sync(&db->phy_poll);
+
+ netif_stop_queue(ndev);
+ netif_carrier_off(ndev);
+
+ /* free interrupt */
+ free_irq(ndev->irq, ndev);
+
+ dm9000_shutdown(ndev);
+
+ return 0;
+}
+
+#define res_size(_r) (((_r)->end - (_r)->start) + 1)
+
+/*
+ * Search DM9000 board, allocate space and register it
+ */
+static int __devinit
+dm9000_probe(struct platform_device *pdev)
+{
+ struct dm9000_plat_data *pdata = pdev->dev.platform_data;
+ struct board_info *db; /* Point a board information structure */
+ struct net_device *ndev;
+ const unsigned char *mac_src;
+ int ret = 0;
+ int iosize;
+ int i;
+ u32 id_val;
+
+ /* Init network device */
+ ndev = alloc_etherdev(sizeof (struct board_info));
+ if (!ndev) {
+ dev_err(&pdev->dev, "could not allocate device.\n");
+ return -ENOMEM;
+ }
+
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
+ dev_dbg(&pdev->dev, "dm9000_probe()\n");
+
+ /* setup board info structure */
+ db = (struct board_info *) ndev->priv;
+ memset(db, 0, sizeof (*db));
+
+ db->dev = &pdev->dev;
+ db->ndev = ndev;
+
+ spin_lock_init(&db->lock);
+ mutex_init(&db->addr_lock);
+
+ INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);
+
+ db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (db->addr_res == NULL || db->data_res == NULL ||
+ db->irq_res == NULL) {
+ dev_err(db->dev, "insufficient resources\n");
+ ret = -ENOENT;
+ goto out;
+ }
+
+ iosize = res_size(db->addr_res);
+ db->addr_req = request_mem_region(db->addr_res->start, iosize,
+ pdev->name);
+
+ if (db->addr_req == NULL) {
+ dev_err(db->dev, "cannot claim address reg area\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ db->io_addr = ioremap(db->addr_res->start, iosize);
+
+ if (db->io_addr == NULL) {
+ dev_err(db->dev, "failed to ioremap address reg\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ iosize = res_size(db->data_res);
+ db->data_req = request_mem_region(db->data_res->start, iosize,
+ pdev->name);
+
+ if (db->data_req == NULL) {
+ dev_err(db->dev, "cannot claim data reg area\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ db->io_data = ioremap(db->data_res->start, iosize);
+
+ if (db->io_data == NULL) {
+ dev_err(db->dev,"failed to ioremap data reg\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* fill in parameters for net-dev structure */
+ ndev->base_addr = (unsigned long)db->io_addr;
+ ndev->irq = db->irq_res->start;
+
+ /* ensure at least we have a default set of IO routines */
+ dm9000_set_io(db, iosize);
+
+ /* check to see if anything is being over-ridden */
+ if (pdata != NULL) {
+ /* check to see if the driver wants to over-ride the
+ * default IO width */
+
+ if (pdata->flags & DM9000_PLATF_8BITONLY)
+ dm9000_set_io(db, 1);
+
+ if (pdata->flags & DM9000_PLATF_16BITONLY)
+ dm9000_set_io(db, 2);
+
+ if (pdata->flags & DM9000_PLATF_32BITONLY)
+ dm9000_set_io(db, 4);
+
+ /* check to see if there are any IO routine
+ * over-rides */
+
+ if (pdata->inblk != NULL)
+ db->inblk = pdata->inblk;
+
+ if (pdata->outblk != NULL)
+ db->outblk = pdata->outblk;
+
+ if (pdata->dumpblk != NULL)
+ db->dumpblk = pdata->dumpblk;
+
+ db->flags = pdata->flags;
+ }
+
+ dm9000_reset(db);
+
+ /* try multiple times, DM9000 sometimes gets the read wrong */
+ for (i = 0; i < 8; i++) {
+ id_val = ior(db, DM9000_VIDL);
+ id_val |= (u32)ior(db, DM9000_VIDH) << 8;
+ id_val |= (u32)ior(db, DM9000_PIDL) << 16;
+ id_val |= (u32)ior(db, DM9000_PIDH) << 24;
+
+ if (id_val == DM9000_ID)
+ break;
+ dev_err(db->dev, "read wrong id 0x%08x\n", id_val);
+ }
+
+ if (id_val != DM9000_ID) {
+ dev_err(db->dev, "wrong id: 0x%08x\n", id_val);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ /* Identify what type of DM9000 we are working on */
+
+ id_val = ior(db, DM9000_CHIPR);
+ dev_dbg(db->dev, "dm9000 revision 0x%02x\n", id_val);
+
+ switch (id_val) {
+ case CHIPR_DM9000A:
+ db->type = TYPE_DM9000A;
+ break;
+ case CHIPR_DM9000B:
+ db->type = TYPE_DM9000B;
+ break;
+ default:
+ dev_dbg(db->dev, "ID %02x => defaulting to DM9000E\n", id_val);
+ db->type = TYPE_DM9000E;
+ }
+
+ /* from this point we assume that we have found a DM9000 */
+
+ /* driver system function */
+ ether_setup(ndev);
+
+ ndev->open = &dm9000_open;
+ ndev->hard_start_xmit = &dm9000_start_xmit;
+ ndev->tx_timeout = &dm9000_timeout;
+ ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
+ ndev->stop = &dm9000_stop;
+ ndev->set_multicast_list = &dm9000_hash_table;
+ ndev->ethtool_ops = &dm9000_ethtool_ops;
+ ndev->do_ioctl = &dm9000_ioctl;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ ndev->poll_controller = &dm9000_poll_controller;
+#endif
+
+ db->msg_enable = NETIF_MSG_LINK;
+ db->mii.phy_id_mask = 0x1f;
+ db->mii.reg_num_mask = 0x1f;
+ db->mii.force_media = 0;
+ db->mii.full_duplex = 0;
+ db->mii.dev = ndev;
+ db->mii.mdio_read = dm9000_phy_read;
+ db->mii.mdio_write = dm9000_phy_write;
+
+ mac_src = "eeprom";
+
+ /* try reading the node address from the attached EEPROM */
+ for (i = 0; i < 6; i += 2)
+ dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);
+
+ if (!is_valid_ether_addr(ndev->dev_addr)) {
+ /* try reading from mac */
+
+ mac_src = "chip";
+ for (i = 0; i < 6; i++)
+ ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
+ }
+
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "
+ "set using ifconfig\n", ndev->name);
+
+ platform_set_drvdata(pdev, ndev);
+ ret = register_netdev(ndev);
+
+ if (ret == 0) {
+ DECLARE_MAC_BUF(mac);
+ printk("%s: dm9000%c at %p,%p IRQ %d MAC: %s (%s)\n",
+ ndev->name, dm9000_type_to_char(db->type),
+ db->io_addr, db->io_data, ndev->irq,
+ print_mac(mac, ndev->dev_addr), mac_src);
+ }
+ return 0;
+
+out:
+ dev_err(db->dev, "not found (%d).\n", ret);
+
+ dm9000_release_board(pdev, db);
+ free_netdev(ndev);
+
+ return ret;
+}
+
static int
dm9000_drv_suspend(struct platform_device *dev, pm_message_t state)
{
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 5/9] DM9000: Use NSR to determine link-status on internal PHY
2008-06-15 23:26 [patch 0/9] DM9000 updates for 2.6.27 Ben Dooks
` (3 preceding siblings ...)
2008-06-15 23:26 ` [patch 4/9] DM9000: Cleanup source code - remove forward declerations Ben Dooks
@ 2008-06-15 23:26 ` Ben Dooks
2008-06-15 23:26 ` [patch 6/9] DM9000: Allow the use of the NSR register to get link status Ben Dooks
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-15 23:26 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik, Ben Dooks
[-- Attachment #1: simtec/simtec-drivers-net-dm9000-linkstatus1.patch --]
[-- Type: text/plain, Size: 1055 bytes --]
The DM9000_NSR register contains a copy of the internal PHY's
link status which we can use to determine if the link is up
or down. This eliminates the more costly (and sleeping) PHY
read when using the DM9000's own PHY.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Index: linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/net/dm9000.c 2008-06-15 23:31:41.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c 2008-06-15 23:38:55.000000000 +0100
@@ -473,7 +473,14 @@ static int dm9000_nway_reset(struct net_
static u32 dm9000_get_link(struct net_device *dev)
{
board_info_t *dm = to_dm9000_board(dev);
- return mii_link_ok(&dm->mii);
+ u32 ret;
+
+ if (dm->flags & DM9000_PLATF_EXT_PHY)
+ ret = mii_link_ok(&dm->mii);
+ else
+ ret = dm9000_read_locked(dm, DM9000_NSR) & NSR_LINKST ? 1 : 0;
+
+ return ret;
}
#define DM_EEPROM_MAGIC (0x444D394B)
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 6/9] DM9000: Allow the use of the NSR register to get link status.
2008-06-15 23:26 [patch 0/9] DM9000 updates for 2.6.27 Ben Dooks
` (4 preceding siblings ...)
2008-06-15 23:26 ` [patch 5/9] DM9000: Use NSR to determine link-status on internal PHY Ben Dooks
@ 2008-06-15 23:26 ` Ben Dooks
2008-06-16 12:51 ` Ben Dooks
2008-06-15 23:27 ` [patch 7/9] DM9000: Add missing msleep() in EEPROM wait code Ben Dooks
` (2 subsequent siblings)
8 siblings, 1 reply; 11+ messages in thread
From: Ben Dooks @ 2008-06-15 23:26 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik, Ben Dooks
[-- Attachment #1: simtec/simtec-drivers-net-dm9000-linkstatus2.patch --]
[-- Type: text/plain, Size: 2709 bytes --]
The DM9000's internal PHY reports a copy of the link status
in the NSR register of the chip. Reading the status when
polling for link status is faster as it eliminates the need
to sleep, but does not print as much information.
Add an platform flag to force this behaviour, and a Kconfig
option to allow it to be forced to the faster method always.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Index: linux-2.6.26-rc6-quilt1/drivers/net/Kconfig
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/net/Kconfig 2008-06-15 23:43:43.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/net/Kconfig 2008-06-15 23:45:20.000000000 +0100
@@ -926,6 +926,15 @@ config DM9000
To compile this driver as a module, choose M here. The module
will be called dm9000.
+config DM9000_FORCE_SIMPLE_PHY_POLL
+ bool "Force simple NSR based PHY polling"
+ depends on DM9000
+ ---help---
+ This configuration forces the DM9000 to use the NSR's LinkStatus
+ bit to determine if the link is up or down instead of the more
+ costly MII PHY reads. Note, this will not work if the chip is
+ operating with an external PHY.
+
config ENC28J60
tristate "ENC28J60 support"
depends on EXPERIMENTAL && SPI && NET_ETHERNET
Index: linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/net/dm9000.c 2008-06-15 23:41:24.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c 2008-06-15 23:43:18.000000000 +0100
@@ -558,7 +558,11 @@ dm9000_poll_work(struct work_struct *w)
struct delayed_work *dw = container_of(w, struct delayed_work, work);
board_info_t *db = container_of(dw, board_info_t, phy_poll);
- mii_check_media(&db->mii, netif_msg_link(db), 0);
+ if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
+ !(db->flags & DM9000_PLATF_EXT_PHY)) {
+
+ } else
+ mii_check_media(&db->mii, netif_msg_link(db), 0);
if (netif_running(db->ndev))
dm9000_schedule_poll(db);
Index: linux-2.6.26-rc6-quilt1/include/linux/dm9000.h
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/include/linux/dm9000.h 2008-06-15 23:42:01.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/include/linux/dm9000.h 2008-06-15 23:42:47.000000000 +0100
@@ -21,6 +21,7 @@
#define DM9000_PLATF_32BITONLY (0x0004)
#define DM9000_PLATF_EXT_PHY (0x0008)
#define DM9000_PLATF_NO_EEPROM (0x0010)
+#define DM9000_PLATF_SIMPLE_PHY (0x0020) /* Use NSR to find LinkStatus */
/* platfrom data for platfrom device structure's platfrom_data field */
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 7/9] DM9000: Add missing msleep() in EEPROM wait code.
2008-06-15 23:26 [patch 0/9] DM9000 updates for 2.6.27 Ben Dooks
` (5 preceding siblings ...)
2008-06-15 23:26 ` [patch 6/9] DM9000: Allow the use of the NSR register to get link status Ben Dooks
@ 2008-06-15 23:27 ` Ben Dooks
2008-06-15 23:27 ` [patch 8/9] DM9000: Re-unit menuconfig entries for DM9000 driver Ben Dooks
2008-06-15 23:27 ` [patch 9/9] DM9000: Show Mbps on link change if using simple polling Ben Dooks
8 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-15 23:27 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik, Ben Dooks
[-- Attachment #1: simtec/simtec-drivers-net-dm9000-eeprom-delay.patch --]
[-- Type: text/plain, Size: 729 bytes --]
The msleep() call in the code that checks for the
EEPROM controller's busy status was missing.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Index: linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/net/dm9000.c 2008-06-16 00:07:15.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c 2008-06-16 00:07:44.000000000 +0100
@@ -343,6 +343,8 @@ static int dm9000_wait_eeprom(board_info
if ((status & EPCR_ERRE) == 0)
break;
+ msleep(1);
+
if (timeout-- < 0) {
dev_dbg(db->dev, "timeout waiting EEPROM\n");
break;
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 8/9] DM9000: Re-unit menuconfig entries for DM9000 driver
2008-06-15 23:26 [patch 0/9] DM9000 updates for 2.6.27 Ben Dooks
` (6 preceding siblings ...)
2008-06-15 23:27 ` [patch 7/9] DM9000: Add missing msleep() in EEPROM wait code Ben Dooks
@ 2008-06-15 23:27 ` Ben Dooks
2008-06-15 23:27 ` [patch 9/9] DM9000: Show Mbps on link change if using simple polling Ben Dooks
8 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-15 23:27 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik, Ben Dooks
[-- Attachment #1: simtec/simtec-drivers-net-dm9000-menuconfig.patch --]
[-- Type: text/plain, Size: 1345 bytes --]
The ENC28J60 driver ended up adding itself inbetween the
two DM9000 Kconfig entries, so re-unite the two together.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Index: linux-2.6.26-rc6-quilt1/drivers/net/Kconfig
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/net/Kconfig 2008-06-16 00:12:47.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/net/Kconfig 2008-06-16 00:13:05.000000000 +0100
@@ -926,6 +926,14 @@ config DM9000
To compile this driver as a module, choose M here. The module
will be called dm9000.
+config DM9000_DEBUGLEVEL
+ int "DM9000 maximum debug level"
+ depends on DM9000
+ default 4
+ help
+ The maximum level of debugging code compiled into the DM9000
+ driver.
+
config DM9000_FORCE_SIMPLE_PHY_POLL
bool "Force simple NSR based PHY polling"
depends on DM9000
@@ -952,14 +960,6 @@ config ENC28J60_WRITEVERIFY
Enable the verify after the buffer write useful for debugging purpose.
If unsure, say N.
-config DM9000_DEBUGLEVEL
- int "DM9000 maximum debug level"
- depends on DM9000
- default 4
- help
- The maximum level of debugging code compiled into the DM9000
- driver.
-
config SMC911X
tristate "SMSC LAN911[5678] support"
select CRC32
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 9/9] DM9000: Show Mbps on link change if using simple polling
2008-06-15 23:26 [patch 0/9] DM9000 updates for 2.6.27 Ben Dooks
` (7 preceding siblings ...)
2008-06-15 23:27 ` [patch 8/9] DM9000: Re-unit menuconfig entries for DM9000 driver Ben Dooks
@ 2008-06-15 23:27 ` Ben Dooks
8 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-15 23:27 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik, Ben Dooks
[-- Attachment #1: simtec/simtec-drivers-net-dm9000-show-mbits.patch --]
[-- Type: text/plain, Size: 991 bytes --]
Show the 10/100Mbps status on link status change if using
the simpler polling code.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Index: linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/net/dm9000.c 2008-06-16 00:18:38.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/net/dm9000.c 2008-06-16 00:22:16.000000000 +0100
@@ -577,10 +577,11 @@ dm9000_poll_work(struct work_struct *w)
if (old_carrier != new_carrier) {
if (netif_msg_link(db))
dev_info(db->dev,
- "%s: link changed from %s to %s\n",
+ "%s: link changed from %s to %s, %dMbps\n",
ndev->name,
dm9000_conv_carrier(old_carrier),
- dm9000_conv_carrier(new_carrier));
+ dm9000_conv_carrier(new_carrier),
+ (status & NSR_SPEED) ? 10 : 100);
if (!new_carrier)
netif_carrier_off(ndev);
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch 6/9] DM9000: Allow the use of the NSR register to get link status.
2008-06-15 23:26 ` [patch 6/9] DM9000: Allow the use of the NSR register to get link status Ben Dooks
@ 2008-06-16 12:51 ` Ben Dooks
0 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-16 12:51 UTC (permalink / raw)
To: Ben Dooks; +Cc: netdev, Jeff Garzik
On Mon, Jun 16, 2008 at 12:26:59AM +0100, Ben Dooks wrote:
> The DM9000's internal PHY reports a copy of the link status
> in the NSR register of the chip. Reading the status when
> polling for link status is faster as it eliminates the need
> to sleep, but does not print as much information.
>
> Add an platform flag to force this behaviour, and a Kconfig
> option to allow it to be forced to the faster method always.
>
> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Argh, this didn't get refreshed before emailing the quilt, will
fix and re-send with the blackfin updates
--
Ben (ben@fluff.org, http://www.fluff.org/)
'a smiley only costs 4 bytes'
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2008-06-16 12:51 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-15 23:26 [patch 0/9] DM9000 updates for 2.6.27 Ben Dooks
2008-06-15 23:26 ` [patch 1/9] DM9000: Remove the 2 resources probe scheme Ben Dooks
2008-06-15 23:26 ` [patch 2/9] DM9000: Add support for DM9000A and DM9000B chips Ben Dooks
2008-06-15 23:26 ` [patch 3/9] DM9000: Cleanup source code Ben Dooks
2008-06-15 23:26 ` [patch 4/9] DM9000: Cleanup source code - remove forward declerations Ben Dooks
2008-06-15 23:26 ` [patch 5/9] DM9000: Use NSR to determine link-status on internal PHY Ben Dooks
2008-06-15 23:26 ` [patch 6/9] DM9000: Allow the use of the NSR register to get link status Ben Dooks
2008-06-16 12:51 ` Ben Dooks
2008-06-15 23:27 ` [patch 7/9] DM9000: Add missing msleep() in EEPROM wait code Ben Dooks
2008-06-15 23:27 ` [patch 8/9] DM9000: Re-unit menuconfig entries for DM9000 driver Ben Dooks
2008-06-15 23:27 ` [patch 9/9] DM9000: Show Mbps on link change if using simple polling Ben Dooks
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).