Created
February 19, 2015 06:30
-
-
Save nonakap/9874e60db55dd6ac1abf to your computer and use it in GitHub Desktop.
NetBSD iwm(4) temp patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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