From 21461380d30fb52b0bbf96dbcccd0b5096a7b346 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 3 Sep 2005 00:54:25 +0200 Subject: [PATCH] sis190: unmask the link change events link changes reporting does not work when the driver masks its irq event Signed-off-by: Arnaud Patard Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/sis190.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/sis190.c') diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index bf3440aa6c2..5f1d0ad5496 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -360,7 +360,7 @@ MODULE_VERSION(DRV_VERSION); MODULE_LICENSE("GPL"); static const u32 sis190_intr_mask = - RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt; + RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange; /* * Maximum number of multicast addresses to filter (vs. Rx-all-multicast). @@ -923,6 +923,7 @@ static void sis190_phy_task(void * data) BMSR_ANEGCOMPLETE)) { net_link(tp, KERN_WARNING "%s: PHY reset until link up.\n", dev->name); + netif_carrier_off(dev); mdio_write(ioaddr, phy_id, MII_BMCR, val | BMCR_RESET); mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT); } else { -- cgit v1.2.3 From 900eb9d69252cf91d42f6a87fc80b1c5518dbff1 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 3 Sep 2005 00:55:27 +0200 Subject: [PATCH] sis190: recent chipsets from SiS include a RGMII Extracted from SiS's GPLed driver. From the few pdf available at SiS's, it seems that the 965 and the 966 south bridge include this interface whereas the 965L (and anything below) does not. It is expected to be a sis191 related feature and should not hurt the existing sis190 driver. Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/sis190.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'drivers/net/sis190.c') diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 5f1d0ad5496..95ec3af9ec7 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -279,6 +279,11 @@ enum sis190_eeprom_address { EEPROMMACAddr = 0x03 }; +enum sis190_feature { + F_HAS_RGMII = 1, + F_PHY_88E1111 = 2 +}; + struct sis190_private { void __iomem *mmio_addr; struct pci_dev *pci_dev; @@ -300,6 +305,7 @@ struct sis190_private { u32 msg_enable; struct mii_if_info mii_if; struct list_head first_phy; + u32 features; }; struct sis190_phy { @@ -321,11 +327,12 @@ static struct mii_chip_info { const char *name; u16 id[2]; unsigned int type; + u32 feature; } mii_chip_table[] = { - { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN }, - { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN }, - { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN }, - { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN }, + { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, 0 }, + { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 }, + { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 }, + { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 }, { NULL, } }; @@ -1309,6 +1316,7 @@ static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp, phy->type = (p->type == MIX) ? ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ? LAN : HOME) : p->type; + tp->features |= p->feature; } else phy->type = UNKNOWN; @@ -1317,6 +1325,25 @@ static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp, (phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id); } +static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp) +{ + if (tp->features & F_PHY_88E1111) { + void __iomem *ioaddr = tp->mmio_addr; + int phy_id = tp->mii_if.phy_id; + u16 reg[2][2] = { + { 0x808b, 0x0ce1 }, + { 0x808f, 0x0c60 } + }, *p; + + p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1]; + + mdio_write(ioaddr, phy_id, 0x1b, p[0]); + udelay(200); + mdio_write(ioaddr, phy_id, 0x14, p[1]); + udelay(200); + } +} + /** * sis190_mii_probe - Probe MII PHY for sis190 * @dev: the net device to probe for @@ -1367,6 +1394,8 @@ static int __devinit sis190_mii_probe(struct net_device *dev) /* Select default PHY for mac */ sis190_default_phy(dev); + sis190_mii_probe_88e1111_fixup(tp); + mii_if->dev = dev; mii_if->mdio_read = __mdio_read; mii_if->mdio_write = __mdio_write; @@ -1506,6 +1535,11 @@ static void sis190_tx_timeout(struct net_device *dev) netif_wake_queue(dev); } +static void sis190_set_rgmii(struct sis190_private *tp, u8 reg) +{ + tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0; +} + static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, struct net_device *dev) { @@ -1533,6 +1567,8 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, ((u16 *)dev->dev_addr)[0] = le16_to_cpu(w); } + sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo)); + return 0; } @@ -1578,6 +1614,8 @@ static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev, outb(0x12, 0x78); reg = inb(0x79); + sis190_set_rgmii(tp, reg); + /* Restore the value to ISA Bridge */ pci_write_config_byte(isa_bridge, 0x48, tmp8); pci_dev_put(isa_bridge); @@ -1800,6 +1838,9 @@ static int __devinit sis190_init_one(struct pci_dev *pdev, dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name, + (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII"); + netif_carrier_off(dev); sis190_set_speed_auto(dev); -- cgit v1.2.3 From 6614a6dc6ebba4d3ca0ba5ea023b61a7d22ab00b Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 3 Sep 2005 00:56:16 +0200 Subject: [PATCH] sis190: make 10Mbps the default when handling the StationControl register This patch does three things: - widen the access to the StationControl register (note the SIS_W16 versus SIS_W32 change); - default to 10Mbps half duplex when the LPA can not be evaluated (reg31->ctl is identical for both). It can be argued that it makes sense as the lowest common denominator when everything else failed. Btw it works better than the current code. :o) - remove some enums: they do not document anymore. Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/sis190.c | 58 +++++++++++++++++++--------------------------------- 1 file changed, 21 insertions(+), 37 deletions(-) (limited to 'drivers/net/sis190.c') diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 95ec3af9ec7..2f69ba8ef88 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -179,14 +179,6 @@ enum sis190_register_content { TxInterFrameGapShift = 24, TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - /* StationControl */ - _1000bpsF = 0x1c00, - _1000bpsH = 0x0c00, - _100bpsF = 0x1800, - _100bpsH = 0x0800, - _10bpsF = 0x1400, - _10bpsH = 0x0400, - LinkStatus = 0x02, // unused FullDup = 0x01, // unused @@ -886,11 +878,6 @@ static void sis190_hw_start(struct net_device *dev) SIS_W32(IntrStatus, 0xffffffff); SIS_W32(IntrMask, 0x0); - /* - * Default is 100Mbps. - * A bit strange: 100Mbps is 0x1801 elsewhere -- FR 2005/06/09 - */ - SIS_W16(StationControl, 0x1901); SIS_W32(GMIIControl, 0x0); SIS_W32(TxMacControl, 0x60); SIS_W16(RxMacControl, 0x02); @@ -937,29 +924,23 @@ static void sis190_phy_task(void * data) /* Rejoice ! */ struct { int val; + u32 ctl; const char *msg; - u16 ctl; } reg31[] = { - { LPA_1000XFULL | LPA_SLCT, - "1000 Mbps Full Duplex", - 0x01 | _1000bpsF }, - { LPA_1000XHALF | LPA_SLCT, - "1000 Mbps Half Duplex", - 0x01 | _1000bpsH }, - { LPA_100FULL, - "100 Mbps Full Duplex", - 0x01 | _100bpsF }, - { LPA_100HALF, - "100 Mbps Half Duplex", - 0x01 | _100bpsH }, - { LPA_10FULL, - "10 Mbps Full Duplex", - 0x01 | _10bpsF }, - { LPA_10HALF, - "10 Mbps Half Duplex", - 0x01 | _10bpsH }, - { 0, "unknown", 0x0000 } - }, *p; + { LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000, + "1000 Mbps Full Duplex" }, + { LPA_1000XHALF | LPA_SLCT, 0x07000c00, + "1000 Mbps Half Duplex" }, + { LPA_100FULL, 0x04000800 | 0x00001000, + "100 Mbps Full Duplex" }, + { LPA_100HALF, 0x04000800, + "100 Mbps Half Duplex" }, + { LPA_10FULL, 0x04000400 | 0x00001000, + "10 Mbps Full Duplex" }, + { LPA_10HALF, 0x04000400, + "10 Mbps Half Duplex" }, + { 0, 0x04000400, "unknown" } + }, *p; u16 adv; val = mdio_read(ioaddr, phy_id, 0x1f); @@ -972,12 +953,15 @@ static void sis190_phy_task(void * data) val &= adv; - for (p = reg31; p->ctl; p++) { + for (p = reg31; p->val; p++) { if ((val & p->val) == p->val) break; } - if (p->ctl) - SIS_W16(StationControl, p->ctl); + + p->ctl |= SIS_R32(StationControl) & ~0x0f001c00; + + SIS_W32(StationControl, p->ctl); + net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name, p->msg); netif_carrier_on(dev); -- cgit v1.2.3 From c3d6f1f24cf3fdfdad3bff631349dc2aef06c8df Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 3 Sep 2005 00:56:57 +0200 Subject: [PATCH] sis190: RGMII Tx internal delay fiddling Don't ask. The patch is based on SiS's GPLed driver. Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/sis190.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/net/sis190.c') diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 2f69ba8ef88..61a24a944b8 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -273,7 +273,8 @@ enum sis190_eeprom_address { enum sis190_feature { F_HAS_RGMII = 1, - F_PHY_88E1111 = 2 + F_PHY_88E1111 = 2, + F_PHY_BCM5461 = 4 }; struct sis190_private { @@ -321,7 +322,7 @@ static struct mii_chip_info { unsigned int type; u32 feature; } mii_chip_table[] = { - { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, 0 }, + { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 }, { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 }, { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 }, { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 }, @@ -960,8 +961,22 @@ static void sis190_phy_task(void * data) p->ctl |= SIS_R32(StationControl) & ~0x0f001c00; + if ((tp->features & F_HAS_RGMII) && + (tp->features & F_PHY_BCM5461)) { + // Set Tx Delay in RGMII mode. + mdio_write(ioaddr, phy_id, 0x18, 0xf1c7); + udelay(200); + mdio_write(ioaddr, phy_id, 0x1c, 0x8c00); + p->ctl |= 0x03000000; + } + SIS_W32(StationControl, p->ctl); + if (tp->features & F_HAS_RGMII) { + SIS_W32(RGDelay, 0x0441); + SIS_W32(RGDelay, 0x0440); + } + net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name, p->msg); netif_carrier_on(dev); -- cgit v1.2.3 From e797637f4c1cbcecb2d8f5cfa05b161da1f0b802 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 3 Sep 2005 00:57:51 +0200 Subject: [PATCH] sis190: basic sis191 support The sis191 is the gigabit brother of the sis190. SiS's driver suggests that the register set is backward compatible: this should hopefully give a basic driver. The device should allow the usual features from a modern ethernet adapter (802.1q, SG, Jumbo frames, TSO, checksum offload). So far the relevant register layout is not documented. SiS's driver does not provide these features either (at least not for Linux). Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/sis190.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/sis190.c') diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 61a24a944b8..92f75529eff 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -331,14 +331,14 @@ static struct mii_chip_info { const static struct { const char *name; - u8 version; /* depend on docs */ - u32 RxConfigMask; /* clear the bits supported by this chip */ } sis_chip_info[] = { - { DRV_NAME, 0x00, 0xff7e1880, }, + { "SiS 190 PCI Fast Ethernet adapter" }, + { "SiS 191 PCI Gigabit Ethernet adapter" }, }; static struct pci_device_id sis190_pci_tbl[] __devinitdata = { { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 }, { 0, }, }; -- cgit v1.2.3