aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2009-10-29 02:37:09 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-30 01:57:30 -0400
commit0f5aac7070a01ec757ed243febe4fff7c944c4d2 (patch)
tree85322500f3ca59233c4b5a90c786c83d29734bb7 /drivers
parent877c8570fb00ad0529b07f8193cc098ac0193d03 (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.c79
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) */
2142static 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);