From 5aa42346bba2e385674eb1dd4019dfce4c2ef771 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:07 +0200 Subject: wl12xx: 1281/1283 support - Add Definitions Definitions to support wl128x: - New FW file name - Chip ID - New PLL Configuration Algorithm macros that will be used at wl128x boot stage - Rename NVS macro name: wl127x and wl128x are using the same NVS file name. However, the ini parameters between them are different. The driver will validate the correct NVS size in wl1271_boot_upload_nvs(). [Cleaned up some of the definitions. -- Luca] Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/spi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless/wl12xx/spi.c') diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index ffc745b17f4..80295f55f23 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -490,5 +490,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL1271_FW_NAME); +MODULE_FIRMWARE(WL128X_FW_NAME); MODULE_FIRMWARE(WL1271_AP_FW_NAME); MODULE_ALIAS("spi:wl1271"); -- cgit v1.2.3-70-g09d2 From a81159edf8d64011933df177ec42f82d7896a0c7 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 14 Mar 2011 14:05:13 +0200 Subject: wl12xx: 1281/1283 support - add block size handling for sdio and spi Add the the set_block_size op in the SDIO and in the SPI modules. Since it is only used with SDIO, just explicitly set the op to NULL in spi.c Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 18 +++++++++++++++++- drivers/net/wireless/wl12xx/spi.c | 3 ++- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/wl12xx/spi.c') diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 1b6a1adb81a..7491b3d8487 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -51,6 +51,18 @@ static const struct sdio_device_id wl1271_devices[] = { }; MODULE_DEVICE_TABLE(sdio, wl1271_devices); +/* The max SDIO block size is 256 when working with tx padding to SDIO block */ +#define TX_PAD_SDIO_BLK_SIZE 256 + +static void wl1271_sdio_set_block_size(struct wl1271 *wl) +{ + wl->block_size = TX_PAD_SDIO_BLK_SIZE; + + sdio_claim_host(wl->if_priv); + sdio_set_block_size(wl->if_priv, TX_PAD_SDIO_BLK_SIZE); + sdio_release_host(wl->if_priv); +} + static inline struct sdio_func *wl_to_func(struct wl1271 *wl) { return wl->if_priv; @@ -166,6 +178,9 @@ static int wl1271_sdio_power_on(struct wl1271 *wl) sdio_claim_host(func); sdio_enable_func(func); + /* Set the default block size in case it was modified */ + sdio_set_block_size(func, 0); + out: return ret; } @@ -203,7 +218,8 @@ static struct wl1271_if_operations sdio_ops = { .power = wl1271_sdio_set_power, .dev = wl1271_sdio_wl_to_dev, .enable_irq = wl1271_sdio_enable_interrupts, - .disable_irq = wl1271_sdio_disable_interrupts + .disable_irq = wl1271_sdio_disable_interrupts, + .set_block_size = wl1271_sdio_set_block_size, }; static int __devinit wl1271_probe(struct sdio_func *func, diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 80295f55f23..bfb1171176c 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -355,7 +355,8 @@ static struct wl1271_if_operations spi_ops = { .power = wl1271_spi_set_power, .dev = wl1271_spi_wl_to_dev, .enable_irq = wl1271_spi_enable_interrupts, - .disable_irq = wl1271_spi_disable_interrupts + .disable_irq = wl1271_spi_disable_interrupts, + .set_block_size = NULL, }; static int __devinit wl1271_probe(struct spi_device *spi) -- cgit v1.2.3-70-g09d2 From 5ea417ae7749076ddaacb5b36487cae6ac920413 Mon Sep 17 00:00:00 2001 From: Shahar Levi Date: Sun, 6 Mar 2011 16:32:11 +0200 Subject: wl12xx: 1281/1283 support - New boot sequence Boot sequence support FREF clock and TCXO clock. WL128x has two clocks input - TCXO and FREF. TCXO is the main clock of the device, while FREF is used to sync between the GPS and the cellular modem. Auto-detection checks where TCXO is 32.736MHz or 16.368MHz, in that case the FREF will be used as the WLAN/BT main clock. [Use clock enumeration as defined in linux/wl12xx.h; remove unnecessary else block in wl128x_switch_fref; remove unnecessary change in main.c; remove some unnecessary debug prints and comments; fix potential use of uninitialized value (pll_config) -- Luca] Signed-off-by: Shahar Levi Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 183 ++++++++++++++++++++++++++++++-- drivers/net/wireless/wl12xx/sdio.c | 1 + drivers/net/wireless/wl12xx/sdio_test.c | 1 + drivers/net/wireless/wl12xx/spi.c | 1 + drivers/net/wireless/wl12xx/wl12xx.h | 1 + 5 files changed, 179 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/wl12xx/spi.c') diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 38f3e8ba262..9d742c1e75a 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -22,6 +22,7 @@ */ #include +#include #include "acx.h" #include "reg.h" @@ -520,24 +521,159 @@ static void wl1271_boot_hw_version(struct wl1271 *wl) wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; } -/* uploads NVS and firmware */ -int wl1271_load_firmware(struct wl1271 *wl) +/* + * WL128x has two clocks input - TCXO and FREF. + * TCXO is the main clock of the device, while FREF is used to sync + * between the GPS and the cellular modem. + * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used + * as the WLAN/BT main clock. + */ +static int wl128x_switch_fref(struct wl1271 *wl, bool *is_ref_clk) { - int ret = 0; - u32 tmp, clk, pause; + u16 sys_clk_cfg_val; + + /* if working on XTAL-only mode go directly to TCXO TO FREF SWITCH */ + if ((wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) || + (wl->ref_clock == CONF_REF_CLK_26_M_XTAL)) + return true; + + /* Read clock source FREF or TCXO */ + sys_clk_cfg_val = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG); + + if (sys_clk_cfg_val & PRCM_CM_EN_MUX_WLAN_FREF) { + /* if bit 3 is set - working with FREF clock */ + wl1271_debug(DEBUG_BOOT, "working with FREF clock, skip" + " to FREF"); + + *is_ref_clk = true; + } else { + /* if bit 3 is clear - working with TCXO clock */ + wl1271_debug(DEBUG_BOOT, "working with TCXO clock"); + + /* TCXO to FREF switch, check TXCO clock config */ + if ((wl->tcxo_clock != WL12XX_TCXOCLOCK_16_368) && + (wl->tcxo_clock != WL12XX_TCXOCLOCK_32_736)) { + /* + * not 16.368Mhz and not 32.736Mhz - skip to + * configure ELP stage + */ + wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:" + " TcxoRefClk=%d - not 16.368Mhz and not" + " 32.736Mhz - skip to configure ELP" + " stage", wl->tcxo_clock); + + *is_ref_clk = false; + } else { + wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:" + "TcxoRefClk=%d - 16.368Mhz or 32.736Mhz" + " - TCXO to FREF switch", + wl->tcxo_clock); + + return true; + } + } + + return false; +} + +static int wl128x_boot_clk(struct wl1271 *wl, bool *is_ref_clk) +{ + if (wl128x_switch_fref(wl, is_ref_clk)) { + wl1271_debug(DEBUG_BOOT, "XTAL-only mode go directly to" + " TCXO TO FREF SWITCH"); + /* TCXO to FREF switch - for PG2.0 */ + wl1271_top_reg_write(wl, WL_SPARE_REG, + WL_SPARE_MASK_8526); + + wl1271_top_reg_write(wl, SYS_CLK_CFG_REG, + WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); + + *is_ref_clk = true; + mdelay(15); + } + + /* Set bit 2 in spare register to avoid illegal access */ + wl1271_top_reg_write(wl, WL_SPARE_REG, WL_SPARE_VAL); + + /* working with TCXO clock */ + if ((*is_ref_clk == false) && + ((wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8) || + (wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6))) { + wl1271_debug(DEBUG_BOOT, "16_8_M or 33_6_M TCXO detected"); + + /* Manually Configure MCS PLL settings PG2.0 Only */ + wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); + wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); + wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, + MCS_PLL_CONFIG_REG_VAL); + } else { + int pll_config; + u16 mcs_pll_config_val; + + /* + * Configure MCS PLL settings to FREF Freq + * Set the values that determine the time elapse since the PLL's + * get their enable signal until the lock indication is set + */ + wl1271_top_reg_write(wl, PLL_LOCK_COUNTERS_REG, + PLL_LOCK_COUNTERS_COEX | PLL_LOCK_COUNTERS_MCS); + + mcs_pll_config_val = wl1271_top_reg_read(wl, + MCS_PLL_CONFIG_REG); + /* + * Set the MCS PLL input frequency value according to the + * reference clock value detected/read + */ + if (*is_ref_clk == false) { + if ((wl->tcxo_clock == WL12XX_TCXOCLOCK_19_2) || + (wl->tcxo_clock == WL12XX_TCXOCLOCK_38_4)) + pll_config = 1; + else if ((wl->tcxo_clock == WL12XX_TCXOCLOCK_26) + || + (wl->tcxo_clock == WL12XX_TCXOCLOCK_52)) + pll_config = 2; + else + return -EINVAL; + } else { + if ((wl->ref_clock == CONF_REF_CLK_19_2_E) || + (wl->ref_clock == CONF_REF_CLK_38_4_E)) + pll_config = 1; + else if ((wl->ref_clock == CONF_REF_CLK_26_E) || + (wl->ref_clock == CONF_REF_CLK_52_E)) + pll_config = 2; + else + return -EINVAL; + } + + mcs_pll_config_val |= (pll_config << (MCS_SEL_IN_FREQ_SHIFT)) & + (MCS_SEL_IN_FREQ_MASK); + wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, + mcs_pll_config_val); + } + + return 0; +} + +static int wl127x_boot_clk(struct wl1271 *wl) +{ + u32 pause; + u32 clk; wl1271_boot_hw_version(wl); - if (wl->ref_clock == 0 || wl->ref_clock == 2 || wl->ref_clock == 4) + if (wl->ref_clock == CONF_REF_CLK_19_2_E || + wl->ref_clock == CONF_REF_CLK_38_4_E || + wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) /* ref clk: 19.2/38.4/38.4-XTAL */ clk = 0x3; - else if (wl->ref_clock == 1 || wl->ref_clock == 3) + else if (wl->ref_clock == CONF_REF_CLK_26_E || + wl->ref_clock == CONF_REF_CLK_52_E) /* ref clk: 26/52 */ clk = 0x5; else return -EINVAL; - if (wl->ref_clock != 0) { + if (wl->ref_clock != CONF_REF_CLK_19_2_E) { u16 val; /* Set clock type (open drain) */ val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); @@ -567,6 +703,26 @@ int wl1271_load_firmware(struct wl1271 *wl) pause |= WU_COUNTER_PAUSE_VAL; wl1271_write32(wl, WU_COUNTER_PAUSE, pause); + return 0; +} + +/* uploads NVS and firmware */ +int wl1271_load_firmware(struct wl1271 *wl) +{ + int ret = 0; + u32 tmp, clk; + bool is_ref_clk = false; + + if (wl->chip.id == CHIP_ID_1283_PG20) { + ret = wl128x_boot_clk(wl, &is_ref_clk); + if (ret < 0) + goto out; + } else { + ret = wl127x_boot_clk(wl); + if (ret < 0) + goto out; + } + /* Continue the ELP wake up sequence */ wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); udelay(500); @@ -582,7 +738,15 @@ int wl1271_load_firmware(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); - clk |= (wl->ref_clock << 1) << 4; + if (wl->chip.id == CHIP_ID_1283_PG20) { + if (is_ref_clk == false) + clk |= ((wl->tcxo_clock & 0x3) << 1) << 4; + else + clk |= ((wl->ref_clock & 0x3) << 1) << 4; + } else { + clk |= (wl->ref_clock << 1) << 4; + } + wl1271_write32(wl, DRPW_SCRATCH_START, clk); wl1271_set_partition(wl, &part_table[PART_WORK]); @@ -615,6 +779,9 @@ int wl1271_load_firmware(struct wl1271 *wl) /* WL1271: The reference driver skips steps 7 to 10 (jumps directly * to upload_fw) */ + if (wl->chip.id == CHIP_ID_1283_PG20) + wl1271_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); + ret = wl1271_boot_upload_firmware(wl); if (ret < 0) goto out; diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 7491b3d8487..f6dd3dea4f3 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -255,6 +255,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; + wl->tcxo_clock = wlan_data->board_tcxo_clock; ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c index e6e2ad63a1c..c02c8704661 100644 --- a/drivers/net/wireless/wl12xx/sdio_test.c +++ b/drivers/net/wireless/wl12xx/sdio_test.c @@ -421,6 +421,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; + wl->tcxo_clock = wlan_data->board_tcxo_clock; sdio_set_drvdata(func, wl_test); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index bfb1171176c..f5525361f2f 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -401,6 +401,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) } wl->ref_clock = pdata->board_ref_clock; + wl->tcxo_clock = pdata->board_tcxo_clock; wl->irq = spi->irq; if (wl->irq < 0) { diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index e59f5392e90..4b556776fd5 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -535,6 +535,7 @@ struct wl1271 { u8 ba_rx_bitmap; u32 block_size; + int tcxo_clock; /* * AP-mode - links indexed by HLID. The global and broadcast links -- cgit v1.2.3-70-g09d2 From 1aed55fd784d000fb6741cefb68712d64817bd68 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 6 Mar 2011 16:32:18 +0200 Subject: wl12xx: 1281/1283 support - Use different FW file for AP mode wl127x/wl128x chips Choose a different FW for AP-mode wl127x and wl128x chips, base on chip ID at boot time. Signed-off-by: Arik Nemtsov Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 5 ++++- drivers/net/wireless/wl12xx/sdio.c | 3 ++- drivers/net/wireless/wl12xx/spi.c | 3 ++- drivers/net/wireless/wl12xx/wl12xx.h | 3 ++- 4 files changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/wl12xx/spi.c') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 54ac6757c39..9a7ca6524d2 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -832,7 +832,10 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) switch (wl->bss_type) { case BSS_TYPE_AP_BSS: - fw_name = WL1271_AP_FW_NAME; + if (wl->chip.id == CHIP_ID_1283_PG20) + fw_name = WL128X_AP_FW_NAME; + else + fw_name = WL127X_AP_FW_NAME; break; case BSS_TYPE_IBSS: case BSS_TYPE_STA_BSS: diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index f6dd3dea4f3..5a2951ed6ed 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -361,4 +361,5 @@ MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL1271_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME); -MODULE_FIRMWARE(WL1271_AP_FW_NAME); +MODULE_FIRMWARE(WL127X_AP_FW_NAME); +MODULE_FIRMWARE(WL128X_AP_FW_NAME); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index f5525361f2f..7b82b5f0e49 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -493,5 +493,6 @@ MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL1271_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME); -MODULE_FIRMWARE(WL1271_AP_FW_NAME); +MODULE_FIRMWARE(WL127X_AP_FW_NAME); +MODULE_FIRMWARE(WL128X_AP_FW_NAME); MODULE_ALIAS("spi:wl1271"); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index ad04b8337a2..890c1a54382 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -132,7 +132,8 @@ extern u32 wl12xx_debug_level; #define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin" #define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin" -#define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" +#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" +#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin" /* * wl127x and wl128x are using the same NVS file name. However, the -- cgit v1.2.3-70-g09d2 From 341b7cde6ccc60672fcd7fc84dd24a1b7c0b8d94 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 31 Mar 2011 10:07:01 +0200 Subject: wl12xx: Handle platforms without level trigger interrupts Some platforms are incapable of triggering on level interrupts. Add a platform quirks member in the platform data structure, as well as an edge interrupt quirk which can be set on such platforms. When the interrupt is requested with IRQF_TRIGGER_RISING, IRQF_ONESHOT cannot be used, as we might miss interrupts that occur after the FW status is cleared and before the threaded interrupt handler exits. Moreover, when IRQF_ONESHOT is not set, iterating more than once in the threaded interrupt handler introduces a few race conditions between this handler and the hardirq handler. Currently this is worked around by limiting the loop to one iteration only. This workaround has an impact on performance. To remove to this restriction, the race conditions will need to be addressed. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 9 +++++++++ drivers/net/wireless/wl12xx/sdio.c | 9 ++++++++- drivers/net/wireless/wl12xx/spi.c | 9 ++++++++- drivers/net/wireless/wl12xx/wl12xx.h | 3 +++ include/linux/wl12xx.h | 4 ++++ 5 files changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/wl12xx/spi.c') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 1feb9551ef8..7126506611c 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "wl12xx.h" #include "wl12xx_80211.h" @@ -719,6 +720,13 @@ irqreturn_t wl1271_irq(int irq, void *cookie) set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); cancel_work_sync(&wl->tx_work); + /* + * In case edge triggered interrupt must be used, we cannot iterate + * more than once without introducing race conditions with the hardirq. + */ + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) + loopcount = 1; + mutex_lock(&wl->mutex); wl1271_debug(DEBUG_IRQ, "IRQ work"); @@ -3648,6 +3656,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->ap_ps_map = 0; wl->ap_fw_ps_map = 0; wl->quirks = 0; + wl->platform_quirks = 0; memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 8246e9de430..bcd4ad7ba90 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -220,6 +220,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, struct ieee80211_hw *hw; const struct wl12xx_platform_data *wlan_data; struct wl1271 *wl; + unsigned long irqflags; int ret; /* We are only able to handle the wlan function */ @@ -251,9 +252,15 @@ static int __devinit wl1271_probe(struct sdio_func *func, wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; wl->tcxo_clock = wlan_data->board_tcxo_clock; + wl->platform_quirks = wlan_data->platform_quirks; + + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) + irqflags = IRQF_TRIGGER_RISING; + else + irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + irqflags, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 7b82b5f0e49..51662bb6801 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -364,6 +364,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) struct wl12xx_platform_data *pdata; struct ieee80211_hw *hw; struct wl1271 *wl; + unsigned long irqflags; int ret; pdata = spi->dev.platform_data; @@ -402,6 +403,12 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->ref_clock = pdata->board_ref_clock; wl->tcxo_clock = pdata->board_tcxo_clock; + wl->platform_quirks = pdata->platform_quirks; + + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) + irqflags = IRQF_TRIGGER_RISING; + else + irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; wl->irq = spi->irq; if (wl->irq < 0) { @@ -411,7 +418,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) } ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + irqflags, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9ccbcfdd080..fb2b79fa42b 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -579,6 +579,9 @@ struct wl1271 { /* Quirks of specific hardware revisions */ unsigned int quirks; + + /* Platform limitations */ + unsigned int platform_quirks; }; struct wl1271_station { diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h index c1a743ea747..4b697395326 100644 --- a/include/linux/wl12xx.h +++ b/include/linux/wl12xx.h @@ -53,8 +53,12 @@ struct wl12xx_platform_data { bool use_eeprom; int board_ref_clock; int board_tcxo_clock; + unsigned long platform_quirks; }; +/* Platform does not support level trigger interrupts */ +#define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0) + #ifdef CONFIG_WL12XX_PLATFORM_DATA int wl12xx_set_platform_data(const struct wl12xx_platform_data *data); -- cgit v1.2.3-70-g09d2