diff options
author | Ben Dooks <ben-linux@fluff.org> | 2008-06-24 17:15:59 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-06-24 22:57:16 -0400 |
commit | 6d406b3c76b369a7b043470719761aa6ee1a38d1 (patch) | |
tree | 06eb1d946e37d097c96d059cd7871611fbabd98c | |
parent | da3854fc9f80c0240ba7cadd2aebf036683ff21b (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.c | 66 | ||||
-rw-r--r-- | drivers/net/dm9000.h | 11 |
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 | |||
92 | enum dm9000_type { | ||
93 | TYPE_DM9000E, /* original DM9000 */ | ||
94 | TYPE_DM9000A, | ||
95 | TYPE_DM9000B | ||
96 | }; | ||
97 | |||
88 | /* Structure/enum declaration ------------------------------- */ | 98 | /* Structure/enum declaration ------------------------------- */ |
89 | typedef struct board_info { | 99 | typedef 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 | ||
303 | static void dm9000_schedule_poll(board_info_t *db) | 315 | static 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 | ||
532 | static 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 | |||
778 | dm9000_init_dm9000(struct net_device *dev) | 820 | dm9000_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 | ||