bge-wol.diff

Stefan Sperling, 05/17/2014 04:35 pm

Download (10.6 kB)

sys/dev/mii/brgphyreg.h 23 Apr 2014 14:11:06 -0000
206 206
#define BRGPHY_AUXCTL_TX_TST	0x0400	/* TX test, always 1 */
207 207
#define BRGPHY_AUXCTL_DIS_PRF	0x0080	/* dis part resp filter */
208 208
#define BRGPHY_AUXCTL_DIAG_MODE	0x0004	/* Diagnostic mode */
209
#define BRGPHY_AUXCTL_WOL_ENBL	0x000A	/* Enable WOL */
209 210

  
210 211
#define BRGPHY_MII_AUXSTS	0x19	/* AUX status */
211 212
#define BRGPHY_AUXSTS_ACOMP	0x8000	/* autoneg complete */
sys/dev/pci/if_bge.c 27 Apr 2014 13:07:02 -0000
202 202
void bge_stop_fw(struct bge_softc *, int);
203 203
void bge_reset(struct bge_softc *);
204 204
void bge_link_upd(struct bge_softc *);
205
#ifndef SMALL_KERNEL
206
int bge_wol(struct ifnet *, int);
207
void bge_wol_power(struct bge_softc *);
208
#endif
205 209

  
206 210
void bge_ape_lock_init(struct bge_softc *);
207 211
void bge_ape_read_fw_ver(struct bge_softc *);
......
3064 3068
	if (BGE_IS_5755_PLUS(sc) && sc->bge_flags & BGE_MSI)
3065 3069
		CSR_WRITE_4(sc, BGE_MSI_MODE, CSR_READ_4(sc, BGE_MSI_MODE) &
3066 3070
		    ~BGE_MSIMODE_ONE_SHOT_DISABLE);
3071
	
3072
#ifndef SMALL_KERNEL
3073
	if (hwcfg & BGE_HWCFG_NO_GPIO2)
3074
		sc->bge_flags |= BGE_NO_GPIO2;
3075

  
3076
	if (BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5700) {
3077
		/* Check if ASF is enabled. */
3078
		if (!(sc->bge_flags & BGE_NO_EEPROM)) {
3079
		    if (bge_read_eeprom(sc, (caddr_t)&hwcfg,
3080
			BGE_EE_FEATURE_CFG_OFFSET, sizeof(hwcfg)) == 0) {
3081
				hwcfg = ntohl(hwcfg);
3082
				if (hwcfg & BGE_HWCFG_ASF)
3083
					sc->bge_flags |= BGE_ASF_MODE;
3084
		    }
3085
		} else if (hwcfg & BGE_HWCFG_ASF) {
3086
			sc->bge_flags |= BGE_ASF_MODE;
3087
		}
3088
	}
3089

  
3090
	/* Allow WoL if ASF is unsupported or disabled. */
3091
	if (!(sc->bge_flags & BGE_ASF_MODE)) {
3092
		ifp->if_capabilities |= IFCAP_WOL;
3093
		ifp->if_wol = bge_wol;
3094

  
3095
		/* This heuristic matches the Linux driver. */
3096
		if (!(hwcfg & BGE_HWCFG_EEPROM_WRITE_PROTECT))
3097
			sc->bge_flags |= BGE_WOL_NEEDS_VAUX;
3098
	}
3099
#endif
3067 3100

  
3068 3101
	/* Hookup IRQ last. */
3069 3102
	DPRINTFN(5, ("pci_intr_establish\n"));
......
3160 3193
		rv = config_activate_children(self, act);
3161 3194
		if (ifp->if_flags & IFF_RUNNING)
3162 3195
			bge_stop(sc);
3196
#ifndef SMALL_KERNEL
3197
		bge_wol_power(sc);
3198
#endif
3163 3199
		break;
3164 3200
	case DVACT_RESUME:
3165 3201
		if (ifp->if_flags & IFF_UP)
3166 3202
			bge_init(sc);
3167 3203
		break;
3204
	case DVACT_POWERDOWN:
3205
		rv = config_activate_children(self, act);
3206
		if (ifp->if_flags & IFF_RUNNING)
3207
			bge_stop(sc);
3208
#ifndef SMALL_KERNEL
3209
		bge_wol_power(sc);
3210
#endif
3211
		break;
3168 3212
	default:
3169 3213
		rv = config_activate_children(self, act);
3170 3214
		break;
......
4729 4773
	    BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE|
4730 4774
	    BGE_MACSTAT_LINK_CHANGED);
4731 4775
}
4776

  
4777
#ifndef SMALL_KERNEL
4778
int
4779
bge_wol(struct ifnet *ifp, int enable)
4780
{
4781
	struct bge_softc *sc = ifp->if_softc;
4782

  
4783
	if (enable)
4784
		sc->bge_flags |= BGE_WOL;
4785
	else
4786
		sc->bge_flags &= ~BGE_WOL;
4787

  
4788
	return (0);
4789
}
4790

  
4791
void
4792
bge_wol_power(struct bge_softc *sc)
4793
{
4794
	struct ifnet *ifp = &sc->arpcom.ac_if;
4795
	struct pci_attach_args *pa = &sc->bge_pa;
4796
	pcireg_t pcireg;
4797
	int s, offset, if_flags;
4798
	u_int32_t reg;
4799

  
4800
	if (!(sc->bge_flags & BGE_WOL))
4801
		return;
4802

  
4803
	s = splnet();
4804

  
4805
	/* 
4806
	 * In case the interface was never up we need to init the
4807
	 * chip for WOL to work.
4808
	 * XXX Need a smaller hammer than bge_init()/bge_stop().
4809
	 */
4810
	bge_init(sc);
4811

  
4812
	/* Tell the firmware we're taking control of WOL. */
4813
	bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM_WOL, BGE_MAGIC_WOL_NUMBER);
4814
	DELAY(100);
4815

  
4816
	bge_stop(sc);
4817

  
4818
	/* Disable host interrupts. */
4819
	BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
4820

  
4821
	/* Clear the PME status bit. */
4822
	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
4823
	    &offset, &pcireg))
4824
		pci_conf_write(pa->pa_pc, pa->pa_tag, offset + PCI_PMCSR,
4825
		    pcireg|PCI_PMCSR_PME_STATUS);
4826

  
4827
	/* Configure 10Mbps, the chip draws too much power in D3cold. */
4828
	if (!(sc->bge_flags & BGE_FIBER_TBI) &&
4829
	    !(sc->bge_flags & BGE_FIBER_MII)) {
4830
		sc->bge_ifmedia.ifm_media = IFM_ETHER|IFM_10_T;
4831
		if_flags = ifp->if_flags;
4832
		ifp->if_flags |= IFF_UP;
4833
		bge_ifmedia_upd(ifp);
4834
		ifp->if_flags = if_flags;
4835
	}
4836

  
4837
	/* Disable DMA. */
4838
	BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_FRMHDR_DMA_ENB|
4839
	    BGE_MACMODE_TXDMA_ENB|BGE_MACMODE_RXDMA_ENB);
4840

  
4841
	/* Halt CPUs. */
4842
	BGE_SETBIT(sc, BGE_TXCPU_MODE, BGE_TXCPUMODE_HALTCPU);
4843
	BGE_SETBIT(sc, BGE_RXCPU_MODE, BGE_RXCPUMODE_HALTCPU);
4844

  
4845
	/* Configure the PHY for WOL mode. */
4846
	bge_miibus_writereg(&sc->bge_dev, 1, BRGPHY_MII_AUXCTL,
4847
	    BRGPHY_AUXCTL_WOL_ENBL);
4848
	BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_PORTMODE);
4849
	CSR_WRITE_4(sc, BGE_MAC_MODE, BGE_PORTMODE_MII|
4850
	    BGE_MACMODE_LINK_POLARITY|BGE_MACMODE_MAGIC_PKT_ENB);
4851
	DELAY(100);
4852

  
4853
	/* Disable RX and TX CPUs, enable alternate clock. */
4854
	BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLOCKCTL_RW);
4855
	BGE_SETBIT(sc, BGE_PCI_CLKCTL,
4856
	    BGE_PCICLOCKCTL_RXCPU_CLK_DIS|BGE_PCICLOCKCTL_TXCPU_CLK_DIS|
4857
	    BGE_PCICLOCKCTL_ALTCLK|BGE_PCICLOCKCTL_LOW_SPEED_PLL);
