Commit 77675260 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Jeff Garzik

[PATCH] Better tulip handling on PA-RISC

This patch improves some of the handling of PA-RISC tulip cards.

 - Introduce HAS_SWAPPED_SEEPROM and NEEDS_FAKE_MEDIA_TABLE
 - Only trigger this code on GSC machines.  The pure PCI machines don't
   have these cards.
 - Allow the chip_name to be overridden in tulip_init_one().
 - Fix some indentation.
 - Handle the output from tulip_read_eeprom() better.
parent c2b08fea
...@@ -90,12 +90,8 @@ static const char *block_name[] __devinitdata = { ...@@ -90,12 +90,8 @@ static const char *block_name[] __devinitdata = {
*/ */
static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp) static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
{ {
#ifdef __hppa__ #ifdef CONFIG_GSC
unsigned char *ee_data = tp->eeprom; if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
if (ee_data[0] == 0x3c && ee_data[1] == 0x10 &&
(ee_data[2] == 0x63 || ee_data[2] == 0x61) && ee_data[3] == 0x10) {
static unsigned char leafdata[] = static unsigned char leafdata[] =
{ 0x01, /* phy number */ { 0x01, /* phy number */
0x02, /* gpr setup sequence length */ 0x02, /* gpr setup sequence length */
...@@ -306,12 +302,12 @@ void __devinit tulip_parse_eeprom(struct net_device *dev) ...@@ -306,12 +302,12 @@ void __devinit tulip_parse_eeprom(struct net_device *dev)
/* EEPROM_Ctrl bits. */ /* EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */ #define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
#define EE_CS 0x01 /* EEPROM chip select. */ #define EE_CS 0x01 /* EEPROM chip select. */
#define EE_DATA_WRITE 0x04 /* Data from the Tulip to EEPROM. */ #define EE_DATA_WRITE 0x04 /* Data from the Tulip to EEPROM. */
#define EE_WRITE_0 0x01 #define EE_WRITE_0 0x01
#define EE_WRITE_1 0x05 #define EE_WRITE_1 0x05
#define EE_DATA_READ 0x08 /* Data from the EEPROM chip. */ #define EE_DATA_READ 0x08 /* Data from the EEPROM chip. */
#define EE_ENB (0x4800 | EE_CS) #define EE_ENB (0x4800 | EE_CS)
/* Delay between EEPROM clock transitions. /* Delay between EEPROM clock transitions.
Even at 33Mhz current PCI implementations don't overrun the EEPROM clock. Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
...@@ -322,11 +318,12 @@ void __devinit tulip_parse_eeprom(struct net_device *dev) ...@@ -322,11 +318,12 @@ void __devinit tulip_parse_eeprom(struct net_device *dev)
#define EE_READ_CMD (6) #define EE_READ_CMD (6)
/* Note: this routine returns extra data bits for size detection. */ /* Note: this routine returns extra data bits for size detection. */
int __devinit tulip_read_eeprom(long ioaddr, int location, int addr_len) int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
{ {
int i; int i;
unsigned retval = 0; unsigned retval = 0;
long ee_addr = ioaddr + CSR9; struct tulip_private *tp = dev->priv;
long ee_addr = tp->base_addr + CSR9;
int read_cmd = location | (EE_READ_CMD << addr_len); int read_cmd = location | (EE_READ_CMD << addr_len);
outl(EE_ENB & ~EE_CS, ee_addr); outl(EE_ENB & ~EE_CS, ee_addr);
...@@ -354,6 +351,6 @@ int __devinit tulip_read_eeprom(long ioaddr, int location, int addr_len) ...@@ -354,6 +351,6 @@ int __devinit tulip_read_eeprom(long ioaddr, int location, int addr_len)
/* Terminate the EEPROM access. */ /* Terminate the EEPROM access. */
outl(EE_ENB & ~EE_CS, ee_addr); outl(EE_ENB & ~EE_CS, ee_addr);
return retval; return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval;
} }
...@@ -64,6 +64,8 @@ enum tbl_flag { ...@@ -64,6 +64,8 @@ enum tbl_flag {
COMET_MAC_ADDR = 0x0800, COMET_MAC_ADDR = 0x0800,
HAS_PCI_MWI = 0x1000, HAS_PCI_MWI = 0x1000,
HAS_PHY_IRQ = 0x2000, HAS_PHY_IRQ = 0x2000,
HAS_SWAPPED_SEEPROM = 0x4000,
NEEDS_FAKE_MEDIA_TABLE = 0x8000,
}; };
...@@ -407,7 +409,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5); ...@@ -407,7 +409,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5);
/* eeprom.c */ /* eeprom.c */
void tulip_parse_eeprom(struct net_device *dev); void tulip_parse_eeprom(struct net_device *dev);
int tulip_read_eeprom(long ioaddr, int location, int addr_len); int tulip_read_eeprom(struct net_device *dev, int location, int addr_len);
/* interrupt.c */ /* interrupt.c */
extern unsigned int tulip_max_interrupt_work; extern unsigned int tulip_max_interrupt_work;
......
...@@ -1246,6 +1246,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, ...@@ -1246,6 +1246,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
long ioaddr; long ioaddr;
static int board_idx = -1; static int board_idx = -1;
int chip_idx = ent->driver_data; int chip_idx = ent->driver_data;
const char *chip_name = tulip_tbl[chip_idx].chip_name;
unsigned int eeprom_missing = 0; unsigned int eeprom_missing = 0;
unsigned int force_csr0 = 0; unsigned int force_csr0 = 0;
...@@ -1414,6 +1415,23 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, ...@@ -1414,6 +1415,23 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
pci_set_master(pdev); pci_set_master(pdev);
#ifdef CONFIG_GSC
if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP) {
switch (pdev->subsystem_device) {
default:
break;
case 0x1061:
case 0x1062:
case 0x1063:
case 0x1098:
case 0x1099:
case 0x10EE:
tp->flags |= HAS_SWAPPED_SEEPROM | NEEDS_FAKE_MEDIA_TABLE;
chip_name = "GSC DS21140 Tulip";
}
}
#endif
/* Clear the missed-packet counter. */ /* Clear the missed-packet counter. */
inl(ioaddr + CSR8); inl(ioaddr + CSR8);
...@@ -1442,11 +1460,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, ...@@ -1442,11 +1460,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
} else { } else {
/* A serial EEPROM interface, we read now and sort it out later. */ /* A serial EEPROM interface, we read now and sort it out later. */
int sa_offset = 0; int sa_offset = 0;
int ee_addr_size = tulip_read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; int ee_addr_size = tulip_read_eeprom(dev, 0xff, 8) & 0x40000 ? 8 : 6;
for (i = 0; i < sizeof(tp->eeprom)/2; i++) for (i = 0; i < sizeof(tp->eeprom); i+=2) {
((u16 *)ee_data)[i] = u16 data = tulip_read_eeprom(dev, i/2, ee_addr_size);
le16_to_cpu(tulip_read_eeprom(ioaddr, i, ee_addr_size)); ee_data[i] = data & 0xff;
ee_data[i + 1] = data >> 8;
}
/* DEC now has a specification (see Notes) but early board makers /* DEC now has a specification (see Notes) but early board makers
just put the address in the first EEPROM locations. */ just put the address in the first EEPROM locations. */
...@@ -1489,25 +1509,26 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, ...@@ -1489,25 +1509,26 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
tp->flags &= ~HAS_MEDIA_TABLE; tp->flags &= ~HAS_MEDIA_TABLE;
} }
#endif #endif
#ifdef __hppa__ #ifdef CONFIG_GSC
/* 3x5 HSC (J3514A) has a broken srom */ /* Check to see if we have a broken srom */
if(ee_data[0] == 0x61 && ee_data[1] == 0x10) { if (ee_data[0] == 0x61 && ee_data[1] == 0x10) {
/* pci_vendor_id and subsystem_id are swapped */ /* pci_vendor_id and subsystem_id are swapped */
ee_data[0] = ee_data[2]; ee_data[0] = ee_data[2];
ee_data[1] = ee_data[3]; ee_data[1] = ee_data[3];
ee_data[2] = 0x61; ee_data[2] = 0x61;
ee_data[3] = 0x10; ee_data[3] = 0x10;
/* srom need to be byte-swaped and shifted up 1 word. /* HSC-PCI boards need to be byte-swaped and shifted
* This shift needs to happen at the end of the MAC * up 1 word. This shift needs to happen at the end
* first because of the 2 byte overlap. * of the MAC first because of the 2 byte overlap.
*/ */
for(i = 4; i >= 0; i -= 2) { for (i = 4; i >= 0; i -= 2) {
ee_data[17 + i + 3] = ee_data[17 + i]; ee_data[17 + i + 3] = ee_data[17 + i];
ee_data[16 + i + 5] = ee_data[16 + i]; ee_data[16 + i + 5] = ee_data[16 + i];
} }
} }
#endif #endif
for (i = 0; i < 6; i ++) { for (i = 0; i < 6; i ++) {
dev->dev_addr[i] = ee_data[i + sa_offset]; dev->dev_addr[i] = ee_data[i + sa_offset];
sum += ee_data[i + sa_offset]; sum += ee_data[i + sa_offset];
...@@ -1628,7 +1649,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, ...@@ -1628,7 +1649,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
goto err_out_free_ring; goto err_out_free_ring;
printk(KERN_INFO "%s: %s rev %d at %#3lx,", printk(KERN_INFO "%s: %s rev %d at %#3lx,",
dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr); dev->name, chip_name, chip_rev, ioaddr);
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
if (eeprom_missing) if (eeprom_missing)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment