Skip to content

Instantly share code, notes, and snippets.

@nonakap
Created February 19, 2015 06:30
Show Gist options
  • Select an option

  • Save nonakap/9874e60db55dd6ac1abf to your computer and use it in GitHub Desktop.

Select an option

Save nonakap/9874e60db55dd6ac1abf to your computer and use it in GitHub Desktop.
NetBSD iwm(4) temp patch
Index: if_iwm.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.9
diff -u -r1.9 if_iwm.c
--- if_iwm.c 17 Feb 2015 09:18:45 -0000 1.9
+++ if_iwm.c 18 Feb 2015 01:38:27 -0000
@@ -253,6 +253,8 @@
static int iwm_prepare_card_hw(struct iwm_softc *);
static void iwm_apm_config(struct iwm_softc *);
static int iwm_apm_init(struct iwm_softc *);
+static void iwl_apm_lp_xtal_enable(struct iwm_softc *);
+static void iwm_apm_stop_master(struct iwm_softc *);
static void iwm_apm_stop(struct iwm_softc *);
static int iwm_start_hw(struct iwm_softc *);
static void iwm_stop_device(struct iwm_softc *);
@@ -1373,40 +1375,46 @@
static int
iwm_set_hw_ready(struct iwm_softc *sc)
{
+ int rv;
+
IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
- return iwm_poll_bit(sc, IWM_CSR_HW_IF_CONFIG_REG,
+ rv = iwm_poll_bit(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
IWM_HW_READY_TIMEOUT);
+ if (rv != 0) {
+ IWM_SETBITS(sc, IWM_CSR_MBOX_SET_REG,
+ IWM_CSR_MBOX_SET_REG_OS_ALIVE);
+ }
+ return rv;
}
#undef IWM_HW_READY_TIMEOUT
static int
iwm_prepare_card_hw(struct iwm_softc *sc)
{
- int rv = 0;
int t = 0;
- if (!iwm_set_hw_ready(sc))
- goto out;
-
- /* If HW is not ready, prepare the conditions to check again */
- IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
- IWM_CSR_HW_IF_CONFIG_REG_PREPARE);
-
- do {
- if (iwm_set_hw_ready(sc))
- goto out;
- DELAY(200);
- t += 200;
- } while (t < 150000);
+ if (iwm_set_hw_ready(sc))
+ return 0;
- rv = ETIMEDOUT;
+ for (int i = 0; i < 10; ++i) {
+ /* If HW is not ready, prepare the conditions to check again */
+ IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
+ IWM_CSR_HW_IF_CONFIG_REG_PREPARE);
+
+ do {
+ if (iwm_set_hw_ready(sc))
+ return 0;
+ DELAY(200);
+ t += 200;
+ } while (t < 150000);
+ DELAY(25000);
+ }
- out:
- return rv;
+ return ETIMEDOUT;
}
static void
@@ -1534,9 +1542,135 @@
}
/* iwlwifi/pcie/trans.c */
+static uint32_t
+iwm_read_shr(struct iwm_softc *sc, uint32_t reg)
+{
+
+ IWM_WRITE(sc, IWM_HEEP_CTRL_WRD_PCIEX_CTRL_REG,
+ ((reg & 0x0000ffff) | (2 << 28)));
+ return IWM_READ(sc, IWM_HEEP_CTRL_WRD_PCIEX_DATA_REG);
+}
+
+/* iwlwifi pcie/trans.c */
static void
-iwm_apm_stop(struct iwm_softc *sc)
+iwm_write_shr(struct iwm_softc *sc, uint32_t reg, uint32_t value)
{
+
+ IWM_WRITE(sc, IWM_HEEP_CTRL_WRD_PCIEX_DATA_REG, value);
+ IWM_WRITE(sc, IWM_HEEP_CTRL_WRD_PCIEX_CTRL_REG,
+ ((reg & 0x0000ffff) | (3 << 28)));
+}
+
+/* iwlwifi pcie/trans.c */
+/*
+ * Enable LP XTAL to avoid HW bug where device may consume much power if
+ * FW is not loaded after device reset. LP XTAL is disabled by default
+ * after device HW reset. Do it only if XTAL is fed by internal source.
+ * Configure device's "persistence" mode to avoid resetting XTAL again when
+ * SHRD_HW_RST occurs in S3.
+ */
+static void
+iwl_apm_lp_xtal_enable(struct iwm_softc *sc)
+{
+ uint32_t apmg_xtal_cfg_reg;
+ uint32_t apmg_gp1_reg;
+ uint32_t dl_cfg_reg;
+
+ /* Force XTAL ON */
+ IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
+
+ /* Reset entire device - do controller reset (results in SHRD_HW_RST) */
+ IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET);
+
+ DELAY(10);
+
+ /*
+ * Set "initialization complete" bit to move adapter from
+ * D0U* --> D0A* (powered-up active) state.
+ */
+ IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+ /*
+ * Wait for clock stabilization; once stabilized, access to
+ * device-internal resources is possible.
+ */
+ if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
+ IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {
+ aprint_error_dev(sc->sc_dev,
+ "Access time out - failed to enable LP XTAL\n");
+ /* Release XTAL ON request */
+ IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
+ IWM_CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
+ return;
+ }
+
+ /*
+ * Clear "disable persistence" to avoid LP XTAL resetting when
+ * SHRD_HW_RST is applied in S3.
+ */
+ iwm_clear_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
+ IWM_APMG_PCIDEV_STT_VAL_PERSIST_DIS);
+
+ /*
+ * Force APMG XTAL to be active to prevent its disabling by HW
+ * caused by APMG idle state.
+ */
+ apmg_xtal_cfg_reg = iwm_read_shr(sc, IWM_SHR_APMG_XTAL_CFG_REG);
+ iwm_write_shr(sc, IWM_SHR_APMG_XTAL_CFG_REG,
+ apmg_xtal_cfg_reg | IWM_SHR_APMG_XTAL_CFG_XTAL_ON_REQ);
+
+ /*
+ * Reset entire device again - do controller reset (results in
+ * SHRD_HW_RST). Turn MAC off before proceeding.
+ */
+ IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET);
+
+ DELAY(10);
+
+ /* Enable LP XTAL by indirect access through CSR */
+ apmg_gp1_reg = iwm_read_shr(sc, IWM_SHR_APMG_GP1_REG);
+ iwm_write_shr(sc, IWM_SHR_APMG_GP1_REG,
+ apmg_gp1_reg
+ | IWM_SHR_APMG_GP1_WF_XTAL_LP_EN
+ | IWM_SHR_APMG_GP1_CHICKEN_BIT_SELECT);
+
+ /* Clear delay line clock power up */
+ dl_cfg_reg = iwm_read_shr(sc, IWM_SHR_APMG_DL_CFG_REG);
+ iwm_write_shr(sc, IWM_SHR_APMG_DL_CFG_REG,
+ dl_cfg_reg & ~IWM_SHR_APMG_DL_CFG_DL_CLOCK_POWER_UP);
+
+ /*
+ * Enable persistence mode to avoid LP XTAL resetting when
+ * SHRD_HW_RST is applied in S3.
+ */
+ IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
+ IWM_CSR_HW_IF_CONFIG_REG_PERSIST_MODE);
+
+ /*
+ * Clear "initialization complete" bit to move adapter from
+ * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
+ */
+ IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+ /* Activates XTAL resources monitor */
+ IWM_SETBITS(sc, IWM_CSR_MONITOR_CFG_REG,
+ IWM_CSR_MONITOR_XTAL_RESOURCES);
+
+ /* Release XTAL ON request */
+ IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
+ DELAY(10);
+
+ /* Release APMG XTAL */
+ iwm_write_shr(sc, IWM_SHR_APMG_XTAL_CFG_REG,
+ apmg_xtal_cfg_reg & ~IWM_SHR_APMG_XTAL_CFG_XTAL_ON_REQ);
+}
+
+/* iwlwifi pcie/trans.c */
+static void
+iwm_apm_stop_master(struct iwm_softc *sc)
+{
+
/* stop device's busmaster DMA activity */
IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_STOP_MASTER);
@@ -1544,6 +1678,29 @@
IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED,
IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED, 100))
aprint_error_dev(sc->sc_dev, "timeout waiting for master\n");
+}
+
+/* iwlwifi pcie/trans.c */
+static void
+iwm_apm_stop(struct iwm_softc *sc)
+{
+
+ iwm_apm_stop_master(sc);
+
+ if (sc->sc_flags & IWM_FLAG_LP_XTAL_WORKAROUND)
+ iwl_apm_lp_xtal_enable(sc);
+
+ /* Reset the entire device */
+ IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET);
+
+ DELAY(10);
+
+ /*
+ * Clear "initialization complete" bit to move adapter from
+ * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
+ */
+ IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
DPRINTF(("iwm apm stop\n"));
}
@@ -1572,7 +1729,6 @@
}
/* iwlwifi pcie/trans.c */
-
static void
iwm_stop_device(struct iwm_softc *sc)
{
@@ -1586,7 +1742,6 @@
sc->sc_flags &= ~IWM_FLAG_USE_ICT;
/* stop tx and rx. tx and rx bits, as usual, are from if_iwn */
-
iwm_write_prph(sc, IWM_SCD_TXFACT, 0);
/* Stop all DMA channels. */
@@ -6654,6 +6809,7 @@
case PCI_PRODUCT_INTEL_WIFI_LINK_7260_1:
case PCI_PRODUCT_INTEL_WIFI_LINK_7260_2:
sc->sc_fwname = "iwlwifi-7260-9.ucode";
+ sc->sc_flags |= IWM_FLAG_LP_XTAL_WORKAROUND;
break;
case PCI_PRODUCT_INTEL_WIFI_LINK_3160_1:
case PCI_PRODUCT_INTEL_WIFI_LINK_3160_2:
Index: if_iwmreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_iwmreg.h,v
retrieving revision 1.2
diff -u -r1.2 if_iwmreg.h
--- if_iwmreg.h 16 Feb 2015 13:22:19 -0000 1.2
+++ if_iwmreg.h 18 Feb 2015 01:38:27 -0000
@@ -131,6 +131,8 @@
#define IWM_CSR_UCODE_DRV_GP1_CLR (0x05c)
#define IWM_CSR_UCODE_DRV_GP2 (0x060)
+#define IWM_CSR_MBOX_SET_REG (0x088)
+
#define IWM_CSR_LED_REG (0x094)
#define IWM_CSR_DRAM_INT_TBL_REG (0x0A0)
#define IWM_CSR_MAC_SHADOW_REG_CTRL (0x0A8) /* 6000 and up */
@@ -143,6 +145,13 @@
#define IWM_CSR_ANA_PLL_CFG (0x20c)
/*
+ * CSR HW resources monitor registers
+ */
+#define IWM_CSR_MONITOR_CFG_REG (0x214)
+#define IWM_CSR_MONITOR_STATUS_REG (0x228)
+#define IWM_CSR_MONITOR_XTAL_RESOURCES (0x00000010)
+
+/*
* CSR Hardware Revision Workaround Register. Indicates hardware rev;
* "step" determines CCK backoff for txpower calculation. Used for 4965 only.
* See also IWM_CSR_HW_REV register.
@@ -177,6 +186,10 @@
#define IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */
#define IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */
#define IWM_CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */
+#define IWM_CSR_HW_IF_CONFIG_REG_ENABLE_PME (0x10000000)
+#define IWM_CSR_HW_IF_CONFIG_REG_PERSIST_MODE (0x40000000) /* PERSISTENCE */
+
+#define IWM_CSR_MBOX_SET_REG_OS_ALIVE __BIT(5)
#define IWM_CSR_INT_PERIODIC_DIS (0x00) /* disable periodic int*/
#define IWM_CSR_INT_PERIODIC_ENA (0xFF) /* 255*32 usec ~ 8 msec*/
@@ -275,6 +288,7 @@
#define IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
#define IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
#define IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
+#define IWM_CSR_GP_CNTRL_REG_FLAG_XTAL_ON (0x00000400)
#define IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
@@ -432,6 +446,34 @@
#define IWM_FH_TCSR_0_REG0 (0x1D00)
/*
+ * SHR target access (Shared block memory space)
+ *
+ * Shared internal registers can be accessed directly from PCI bus through SHR
+ * arbiter without need for the MAC HW to be powered up. This is possible due to
+ * indirect read/write via HEEP_CTRL_WRD_PCIEX_CTRL (0xEC) and
+ * HEEP_CTRL_WRD_PCIEX_DATA (0xF4) registers.
+ *
+ * Use iwl_write32()/iwl_read32() family to access these registers. The MAC HW
+ * need not be powered up so no "grab inc access" is required.
+ */
+
+/*
+ * Registers for accessing shared registers (e.g. SHR_APMG_GP1,
+ * SHR_APMG_XTAL_CFG). For example, to read from SHR_APMG_GP1 register (0x1DC),
+ * first, write to the control register:
+ * HEEP_CTRL_WRD_PCIEX_CTRL[15:0] = 0x1DC (offset of the SHR_APMG_GP1 register)
+ * HEEP_CTRL_WRD_PCIEX_CTRL[29:28] = 2 (read access)
+ * second, read from the data register HEEP_CTRL_WRD_PCIEX_DATA[31:0].
+ *
+ * To write the register, first, write to the data register
+ * HEEP_CTRL_WRD_PCIEX_DATA[31:0] and then:
+ * HEEP_CTRL_WRD_PCIEX_CTRL[15:0] = 0x1DC (offset of the SHR_APMG_GP1 register)
+ * HEEP_CTRL_WRD_PCIEX_CTRL[29:28] = 3 (write access)
+ */
+#define IWM_HEEP_CTRL_WRD_PCIEX_CTRL_REG (0x0ec)
+#define IWM_HEEP_CTRL_WRD_PCIEX_DATA_REG (0x0f4)
+
+/*
* HBUS (Host-side Bus)
*
* HBUS registers are mapped directly into PCI bus space, but are used
@@ -833,7 +875,9 @@
#define IWM_APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */
#define IWM_APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060)
+#define IWM_APMG_PCIDEV_STT_VAL_PERSIST_DIS (0x00000200)
#define IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
+#define IWM_APMG_PCIDEV_STT_VAL_WAKE_ME (0x00004000)
#define IWM_APMG_RTC_INT_STT_RFKILL (0x10000000)
@@ -842,6 +886,28 @@
/* Device NMI register */
#define IWM_DEVICE_SET_NMI_REG 0x00a01c30
+#define DEVICE_SET_NMI_VAL_HW __BIT(0)
+#define DEVICE_SET_NMI_VAL_DRV __BIT(7)
+
+/* Shared registers (0x0..0x3ff, via target indirect or periphery */
+#define IWM_SHR_BASE 0x00a10000
+
+/* Shared GP1 register */
+#define IWM_SHR_APMG_GP1_REG 0x01dc
+#define IWM_SHR_APMG_GP1_REG_PRPH (IWM_SHR_BASE + IWM_SHR_APMG_GP1_REG)
+#define IWM_SHR_APMG_GP1_WF_XTAL_LP_EN 0x00000004
+#define IWM_SHR_APMG_GP1_CHICKEN_BIT_SELECT 0x80000000
+
+/* Shared DL_CFG register */
+#define IWM_SHR_APMG_DL_CFG_REG 0x01c4
+#define IWM_SHR_APMG_DL_CFG_REG_PRPH (IWM_SHR_BASE + IWM_SHR_APMG_DL_CFG_REG)
+#define IWM_SHR_APMG_DL_CFG_RTCS_CLK_SELECTOR_MSK 0x000000c0
+#define IWM_SHR_APMG_DL_CFG_RTCS_CLK_INTERNAL_XTAL 0x00000080
+#define IWM_SHR_APMG_DL_CFG_DL_CLOCK_POWER_UP 0x00000100
+
+/* Shared APMG_XTAL_CFG register */
+#define IWM_SHR_APMG_XTAL_CFG_REG 0x1c0
+#define IWM_SHR_APMG_XTAL_CFG_XTAL_ON_REQ 0x80000000
/*****************************************************************************
* 7000/3000 series SHR DTS addresses *
Index: if_iwmvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_iwmvar.h,v
retrieving revision 1.4
diff -u -r1.4 if_iwmvar.h
--- if_iwmvar.h 16 Feb 2015 13:22:19 -0000 1.4
+++ if_iwmvar.h 18 Feb 2015 01:38:27 -0000
@@ -287,12 +287,13 @@
int cur;
};
-#define IWM_FLAG_USE_ICT 0x01
-#define IWM_FLAG_HW_INITED 0x02
-#define IWM_FLAG_STOPPED 0x04
-#define IWM_FLAG_RFKILL 0x08
-#define IWM_FLAG_BUSY 0x10
-#define IWM_FLAG_ATTACHED 0x20
+#define IWM_FLAG_USE_ICT 0x01
+#define IWM_FLAG_HW_INITED 0x02
+#define IWM_FLAG_STOPPED 0x04
+#define IWM_FLAG_RFKILL 0x08
+#define IWM_FLAG_BUSY 0x10
+#define IWM_FLAG_ATTACHED 0x20
+#define IWM_FLAG_LP_XTAL_WORKAROUND 0x40
struct iwm_ucode_status {
uint32_t uc_error_event_table;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment