svn commit: r295874 - head/sys/dev/usb/wlan

Andriy Voskoboinyk avos at FreeBSD.org
Mon Feb 22 01:15:04 UTC 2016


Author: avos
Date: Mon Feb 22 01:15:02 2016
New Revision: 295874
URL: https://svnweb.freebsd.org/changeset/base/295874

Log:
  urtwn: shutdown the device properly
  
  - R92C path: NetBSD (mostly)
  - R88E path: TP-Link driver
  
  Tested with RTL8188EU and RTL8188CUS.
  
  Reviewed by:	kevlo
  Approved by:	adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D5198

Modified:
  head/sys/dev/usb/wlan/if_urtwn.c
  head/sys/dev/usb/wlan/if_urtwnreg.h
  head/sys/dev/usb/wlan/if_urtwnvar.h

Modified: head/sys/dev/usb/wlan/if_urtwn.c
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwn.c	Mon Feb 22 00:58:04 2016	(r295873)
+++ head/sys/dev/usb/wlan/if_urtwn.c	Mon Feb 22 01:15:02 2016	(r295874)
@@ -308,6 +308,8 @@ static void		urtwn_start(struct urtwn_so
 static void		urtwn_parent(struct ieee80211com *);
 static int		urtwn_r92c_power_on(struct urtwn_softc *);
 static int		urtwn_r88e_power_on(struct urtwn_softc *);
+static void		urtwn_r92c_power_off(struct urtwn_softc *);
+static void		urtwn_r88e_power_off(struct urtwn_softc *);
 static int		urtwn_llt_init(struct urtwn_softc *);
 #ifndef URTWN_WITHOUT_UCODE
 static void		urtwn_fw_reset(struct urtwn_softc *);
@@ -1782,6 +1784,7 @@ urtwn_read_rom(struct urtwn_softc *sc)
 
 	sc->sc_rf_write = urtwn_r92c_rf_write;
 	sc->sc_power_on = urtwn_r92c_power_on;
+	sc->sc_power_off = urtwn_r92c_power_off;
 
 	return (0);
 }
@@ -1809,6 +1812,7 @@ urtwn_r88e_read_rom(struct urtwn_softc *
 
 	sc->sc_rf_write = urtwn_r88e_rf_write;
 	sc->sc_power_on = urtwn_r88e_power_on;
+	sc->sc_power_off = urtwn_r88e_power_off;
 
 	return (0);
 }
@@ -3235,7 +3239,7 @@ urtwn_r88e_power_on(struct urtwn_softc *
 
 	/* Enable LDO normal mode. */
 	error = urtwn_write_1(sc, R92C_LPLDO_CTRL,
-	    urtwn_read_1(sc, R92C_LPLDO_CTRL) & ~0x10);
+	    urtwn_read_1(sc, R92C_LPLDO_CTRL) & ~R92C_LPLDO_CTRL_SLEEP);
 	if (error != USB_ERR_NORMAL_COMPLETION)
 		return (EIO);
 
@@ -3254,6 +3258,269 @@ urtwn_r88e_power_on(struct urtwn_softc *
 	return (0);
 }
 
+static __inline void
+urtwn_power_off(struct urtwn_softc *sc)
+{
+
+	return sc->sc_power_off(sc);
+}
+
+static void
+urtwn_r92c_power_off(struct urtwn_softc *sc)
+{
+	uint32_t reg;
+
+	/* Block all Tx queues. */
+	urtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
+
+	/* Disable RF */
+	urtwn_rf_write(sc, 0, 0, 0);
+
+	urtwn_write_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF);
+
+	/* Reset BB state machine */
+	urtwn_write_1(sc, R92C_SYS_FUNC_EN,
+	    R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA |
+	    R92C_SYS_FUNC_EN_BB_GLB_RST);
+	urtwn_write_1(sc, R92C_SYS_FUNC_EN,
+	    R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA);
+
+	/*
+	 * Reset digital sequence
+	 */
+#ifndef URTWN_WITHOUT_UCODE
+	if (urtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY) {
+		/* Reset MCU ready status */
+		urtwn_write_1(sc, R92C_MCUFWDL, 0);
+
+		/* If firmware in ram code, do reset */
+		urtwn_fw_reset(sc);
+	}
+#endif
+
+	/* Reset MAC and Enable 8051 */
+	urtwn_write_1(sc, R92C_SYS_FUNC_EN + 1,
+	    (R92C_SYS_FUNC_EN_CPUEN |
+	     R92C_SYS_FUNC_EN_ELDR |
+	     R92C_SYS_FUNC_EN_HWPDN) >> 8);
+
+	/* Reset MCU ready status */
+	urtwn_write_1(sc, R92C_MCUFWDL, 0);
+
+	/* Disable MAC clock */
+	urtwn_write_2(sc, R92C_SYS_CLKR,
+	    R92C_SYS_CLKR_ANAD16V_EN |
+	    R92C_SYS_CLKR_ANA8M |
+	    R92C_SYS_CLKR_LOADER_EN | 
+	    R92C_SYS_CLKR_80M_SSC_DIS |
+	    R92C_SYS_CLKR_SYS_EN |
+	    R92C_SYS_CLKR_RING_EN |
+	    0x4000);
+
+	/* Disable AFE PLL */
+	urtwn_write_1(sc, R92C_AFE_PLL_CTRL, 0x80);
+
+	/* Gated AFE DIG_CLOCK */
+	urtwn_write_2(sc, R92C_AFE_XTAL_CTRL, 0x880F);
+
+	/* Isolated digital to PON */
+	urtwn_write_1(sc, R92C_SYS_ISO_CTRL,
+	    R92C_SYS_ISO_CTRL_MD2PP |
+	    R92C_SYS_ISO_CTRL_PA2PCIE |
+	    R92C_SYS_ISO_CTRL_PD2CORE |
+	    R92C_SYS_ISO_CTRL_IP2MAC |
+	    R92C_SYS_ISO_CTRL_DIOP |
+	    R92C_SYS_ISO_CTRL_DIOE);
+
+	/*
+	 * Pull GPIO PIN to balance level and LED control
+	 */
+	/* 1. Disable GPIO[7:0] */
+	urtwn_write_2(sc, R92C_GPIO_IOSEL, 0x0000);
+
+	reg = urtwn_read_4(sc, R92C_GPIO_PIN_CTRL) & ~0x0000ff00;
+	reg |= ((reg << 8) & 0x0000ff00) | 0x00ff0000;
+	urtwn_write_4(sc, R92C_GPIO_PIN_CTRL, reg);
+
+	/* Disable GPIO[10:8] */
+	urtwn_write_1(sc, R92C_MAC_PINMUX_CFG, 0x00);
+
+	reg = urtwn_read_2(sc, R92C_GPIO_IO_SEL) & ~0x00f0;
+	reg |= (((reg & 0x000f) << 4) | 0x0780);
+	urtwn_write_2(sc, R92C_GPIO_IO_SEL, reg);
+
+	/* Disable LED0 & 1 */
+	urtwn_write_2(sc, R92C_LEDCFG0, 0x8080);
+
+	/*
+	 * Reset digital sequence
+	 */
+	/* Disable ELDR clock */
+	urtwn_write_2(sc, R92C_SYS_CLKR,
+	    R92C_SYS_CLKR_ANAD16V_EN |
+	    R92C_SYS_CLKR_ANA8M |
+	    R92C_SYS_CLKR_LOADER_EN |
+	    R92C_SYS_CLKR_80M_SSC_DIS |
+	    R92C_SYS_CLKR_SYS_EN |
+	    R92C_SYS_CLKR_RING_EN |
+	    0x4000);
+
+	/* Isolated ELDR to PON */
+	urtwn_write_1(sc, R92C_SYS_ISO_CTRL + 1,
+	    (R92C_SYS_ISO_CTRL_DIOR |
+	     R92C_SYS_ISO_CTRL_PWC_EV12V) >> 8);
+
+	/*
+	 * Disable analog sequence
+	 */
+	/* Disable A15 power */
+	urtwn_write_1(sc, R92C_LDOA15_CTRL, R92C_LDOA15_CTRL_OBUF);
+	/* Disable digital core power */
+	urtwn_write_1(sc, R92C_LDOV12D_CTRL,
+	    urtwn_read_1(sc, R92C_LDOV12D_CTRL) &
+	      ~R92C_LDOV12D_CTRL_LDV12_EN);
+
+	/* Enter PFM mode */
+	urtwn_write_1(sc, R92C_SPS0_CTRL, 0x23);
+
+	/* Set USB suspend */
+	urtwn_write_2(sc, R92C_APS_FSMCO,
+	    R92C_APS_FSMCO_APDM_HOST |
+	    R92C_APS_FSMCO_AFSM_HSUS |
+	    R92C_APS_FSMCO_PFM_ALDN);
+
+	/* Lock ISO/CLK/Power control register. */
+	urtwn_write_1(sc, R92C_RSV_CTRL, 0x0E);
+}
+
+static void
+urtwn_r88e_power_off(struct urtwn_softc *sc)
+{
+	uint8_t reg;
+	int ntries;
+
+	/* Disable any kind of TX reports. */
+	urtwn_write_1(sc, R88E_TX_RPT_CTRL,
+	    urtwn_read_1(sc, R88E_TX_RPT_CTRL) &
+	      ~(R88E_TX_RPT1_ENA | R88E_TX_RPT2_ENA));
+
+	/* Stop Rx. */
+	urtwn_write_1(sc, R92C_CR, 0);
+
+	/* Move card to Low Power State. */
+	/* Block all Tx queues. */
+	urtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
+
+	for (ntries = 0; ntries < 20; ntries++) {
+		/* Should be zero if no packet is transmitting. */
+		if (urtwn_read_4(sc, R88E_SCH_TXCMD) == 0)
+			break;
+
+		urtwn_ms_delay(sc);
+	}
+	if (ntries == 20) {
+		device_printf(sc->sc_dev, "%s: failed to block Tx queues\n",
+		    __func__);
+		return;
+	}
+
+	/* CCK and OFDM are disabled, and clock are gated. */
+	urtwn_write_1(sc, R92C_SYS_FUNC_EN,
+	    urtwn_read_1(sc, R92C_SYS_FUNC_EN) & ~R92C_SYS_FUNC_EN_BBRSTB);
+
+	urtwn_ms_delay(sc);
+
+	/* Reset MAC TRX */
+	urtwn_write_1(sc, R92C_CR,
+	    R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
+	    R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN |
+	    R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN);
+
+	/* check if removed later */
+	urtwn_write_1(sc, R92C_CR + 1,
+	    urtwn_read_1(sc, R92C_CR + 1) & ~(R92C_CR_ENSEC >> 8));
+
+	/* Respond TxOK to scheduler */
+	urtwn_write_1(sc, R92C_DUAL_TSF_RST,
+	    urtwn_read_1(sc, R92C_DUAL_TSF_RST) | 0x20);
+
+	/* If firmware in ram code, do reset. */
+#ifndef URTWN_WITHOUT_UCODE
+	if (urtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY)
+		urtwn_r88e_fw_reset(sc);
+#endif
+
+	/* Reset MCU ready status. */
+	urtwn_write_1(sc, R92C_MCUFWDL, 0x00);
+
+	/* Disable 32k. */
+	urtwn_write_1(sc, R88E_32K_CTRL,
+	    urtwn_read_1(sc, R88E_32K_CTRL) & ~0x01);
+
+	/* Move card to Disabled state. */
+	/* Turn off RF. */
+	urtwn_write_1(sc, R92C_RF_CTRL, 0);
+
+	/* LDO Sleep mode. */
+	urtwn_write_1(sc, R92C_LPLDO_CTRL, 
+	    urtwn_read_1(sc, R92C_LPLDO_CTRL) | R92C_LPLDO_CTRL_SLEEP);
+
+	/* Turn off MAC by HW state machine */
+	urtwn_write_1(sc, R92C_APS_FSMCO + 1,
+	    urtwn_read_1(sc, R92C_APS_FSMCO + 1) |
+	    (R92C_APS_FSMCO_APFM_OFF >> 8));
+
+	for (ntries = 0; ntries < 20; ntries++) {
+		/* Wait until it will be disabled. */
+		if ((urtwn_read_1(sc, R92C_APS_FSMCO + 1) &
+		    (R92C_APS_FSMCO_APFM_OFF >> 8)) == 0)
+			break;
+
+		urtwn_ms_delay(sc);
+	}
+	if (ntries == 20) {
+		device_printf(sc->sc_dev, "%s: could not turn off MAC\n",
+		    __func__);
+		return;
+	}
+
+	/* schmit trigger */
+	urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 2,
+	    urtwn_read_1(sc, R92C_AFE_XTAL_CTRL + 2) | 0x80);
+
+	/* Enable WL suspend. */
+	urtwn_write_1(sc, R92C_APS_FSMCO + 1,
+	    (urtwn_read_1(sc, R92C_APS_FSMCO + 1) & ~0x10) | 0x08);
+
+	/* Enable bandgap mbias in suspend. */
+	urtwn_write_1(sc, R92C_APS_FSMCO + 3, 0);
+
+	/* Clear SIC_EN register. */
+	urtwn_write_1(sc, R92C_GPIO_MUXCFG + 1,
+	    urtwn_read_1(sc, R92C_GPIO_MUXCFG + 1) & ~0x10);
+
+	/* Set USB suspend enable local register */
+	urtwn_write_1(sc, R92C_USB_SUSPEND,
+	    urtwn_read_1(sc, R92C_USB_SUSPEND) | 0x10);
+
+	/* Reset MCU IO Wrapper. */
+	reg = urtwn_read_1(sc, R92C_RSV_CTRL + 1);
+	urtwn_write_1(sc, R92C_RSV_CTRL + 1, reg & ~0x08);
+	urtwn_write_1(sc, R92C_RSV_CTRL + 1, reg | 0x08);
+
+	/* marked as 'For Power Consumption' code. */
+	urtwn_write_1(sc, R92C_GPIO_OUT, urtwn_read_1(sc, R92C_GPIO_IN));
+	urtwn_write_1(sc, R92C_GPIO_IOSEL, 0xff);
+
+	urtwn_write_1(sc, R92C_GPIO_IO_SEL,
+	    urtwn_read_1(sc, R92C_GPIO_IO_SEL) << 4);
+	urtwn_write_1(sc, R92C_GPIO_MOD,
+	    urtwn_read_1(sc, R92C_GPIO_MOD) | 0x0f);
+
+	/* Set LNA, TRSW, EX_PA Pin to output mode. */
+	urtwn_write_4(sc, R88E_BB_PAD_CTRL, 0x00080808);
+}
+
 static int
 urtwn_llt_init(struct urtwn_softc *sc)
 {
@@ -4910,9 +5177,10 @@ urtwn_stop(struct urtwn_softc *sc)
 	    URTWN_TEMP_MEASURED);
 	sc->thcal_lctemp = 0;
 	callout_stop(&sc->sc_watchdog_ch);
-	urtwn_abort_xfers(sc);
 
+	urtwn_abort_xfers(sc);
 	urtwn_drain_mbufq(sc);
+	urtwn_power_off(sc);
 	URTWN_UNLOCK(sc);
 }
 

Modified: head/sys/dev/usb/wlan/if_urtwnreg.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwnreg.h	Mon Feb 22 00:58:04 2016	(r295873)
+++ head/sys/dev/usb/wlan/if_urtwnreg.h	Mon Feb 22 01:15:02 2016	(r295874)
@@ -70,6 +70,10 @@
 #define R92C_GPIO_IO_SEL		0x042
 #define R92C_MAC_PINMUX_CFG		0x043
 #define R92C_GPIO_PIN_CTRL		0x044
+#define R92C_GPIO_IN			0x044
+#define R92C_GPIO_OUT			0x045
+#define R92C_GPIO_IOSEL			0x046
+#define R92C_GPIO_MOD			0x047
 #define R92C_GPIO_INTM			0x048
 #define R92C_LEDCFG0			0x04c
 #define R92C_LEDCFG1			0x04d
@@ -79,6 +83,7 @@
 #define R92C_FSISR			0x054
 #define R92C_HSIMR			0x058
 #define R92C_HSISR			0x05c
+#define R88E_BB_PAD_CTRL		0x064
 #define R92C_MCUFWDL			0x080
 #define R92C_HMEBOX_EXT(idx)		(0x088 + (idx) * 2)
 #define R88E_HIMR			0x0b0
