aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-06-24 17:15:59 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-06-24 22:57:16 -0400
commit6d406b3c76b369a7b043470719761aa6ee1a38d1 (patch)
tree06eb1d946e37d097c96d059cd7871611fbabd98c
parentda3854fc9f80c0240ba7cadd2aebf036683ff21b (diff)
DM9000: Add support for DM9000A and DM9000B chips
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> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/net/dm9000.c66
-rw-r--r--drivers/net/dm9000.h11
2 files changed, 72 insertions, 5 deletions
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index b6d4b8e1d9e2..73270d93ae38 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -85,6 +85,16 @@ MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
85 * these two devices. 85 * these two devices.
86 */ 86 */
87 87
88/* The driver supports the original DM9000E, and now the two newer
89 * devices, DM9000A and DM9000B.
90 */
91
92enum dm9000_type {
93 TYPE_DM9000E, /* original DM9000 */
94 TYPE_DM9000A,
95 TYPE_DM9000B
96};
97
88/* Structure/enum declaration ------------------------------- */ 98/* Structure/enum declaration ------------------------------- */
89typedef struct board_info { 99typedef struct board_info {
90 100
@@ -98,9 +108,11 @@ typedef struct board_info {
98 u16 dbug_cnt; 108 u16 dbug_cnt;
99 u8 io_mode; /* 0:word, 2:byte */ 109 u8 io_mode; /* 0:word, 2:byte */
100 u8 phy_addr; 110 u8 phy_addr;
111 u8 imr_all;
101 unsigned int flags; 112 unsigned int flags;
102 unsigned int in_suspend :1; 113 unsigned int in_suspend :1;
103 114
115 enum dm9000_type type;
104 int debug_level; 116 int debug_level;
105 117
106 void (*inblk)(void __iomem *port, void *data, int length); 118 void (*inblk)(void __iomem *port, void *data, int length);
@@ -302,7 +314,8 @@ static void dm9000_set_io(struct board_info *db, int byte_width)
302 314
303static void dm9000_schedule_poll(board_info_t *db) 315static void dm9000_schedule_poll(board_info_t *db)
304{ 316{
305 schedule_delayed_work(&db->phy_poll, HZ * 2); 317 if (db->type == TYPE_DM9000E)
318 schedule_delayed_work(&db->phy_poll, HZ * 2);
306} 319}
307 320
308/* Our watchdog timed out. Called by the networking layer */ 321/* Our watchdog timed out. Called by the networking layer */
@@ -516,6 +529,17 @@ dm9000_release_board(struct platform_device *pdev, struct board_info *db)
516 } 529 }
517} 530}
518 531
532static unsigned char dm9000_type_to_char(enum dm9000_type type)
533{
534 switch (type) {
535 case TYPE_DM9000E: return 'e';
536 case TYPE_DM9000A: return 'a';
537 case TYPE_DM9000B: return 'b';
538 }
539
540 return '?';
541}
542
519#define res_size(_r) (((_r)->end - (_r)->start) + 1) 543#define res_size(_r) (((_r)->end - (_r)->start) + 1)
520 544
521/* 545/*
@@ -665,6 +689,23 @@ dm9000_probe(struct platform_device *pdev)
665 goto out; 689 goto out;
666 } 690 }
667 691
692 /* Identify what type of DM9000 we are working on */
693
694 id_val = ior(db, DM9000_CHIPR);
695 dev_dbg(db->dev, "dm9000 revision 0x%02x\n", id_val);
696
697 switch (id_val) {
698 case CHIPR_DM9000A:
699 db->type = TYPE_DM9000A;
700 break;
701 case CHIPR_DM9000B:
702 db->type = TYPE_DM9000B;
703 break;
704 default:
705 dev_dbg(db->dev, "ID %02x => defaulting to DM9000E\n", id_val);
706 db->type = TYPE_DM9000E;
707 }
708
668 /* from this point we assume that we have found a DM9000 */ 709 /* from this point we assume that we have found a DM9000 */
669 710
670 /* driver system function */ 711 /* driver system function */
@@ -715,8 +756,9 @@ dm9000_probe(struct platform_device *pdev)
715 756
716 if (ret == 0) { 757 if (ret == 0) {
717 DECLARE_MAC_BUF(mac); 758 DECLARE_MAC_BUF(mac);
718 printk("%s: dm9000 at %p,%p IRQ %d MAC: %s (%s)\n", 759 printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %s (%s)\n",
719 ndev->name, db->io_addr, db->io_data, ndev->irq, 760 ndev->name, dm9000_type_to_char(db->type),
761 db->io_addr, db->io_data, ndev->irq,
720 print_mac(mac, ndev->dev_addr), mac_src); 762 print_mac(mac, ndev->dev_addr), mac_src);
721 } 763 }
722 return 0; 764 return 0;
@@ -778,6 +820,7 @@ static void
778dm9000_init_dm9000(struct net_device *dev) 820dm9000_init_dm9000(struct net_device *dev)
779{ 821{
780 board_info_t *db = (board_info_t *) dev->priv; 822 board_info_t *db = (board_info_t *) dev->priv;
823 unsigned int imr;
781 824
782 dm9000_dbg(db, 1, "entering %s\n", __func__); 825 dm9000_dbg(db, 1, "entering %s\n", __func__);
783 826
@@ -804,8 +847,14 @@ dm9000_init_dm9000(struct net_device *dev)
804 /* Set address filter table */ 847 /* Set address filter table */
805 dm9000_hash_table(dev); 848 dm9000_hash_table(dev);
806 849
850 imr = IMR_PAR | IMR_PTM | IMR_PRM;
851 if (db->type != TYPE_DM9000E)
852 imr |= IMR_LNKCHNG;
853
854 db->imr_all = imr;
855
807 /* Enable TX/RX interrupt mask */ 856 /* Enable TX/RX interrupt mask */
808 iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM); 857 iow(db, DM9000_IMR, imr);
809 858
810 /* Init Driver variable */ 859 /* Init Driver variable */
811 db->tx_pkt_cnt = 0; 860 db->tx_pkt_cnt = 0;
@@ -962,8 +1011,15 @@ dm9000_interrupt(int irq, void *dev_id)
962 if (int_status & ISR_PTS) 1011 if (int_status & ISR_PTS)
963 dm9000_tx_done(dev, db); 1012 dm9000_tx_done(dev, db);
964 1013
1014 if (db->type != TYPE_DM9000E) {
1015 if (int_status & ISR_LNKCHNG) {
1016 /* fire a link-change request */
1017 schedule_delayed_work(&db->phy_poll, 1);
1018 }
1019 }
1020
965 /* Re-enable interrupt mask */ 1021 /* Re-enable interrupt mask */
966 iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM); 1022 iow(db, DM9000_IMR, db->imr_all);
967 1023
968 /* Restore previous register address */ 1024 /* Restore previous register address */
969 writeb(reg_save, db->io_addr); 1025 writeb(reg_save, db->io_addr);
diff --git a/drivers/net/dm9000.h b/drivers/net/dm9000.h
index 82cad360bafc..ba25cf541420 100644
--- a/drivers/net/dm9000.h
+++ b/drivers/net/dm9000.h
@@ -45,6 +45,9 @@
45#define DM9000_CHIPR 0x2C 45#define DM9000_CHIPR 0x2C
46#define DM9000_SMCR 0x2F 46#define DM9000_SMCR 0x2F
47 47
48#define CHIPR_DM9000A 0x19
49#define CHIPR_DM9000B 0x1B
50
48#define DM9000_MRCMDX 0xF0 51#define DM9000_MRCMDX 0xF0
49#define DM9000_MRCMD 0xF2 52#define DM9000_MRCMD 0xF2
50#define DM9000_MRRL 0xF4 53#define DM9000_MRRL 0xF4
@@ -131,5 +134,13 @@
131#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */ 134#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */
132#define DM9000_PKT_MAX 1536 /* Received packet max size */ 135#define DM9000_PKT_MAX 1536 /* Received packet max size */
133 136
137/* DM9000A / DM9000B definitions */
138
139#define IMR_LNKCHNG (1<<5)
140#define IMR_UNDERRUN (1<<4)
141
142#define ISR_LNKCHNG (1<<5)
143#define ISR_UNDERRUN (1<<4)
144
134#endif /* _DM9000X_H_ */ 145#endif /* _DM9000X_H_ */
135 146