4858
	DELAY(500);
4859
	BGE_CLRBIT(sc, BGE_PCI_CLKCTL, BGE_PCICLOCKCTL_ALTCLK);
4860
	BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLOCKCTL_RW);
4861

  
4862
	if (sc->bge_flags & BGE_WOL_NEEDS_VAUX) {
4863
		/* Switch from main power to aux power. */
4864
		if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5700 ||
4865
		    BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5701) {
4866
			BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL,
4867
			    BGE_MLC_INTR_ONATTN|BGE_MLC_AUTO_EEPROM|
4868
			    BGE_MLC_MISCIO_OUTEN0|BGE_MLC_MISCIO_OUTEN1|
4869
			    BGE_MLC_MISCIO_OUTEN2|
4870
			    BGE_MLC_MISCIO_OUT0|BGE_MLC_MISCIO_OUT1);
4871
			DELAY(100);
4872
		} else if (PCI_PRODUCT(pa->pa_id) ==
4873
		    PCI_PRODUCT_BROADCOM_BCM5761 ||
4874
		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_BCM5761S) {
4875
			/* These have GPIO 0 and GPIO 2 swapped. */
4876
			reg = (BGE_MLC_INTR_ONATTN|BGE_MLC_AUTO_EEPROM|
4877
			    BGE_MLC_MISCIO_OUTEN0|BGE_MLC_MISCIO_OUTEN1|
4878
			    BGE_MLC_MISCIO_OUTEN2|
4879
			    BGE_MLC_MISCIO_OUT0|BGE_MLC_MISCIO_OUT1);
4880
			BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
4881
			DELAY(100);
4882
			reg |= BGE_MLC_MISCIO_OUT2;
4883
			BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
4884
			DELAY(100);
4885
			reg &= ~BGE_MLC_MISCIO_OUT0;
4886
			BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
4887
			DELAY(100);
4888
		} else {
4889
			reg = 0;
4890

  
4891
			/* Workaround for drawing too much power. */
4892
			if (BGE_ASICREV(sc->bge_chipid) ==
4893
			    BGE_ASICREV_BCM5714) {
4894
				reg |= BGE_MLC_MISCIO_OUTEN3;	
4895
				BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
4896
				DELAY(100);
4897
			}
4898

  
4899
			if (sc->bge_flags & BGE_NO_GPIO2) {
4900
				reg |= (BGE_MLC_MISCIO_OUTEN0|
4901
				    BGE_MLC_MISCIO_OUTEN1|
4902
				    BGE_MLC_MISCIO_OUT1);
4903
			} else {
4904
				reg |= (BGE_MLC_MISCIO_OUTEN0|
4905
				    BGE_MLC_MISCIO_OUTEN1|
4906
				    BGE_MLC_MISCIO_OUTEN2|
4907
				    BGE_MLC_MISCIO_OUT1|
4908
				    BGE_MLC_MISCIO_OUT2);
4909
			}
4910

  
4911
			BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
4912
			DELAY(100);
4913

  
4914
			reg |= BGE_MLC_MISCIO_OUT0;
4915
			BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
4916
			DELAY(100);
4917

  
4918
			if (!(sc->bge_flags & BGE_NO_GPIO2)) {
4919
				reg &= ~BGE_MLC_MISCIO_OUT2;
4920
				BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, reg);
4921
				DELAY(100);
4922
			}
4923
		}
4924
	} else if (BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5700 &&
4925
		   BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5701) {
4926
		/* Die with vmain power. */
4927
		BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL,
4928
		    BGE_MLC_MISCIO_OUT1|BGE_MLC_MISCIO_OUTEN1);
4929
		DELAY(100);
4930
		BGE_CLRBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUT1);
4931
		DELAY(100);
4932
		BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUT1);
4933
		DELAY(100);
4934
	}
4935

  
4936
	/* Re-enable RX in promiscuous mode. */
4937
	BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE|BGE_RXMODE_RX_PROMISC);
4938

  
4939
	/* Enable PME assertion and put the device to sleep. */
4940
	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