@@ -117,6 +122,7 @@
 #define R92C_MBIST_START		0x174
 #define R92C_MBIST_DONE			0x178
 #define R92C_MBIST_FAIL			0x17c
+#define R88E_32K_CTRL			0x194
 #define R92C_C2HEVT_MSG_NORMAL		0x1a0
 #define R92C_C2HEVT_MSG_TEST		0x1b8
 #define R92C_C2HEVT_CLEAR		0x1bf
@@ -204,6 +210,7 @@
 #define R92C_BE_ADMTIME			0x5c8
 #define R92C_EDCA_RANDOM_GEN		0x5cc
 #define R92C_SCH_TXCMD			0x5d0
+#define R88E_SCH_TXCMD			0x5f8
 /* WMAC Configuration. */
 #define R92C_APSD_CTRL			0x600
 #define R92C_BWOPMODE			0x603
@@ -303,13 +310,30 @@
 #define R92C_RF_CTRL_RSTB	0x02
 #define R92C_RF_CTRL_SDMRSTB	0x04
 
+/* Bits for R92C_LDOA15_CTRL. */
+#define R92C_LDOA15_CTRL_EN		0x01
+#define R92C_LDOA15_CTRL_STBY		0x02
+#define R92C_LDOA15_CTRL_OBUF		0x04
+#define R92C_LDOA15_CTRL_REG_VOS	0x08
+
 /* Bits for R92C_LDOV12D_CTRL. */
 #define R92C_LDOV12D_CTRL_LDV12_EN	0x01
 
