diff options
author | Stephen Hemminger <shemminger@vyatta.com> | 2009-10-29 02:37:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-30 01:57:30 -0400 |
commit | 0f5aac7070a01ec757ed243febe4fff7c944c4d2 (patch) | |
tree | 85322500f3ca59233c4b5a90c786c83d29734bb7 /drivers | |
parent | 877c8570fb00ad0529b07f8193cc098ac0193d03 (diff) |
sky2: 88E8059 support
Tentative support for newer Marvell hardware including
the Yukon-2 Optima chip. Do not have hatdware to test this yet,
code is based on vendor driver.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/sky2.c | 79 |
1 files changed, 78 insertions, 1 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 3387a2f80dad..53cce74d3238 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -140,6 +140,7 @@ static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = { | |||
140 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436D) }, /* 88E8055 */ | 140 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436D) }, /* 88E8055 */ |
141 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */ | 141 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */ |
142 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4380) }, /* 88E8057 */ | 142 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4380) }, /* 88E8057 */ |
143 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4381) }, /* 88E8059 */ | ||
143 | { 0 } | 144 | { 0 } |
144 | }; | 145 | }; |
145 | 146 | ||
@@ -603,6 +604,16 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
603 | /* apply workaround for integrated resistors calibration */ | 604 | /* apply workaround for integrated resistors calibration */ |
604 | gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17); | 605 | gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17); |
605 | gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60); | 606 | gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60); |
607 | } else if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) { | ||
608 | /* apply fixes in PHY AFE */ | ||
609 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00ff); | ||
610 | |||
611 | /* apply RDAC termination workaround */ | ||
612 | gm_phy_write(hw, port, 24, 0x2800); | ||
613 | gm_phy_write(hw, port, 23, 0x2001); | ||
614 | |||
615 | /* set page register back to 0 */ | ||
616 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); | ||
606 | } else if (hw->chip_id != CHIP_ID_YUKON_EX && | 617 | } else if (hw->chip_id != CHIP_ID_YUKON_EX && |
607 | hw->chip_id < CHIP_ID_YUKON_SUPR) { | 618 | hw->chip_id < CHIP_ID_YUKON_SUPR) { |
608 | /* no effect on Yukon-XL */ | 619 | /* no effect on Yukon-XL */ |
@@ -2127,6 +2138,25 @@ out: | |||
2127 | spin_unlock(&sky2->phy_lock); | 2138 | spin_unlock(&sky2->phy_lock); |
2128 | } | 2139 | } |
2129 | 2140 | ||
2141 | /* Special quick link interrupt (Yukon-2 Optima only) */ | ||
2142 | static void sky2_qlink_intr(struct sky2_hw *hw) | ||
2143 | { | ||
2144 | struct sky2_port *sky2 = netdev_priv(hw->dev[0]); | ||
2145 | u32 imask; | ||
2146 | u16 phy; | ||
2147 | |||
2148 | /* disable irq */ | ||
2149 | imask = sky2_read32(hw, B0_IMSK); | ||
2150 | imask &= ~Y2_IS_PHY_QLNK; | ||
2151 | sky2_write32(hw, B0_IMSK, imask); | ||
2152 | |||
2153 | /* reset PHY Link Detect */ | ||
2154 | phy = sky2_pci_read16(hw, PSM_CONFIG_REG4); | ||
2155 | sky2_pci_write16(hw, PSM_CONFIG_REG4, phy | 1); | ||
2156 | |||
2157 | sky2_link_up(sky2); | ||
2158 | } | ||
2159 | |||
2130 | /* Transmit timeout is only called if we are running, carrier is up | 2160 | /* Transmit timeout is only called if we are running, carrier is up |
2131 | * and tx queue is full (stopped). | 2161 | * and tx queue is full (stopped). |
2132 | */ | 2162 | */ |
@@ -2796,6 +2826,9 @@ static int sky2_poll(struct napi_struct *napi, int work_limit) | |||
2796 | if (status & Y2_IS_IRQ_PHY2) | 2826 | if (status & Y2_IS_IRQ_PHY2) |
2797 | sky2_phy_intr(hw, 1); | 2827 | sky2_phy_intr(hw, 1); |
2798 | 2828 | ||
2829 | if (status & Y2_IS_PHY_QLNK) | ||
2830 | sky2_qlink_intr(hw); | ||
2831 | |||
2799 | while ((idx = sky2_read16(hw, STAT_PUT_IDX)) != hw->st_idx) { | 2832 | while ((idx = sky2_read16(hw, STAT_PUT_IDX)) != hw->st_idx) { |
2800 | work_done += sky2_status_intr(hw, work_limit - work_done, idx); | 2833 | work_done += sky2_status_intr(hw, work_limit - work_done, idx); |
2801 | 2834 | ||
@@ -2845,6 +2878,7 @@ static u32 sky2_mhz(const struct sky2_hw *hw) | |||
2845 | case CHIP_ID_YUKON_EX: | 2878 | case CHIP_ID_YUKON_EX: |
2846 | case CHIP_ID_YUKON_SUPR: | 2879 | case CHIP_ID_YUKON_SUPR: |
2847 | case CHIP_ID_YUKON_UL_2: | 2880 | case CHIP_ID_YUKON_UL_2: |
2881 | case CHIP_ID_YUKON_OPT: | ||
2848 | return 125; | 2882 | return 125; |
2849 | 2883 | ||
2850 | case CHIP_ID_YUKON_FE: | 2884 | case CHIP_ID_YUKON_FE: |
@@ -2934,6 +2968,7 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2934 | break; | 2968 | break; |
2935 | 2969 | ||
2936 | case CHIP_ID_YUKON_UL_2: | 2970 | case CHIP_ID_YUKON_UL_2: |
2971 | case CHIP_ID_YUKON_OPT: | ||
2937 | hw->flags = SKY2_HW_GIGABIT | 2972 | hw->flags = SKY2_HW_GIGABIT |
2938 | | SKY2_HW_ADV_POWER_CTL; | 2973 | | SKY2_HW_ADV_POWER_CTL; |
2939 | break; | 2974 | break; |
@@ -3024,6 +3059,46 @@ static void sky2_reset(struct sky2_hw *hw) | |||
3024 | sky2_pci_write32(hw, PCI_DEV_REG3, P_CLK_MACSEC_DIS); | 3059 | sky2_pci_write32(hw, PCI_DEV_REG3, P_CLK_MACSEC_DIS); |
3025 | } | 3060 | } |
3026 | 3061 | ||
3062 | if (hw->chip_id == CHIP_ID_YUKON_OPT) { | ||
3063 | u16 reg; | ||
3064 | u32 msk; | ||
3065 | |||
3066 | if (hw->chip_rev == 0) { | ||
3067 | /* disable PCI-E PHY power down (set PHY reg 0x80, bit 7 */ | ||
3068 | sky2_write32(hw, Y2_PEX_PHY_DATA, (0x80UL << 16) | (1 << 7)); | ||
3069 | |||
3070 | /* set PHY Link Detect Timer to 1.1 second (11x 100ms) */ | ||
3071 | reg = 10; | ||
3072 | } else { | ||
3073 | /* set PHY Link Detect Timer to 0.4 second (4x 100ms) */ | ||
3074 | reg = 3; | ||
3075 | } | ||
3076 | |||
3077 | reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE; | ||
3078 | |||
3079 | /* reset PHY Link Detect */ | ||
3080 | sky2_pci_write16(hw, PSM_CONFIG_REG4, | ||
3081 | reg | PSM_CONFIG_REG4_RST_PHY_LINK_DETECT); | ||
3082 | sky2_pci_write16(hw, PSM_CONFIG_REG4, reg); | ||
3083 | |||
3084 | |||
3085 | /* enable PHY Quick Link */ | ||
3086 | msk = sky2_read32(hw, B0_IMSK); | ||
3087 | msk |= Y2_IS_PHY_QLNK; | ||
3088 | sky2_write32(hw, B0_IMSK, msk); | ||
3089 | |||
3090 | /* check if PSMv2 was running before */ | ||
3091 | reg = sky2_pci_read16(hw, PSM_CONFIG_REG3); | ||
3092 | if (reg & PCI_EXP_LNKCTL_ASPMC) { | ||
3093 | int cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); | ||
3094 | /* restore the PCIe Link Control register */ | ||
3095 | sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg); | ||
3096 | } | ||
3097 | |||
3098 | /* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */ | ||
3099 | sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16)); | ||
3100 | } | ||
3101 | |||
3027 | /* Clear I2C IRQ noise */ | 3102 | /* Clear I2C IRQ noise */ |
3028 | sky2_write32(hw, B2_I2C_IRQ, 1); | 3103 | sky2_write32(hw, B2_I2C_IRQ, 1); |
3029 | 3104 | ||
@@ -4442,9 +4517,11 @@ static const char *sky2_name(u8 chipid, char *buf, int sz) | |||
4442 | "FE+", /* 0xb8 */ | 4517 | "FE+", /* 0xb8 */ |
4443 | "Supreme", /* 0xb9 */ | 4518 | "Supreme", /* 0xb9 */ |
4444 | "UL 2", /* 0xba */ | 4519 | "UL 2", /* 0xba */ |
4520 | "Unknown", /* 0xbb */ | ||
4521 | "Optima", /* 0xbc */ | ||
4445 | }; | 4522 | }; |
4446 | 4523 | ||
4447 | if (chipid >= CHIP_ID_YUKON_XL && chipid < CHIP_ID_YUKON_UL_2) | 4524 | if (chipid >= CHIP_ID_YUKON_XL && chipid < CHIP_ID_YUKON_OPT) |
4448 | strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz); | 4525 | strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz); |
4449 | else | 4526 | else |
4450 | snprintf(buf, sz, "(chip %#x)", chipid); | 4527 | snprintf(buf, sz, "(chip %#x)", chipid); |