4941
	    &offset, &reg)) {
4942
		pci_conf_write(pa->pa_pc, pa->pa_tag, offset + PCI_PMCSR,
4943
		    reg|PCI_PMCSR_PME_EN);
4944
		pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D3);
4945
	}
4946

  
4947
	splx(s);
4948
}
4949
#endif
sys/dev/pci/if_bgereg.h 23 Apr 2014 15:14:07 -0000
80 80
#define	   BGE_VER_SHIFT			16
81 81
#define	BGE_SOFTWARE_GENCOMM_FW		0x00000B78
82 82
#define	   BGE_FW_PAUSE				0x00000002
83
#define BGE_SOFTWARE_GENCOMM_WOL	0x00000D30
83 84
#define	BGE_SOFTWARE_GENCOMM_NICCFG2	0x00000D38
84 85
#define	BGE_SOFTWARE_GENCOMM_NICCFG3	0x00000D3C
85 86
#define	BGE_SOFTWARE_GENCOMM_NICCFG4	0x00000D60
......
438 439
#define	BGE_PCICLOCKCTL_PCIPLL_DISABLE	0x00004000
439 440
#define	BGE_PCICLOCKCTL_SYSPLL_DISABLE	0x00008000
440 441
#define	BGE_PCICLOCKCTL_BIST_ENABLE	0x00010000
442
#define BGE_PCICLOCKCTL_LOW_SPEED_PLL	0x00020000
441 443

  
442 444
/*
443 445
 * High priority mailbox registers
......
2102 2104
#define	BGE_MLC_INTR_CLR		0x00000002
2103 2105
#define	BGE_MLC_INTR_SET		0x00000004
2104 2106
#define	BGE_MLC_INTR_ONATTN		0x00000008
2107
#define	BGE_MLC_MISCIO_OUTEN3		0x00000040
2108
#define	BGE_MLC_MISCIO_OUT3		0x00000080
2105 2109
#define	BGE_MLC_MISCIO_IN0		0x00000100
2106 2110
#define	BGE_MLC_MISCIO_IN1		0x00000200
2107 2111
#define	BGE_MLC_MISCIO_IN2		0x00000400
......
2292 2296
 */
2293 2297
#define	BGE_MAGIC_NUMBER		0x4B657654
2294 2298

  
2299
/*
2300
 * This magic number needs to be written to the firmware mailbox at
2301
 * 0xd30 before WOL is configured.
2302
 */
2303
#define BGE_MAGIC_WOL_NUMBER		0x474C0000
2304

  
2295 2305
typedef struct {
2296 2306
	u_int32_t		bge_addr_hi;
2297 2307
	u_int32_t		bge_addr_lo;
......
2470 2480
 */
2471 2481
#define	BGE_EE_MAC_OFFSET		0x7C
2472 2482
#define	BGE_EE_MAC_OFFSET_5906		0x10
2483
#define	BGE_EE_FEATURE_CFG_OFFSET	0xC4
2473 2484
#define	BGE_EE_HWCFG_OFFSET		0xC8
2474 2485

  
2475 2486
#define	BGE_HWCFG_VOLTAGE		0x00000003
2476 2487
#define	BGE_HWCFG_PHYLED_MODE		0x0000000C
2477 2488
#define	BGE_HWCFG_MEDIA			0x00000030
2478 2489
#define	BGE_HWCFG_ASF			0x00000080
2490
#define BGE_HWCFG_EEPROM_WRITE_PROTECT	0x00000100
2491
#define BGE_HWCFG_NO_GPIO2		0x00100000
2479 2492

  
2480 2493
#define	BGE_VOLTAGE_1POINT3		0x00000000
2481 2494
#define	BGE_VOLTAGE_1POINT8		0x00000001
......
2869 2882
#define	BGE_TAGGED_STATUS	0x00200000
2870 2883
#define	BGE_MSI			0x00400000
2871 2884
#define	BGE_RDMA_BUG		0x00800000
2885
#define BGE_WOL			0x04000000
2886
#define BGE_WOL_NEEDS_VAUX	0x08000000
2887
#define BGE_NO_GPIO2		0x10000000
2872 2888

  
2873 2889
	u_int32_t		bge_phy_flags;
2874 2890
#define	BGE_PHY_NO_3LED		0x00000001