diff options
| -rw-r--r-- | drivers/net/sky2.c | 156 | ||||
| -rw-r--r-- | drivers/net/sky2.h | 1 |
2 files changed, 112 insertions, 45 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 6d9c1db8896e..1d00cdcdaa67 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
| @@ -175,6 +175,91 @@ ready: | |||
| 175 | return gma_read16(hw, port, GM_SMI_DATA); | 175 | return gma_read16(hw, port, GM_SMI_DATA); |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | ||
| 179 | { | ||
| 180 | u16 power_control; | ||
| 181 | u32 reg1; | ||
| 182 | int vaux; | ||
| 183 | int ret = 0; | ||
| 184 | |||
| 185 | pr_debug("sky2_set_power_state %d\n", state); | ||
| 186 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
| 187 | |||
| 188 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control); | ||
| 189 | vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) && | ||
| 190 | (power_control & PCI_PM_CAP_PME_D3cold); | ||
| 191 | |||
| 192 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control); | ||
| 193 | |||
| 194 | power_control |= PCI_PM_CTRL_PME_STATUS; | ||
| 195 | power_control &= ~(PCI_PM_CTRL_STATE_MASK); | ||
| 196 | |||
| 197 | switch (state) { | ||
| 198 | case PCI_D0: | ||
| 199 | /* switch power to VCC (WA for VAUX problem) */ | ||
| 200 | sky2_write8(hw, B0_POWER_CTRL, | ||
| 201 | PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); | ||
| 202 | |||
| 203 | /* disable Core Clock Division, */ | ||
| 204 | sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); | ||
| 205 | |||
| 206 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
| 207 | /* enable bits are inverted */ | ||
| 208 | sky2_write8(hw, B2_Y2_CLK_GATE, | ||
| 209 | Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | | ||
| 210 | Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | | ||
| 211 | Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); | ||
| 212 | else | ||
| 213 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | ||
| 214 | |||
| 215 | /* Turn off phy power saving */ | ||
| 216 | pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®1); | ||
| 217 | reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); | ||
| 218 | |||
| 219 | /* looks like this xl is back asswards .. */ | ||
| 220 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) { | ||
| 221 | reg1 |= PCI_Y2_PHY1_COMA; | ||
| 222 | if (hw->ports > 1) | ||
| 223 | reg1 |= PCI_Y2_PHY2_COMA; | ||
| 224 | } | ||
| 225 | pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1); | ||
| 226 | break; | ||
| 227 | |||
| 228 | case PCI_D3hot: | ||
| 229 | case PCI_D3cold: | ||
| 230 | /* Turn on phy power saving */ | ||
| 231 | pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®1); | ||
| 232 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
| 233 | reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); | ||
| 234 | else | ||
| 235 | reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); | ||
| 236 | pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1); | ||
| 237 | |||
| 238 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
| 239 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | ||
| 240 | else | ||
| 241 | /* enable bits are inverted */ | ||
| 242 | sky2_write8(hw, B2_Y2_CLK_GATE, | ||
| 243 | Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | | ||
| 244 | Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | | ||
| 245 | Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); | ||
| 246 | |||
| 247 | /* switch power to VAUX */ | ||
| 248 | if (vaux && state != PCI_D3cold) | ||
| 249 | sky2_write8(hw, B0_POWER_CTRL, | ||
| 250 | (PC_VAUX_ENA | PC_VCC_ENA | | ||
| 251 | PC_VAUX_ON | PC_VCC_OFF)); | ||
| 252 | break; | ||
| 253 | default: | ||
| 254 | printk(KERN_ERR PFX "Unknown power state %d\n", state); | ||
| 255 | ret = -1; | ||
| 256 | } | ||
| 257 | |||
| 258 | pci_write_config_byte(hw->pdev, hw->pm_cap + PCI_PM_CTRL, power_control); | ||
| 259 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | ||
| 260 | return ret; | ||
| 261 | } | ||
| 262 | |||
| 178 | static void sky2_phy_reset(struct sky2_hw *hw, unsigned port) | 263 | static void sky2_phy_reset(struct sky2_hw *hw, unsigned port) |
| 179 | { | 264 | { |
| 180 | u16 reg; | 265 | u16 reg; |
| @@ -1869,7 +1954,7 @@ static inline u32 sky2_us2clk(const struct sky2_hw *hw, u32 us) | |||
| 1869 | 1954 | ||
| 1870 | static int sky2_reset(struct sky2_hw *hw) | 1955 | static int sky2_reset(struct sky2_hw *hw) |
| 1871 | { | 1956 | { |
| 1872 | u32 ctst, power; | 1957 | u32 ctst; |
| 1873 | u16 status; | 1958 | u16 status; |
| 1874 | u8 t8, pmd_type; | 1959 | u8 t8, pmd_type; |
| 1875 | int i; | 1960 | int i; |
| @@ -1927,33 +2012,7 @@ static int sky2_reset(struct sky2_hw *hw) | |||
| 1927 | } | 2012 | } |
| 1928 | hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; | 2013 | hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; |
| 1929 | 2014 | ||
| 1930 | /* switch power to VCC (WA for VAUX problem) */ | 2015 | sky2_set_power_state(hw, PCI_D0); |
| 1931 | sky2_write8(hw, B0_POWER_CTRL, | ||
| 1932 | PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); | ||
| 1933 | |||
| 1934 | /* disable Core Clock Division, */ | ||
| 1935 | sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); | ||
| 1936 | |||
| 1937 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
| 1938 | /* enable bits are inverted */ | ||
| 1939 | sky2_write8(hw, B2_Y2_CLK_GATE, | ||
| 1940 | Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | | ||
| 1941 | Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | | ||
| 1942 | Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); | ||
| 1943 | else | ||
| 1944 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | ||
| 1945 | |||
| 1946 | /* Turn off phy power saving */ | ||
| 1947 | pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &power); | ||
| 1948 | power &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); | ||
| 1949 | |||
| 1950 | /* looks like this xl is back asswards .. */ | ||
| 1951 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) { | ||
| 1952 | power |= PCI_Y2_PHY1_COMA; | ||
| 1953 | if (hw->ports > 1) | ||
| 1954 | power |= PCI_Y2_PHY2_COMA; | ||
| 1955 | } | ||
| 1956 | pci_write_config_dword(hw->pdev, PCI_DEV_REG1, power); | ||
| 1957 | 2016 | ||
| 1958 | for (i = 0; i < hw->ports; i++) { | 2017 | for (i = 0; i < hw->ports; i++) { |
| 1959 | sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); | 2018 | sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); |
| @@ -2714,7 +2773,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 2714 | { | 2773 | { |
| 2715 | struct net_device *dev, *dev1 = NULL; | 2774 | struct net_device *dev, *dev1 = NULL; |
| 2716 | struct sky2_hw *hw; | 2775 | struct sky2_hw *hw; |
| 2717 | int err, using_dac = 0; | 2776 | int err, pm_cap, using_dac = 0; |
| 2718 | 2777 | ||
| 2719 | err = pci_enable_device(pdev); | 2778 | err = pci_enable_device(pdev); |
| 2720 | if (err) { | 2779 | if (err) { |
| @@ -2732,6 +2791,15 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 2732 | 2791 | ||
| 2733 | pci_set_master(pdev); | 2792 | pci_set_master(pdev); |
| 2734 | 2793 | ||
| 2794 | /* Find power-management capability. */ | ||
| 2795 | pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); | ||
| 2796 | if (pm_cap == 0) { | ||
| 2797 | printk(KERN_ERR PFX "Cannot find PowerManagement capability, " | ||
| 2798 | "aborting.\n"); | ||
| 2799 | err = -EIO; | ||
| 2800 | goto err_out_free_regions; | ||
| 2801 | } | ||
| 2802 | |||
| 2735 | if (sizeof(dma_addr_t) > sizeof(u32)) { | 2803 | if (sizeof(dma_addr_t) > sizeof(u32)) { |
| 2736 | err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); | 2804 | err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); |
| 2737 | if (!err) | 2805 | if (!err) |
| @@ -2775,6 +2843,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 2775 | pci_name(pdev)); | 2843 | pci_name(pdev)); |
| 2776 | goto err_out_free_hw; | 2844 | goto err_out_free_hw; |
| 2777 | } | 2845 | } |
| 2846 | hw->pm_cap = pm_cap; | ||
| 2778 | 2847 | ||
| 2779 | err = sky2_reset(hw); | 2848 | err = sky2_reset(hw); |
| 2780 | if (err) | 2849 | if (err) |
| @@ -2861,8 +2930,10 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
| 2861 | unregister_netdev(dev0); | 2930 | unregister_netdev(dev0); |
| 2862 | 2931 | ||
| 2863 | sky2_write32(hw, B0_IMSK, 0); | 2932 | sky2_write32(hw, B0_IMSK, 0); |
| 2933 | sky2_set_power_state(hw, PCI_D3hot); | ||
| 2864 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 2934 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
| 2865 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 2935 | sky2_write8(hw, B0_CTST, CS_RST_SET); |
| 2936 | sky2_read8(hw, B0_CTST); | ||
| 2866 | 2937 | ||
| 2867 | free_irq(pdev->irq, hw); | 2938 | free_irq(pdev->irq, hw); |
| 2868 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); | 2939 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); |
| @@ -2874,6 +2945,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
| 2874 | free_netdev(dev0); | 2945 | free_netdev(dev0); |
| 2875 | iounmap(hw->regs); | 2946 | iounmap(hw->regs); |
| 2876 | kfree(hw); | 2947 | kfree(hw); |
| 2948 | |||
| 2877 | pci_set_drvdata(pdev, NULL); | 2949 | pci_set_drvdata(pdev, NULL); |
| 2878 | } | 2950 | } |
| 2879 | 2951 | ||
| @@ -2881,28 +2953,21 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
| 2881 | static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | 2953 | static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) |
| 2882 | { | 2954 | { |
| 2883 | struct sky2_hw *hw = pci_get_drvdata(pdev); | 2955 | struct sky2_hw *hw = pci_get_drvdata(pdev); |
| 2884 | int i, wol = 0; | 2956 | int i; |
| 2885 | 2957 | ||
| 2886 | for (i = 0; i < 2; i++) { | 2958 | for (i = 0; i < 2; i++) { |
| 2887 | struct net_device *dev = hw->dev[i]; | 2959 | struct net_device *dev = hw->dev[i]; |
| 2888 | 2960 | ||
| 2889 | if (dev) { | 2961 | if (dev) { |
| 2890 | struct sky2_port *sky2 = netdev_priv(dev); | 2962 | if (!netif_running(dev)) |
| 2891 | if (netif_running(dev)) { | 2963 | continue; |
| 2892 | netif_carrier_off(dev); | 2964 | |
| 2893 | sky2_down(dev); | 2965 | sky2_down(dev); |
| 2894 | } | ||
| 2895 | netif_device_detach(dev); | 2966 | netif_device_detach(dev); |
| 2896 | wol |= sky2->wol; | ||
| 2897 | } | 2967 | } |
| 2898 | } | 2968 | } |
| 2899 | 2969 | ||
| 2900 | pci_save_state(pdev); | 2970 | return sky2_set_power_state(hw, pci_choose_state(pdev, state)); |
| 2901 | pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); | ||
| 2902 | pci_disable_device(pdev); | ||
| 2903 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
| 2904 | |||
| 2905 | return 0; | ||
| 2906 | } | 2971 | } |
| 2907 | 2972 | ||
| 2908 | static int sky2_resume(struct pci_dev *pdev) | 2973 | static int sky2_resume(struct pci_dev *pdev) |
| @@ -2910,18 +2975,19 @@ static int sky2_resume(struct pci_dev *pdev) | |||
| 2910 | struct sky2_hw *hw = pci_get_drvdata(pdev); | 2975 | struct sky2_hw *hw = pci_get_drvdata(pdev); |
| 2911 | int i; | 2976 | int i; |
| 2912 | 2977 | ||
| 2913 | pci_set_power_state(pdev, PCI_D0); | ||
| 2914 | pci_restore_state(pdev); | 2978 | pci_restore_state(pdev); |
| 2915 | pci_enable_wake(pdev, PCI_D0, 0); | 2979 | pci_enable_wake(pdev, PCI_D0, 0); |
| 2980 | sky2_set_power_state(hw, PCI_D0); | ||
| 2916 | 2981 | ||
| 2917 | sky2_reset(hw); | 2982 | sky2_reset(hw); |
| 2918 | 2983 | ||
| 2919 | for (i = 0; i < 2; i++) { | 2984 | for (i = 0; i < 2; i++) { |
| 2920 | struct net_device *dev = hw->dev[i]; | 2985 | struct net_device *dev = hw->dev[i]; |
| 2921 | if (dev) { | 2986 | if (dev) { |
| 2922 | netif_device_attach(dev); | 2987 | if (netif_running(dev)) { |
| 2923 | if (netif_running(dev)) | 2988 | netif_device_attach(dev); |
| 2924 | sky2_up(dev); | 2989 | sky2_up(dev); |
| 2990 | } | ||
| 2925 | } | 2991 | } |
| 2926 | } | 2992 | } |
| 2927 | return 0; | 2993 | return 0; |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index ac91d91f130b..b1acdc606f31 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
| @@ -1854,6 +1854,7 @@ struct sky2_hw { | |||
| 1854 | u32 intr_mask; | 1854 | u32 intr_mask; |
| 1855 | struct net_device *dev[2]; | 1855 | struct net_device *dev[2]; |
| 1856 | 1856 | ||
| 1857 | int pm_cap; | ||
| 1857 | u8 chip_id; | 1858 | u8 chip_id; |
| 1858 | u8 chip_rev; | 1859 | u8 chip_rev; |
| 1859 | u8 copper; | 1860 | u8 copper; |