+/* Bits for R92C_LPLDO_CTRL. */
+#define R92C_LPLDO_CTRL_SLEEP		0x10
+
 /* Bits for R92C_AFE_XTAL_CTRL. */
 #define R92C_AFE_XTAL_CTRL_ADDR_M	0x007ff800
 #define R92C_AFE_XTAL_CTRL_ADDR_S	11
 
+/* Bits for R92C_AFE_PLL_CTRL. */
+#define R92C_AFE_PLL_CTRL_EN		0x0001
+#define R92C_AFE_PLL_CTRL_320_EN	0x0002
+#define R92C_AFE_PLL_CTRL_FREF_SEL	0x0004
+#define R92C_AFE_PLL_CTRL_EDGE_SEL	0x0008
+#define R92C_AFE_PLL_CTRL_WDOGB		0x0010
+#define R92C_AFE_PLL_CTRL_LPFEN		0x0020
+
 /* Bits for R92C_EFUSE_CTRL. */
 #define R92C_EFUSE_CTRL_DATA_M	0x000000ff
 #define R92C_EFUSE_CTRL_DATA_S	0
@@ -748,6 +772,7 @@
 /*
  * USB registers.
  */
+#define R92C_USB_SUSPEND		0xfe10
 #define R92C_USB_INFO			0xfe17
 #define R92C_USB_SPECIAL_OPTION		0xfe55
 #define R92C_USB_HCPWM			0xfe57

Modified: head/sys/dev/usb/wlan/if_urtwnvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwnvar.h	Mon Feb 22 00:58:04 2016	(r295873)
+++ head/sys/dev/usb/wlan/if_urtwnvar.h	Mon Feb 22 01:15:02 2016	(r295874)
@@ -172,6 +172,7 @@ struct urtwn_softc {
 	void				(*sc_rf_write)(struct urtwn_softc *,
 					    int, uint8_t, uint32_t);
 	int				(*sc_power_on)(struct urtwn_softc *);
+	void				(*sc_power_off)(struct urtwn_softc *);
 
 	struct ieee80211_node		*node_list[R88E_MACID_MAX + 1];
 	struct mtx			nt_mtx;


More information about the svn-src-all mailing list