diff options
| author | Hante Meuleman <meuleman@broadcom.com> | 2013-04-12 04:55:55 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2013-04-12 14:27:55 -0400 |
| commit | 668761ac01d6f5a36b8e5a24d4e154550e2c4c3b (patch) | |
| tree | aaf5ab3af476a7b293b0b8d9e78aef42ea77c2d6 | |
| parent | 979c29205ffa607c59ba2c9f9c083b967d356c97 (diff) | |
brcmfmac: define and use platform specific data for SDIO.
This patch adds support for platform specific data for SDIO
fullmac devices. Currently OOB interrupts are configured by Kconfig
BRCMFMAC_SDIO_OOB but that is now determined dynamically by checking
availibility of platform data.
Cc: Hauke Mehrtens <hauke@hauke-m.de>
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Piotr Haber <phaber@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
| -rw-r--r-- | drivers/net/wireless/brcm80211/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 155 | ||||
| -rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 114 | ||||
| -rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 29 | ||||
| -rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | 6 | ||||
| -rw-r--r-- | include/linux/platform_data/brcmfmac-sdio.h | 124 |
6 files changed, 250 insertions, 187 deletions
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index 747e9317dabd..fc8a0fa6d3b2 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig | |||
| @@ -37,15 +37,6 @@ config BRCMFMAC_SDIO | |||
| 37 | IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to | 37 | IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to |
| 38 | use the driver for a SDIO wireless card. | 38 | use the driver for a SDIO wireless card. |
| 39 | 39 | ||
| 40 | config BRCMFMAC_SDIO_OOB | ||
| 41 | bool "Out of band interrupt support for SDIO interface chipset" | ||
| 42 | depends on BRCMFMAC_SDIO | ||
| 43 | ---help--- | ||
| 44 | This option enables out-of-band interrupt support for Broadcom | ||
| 45 | SDIO Wifi chipset using fullmac in order to gain better | ||
| 46 | performance and deep sleep wake up capability on certain | ||
| 47 | platforms. Say N if you are unsure. | ||
| 48 | |||
| 49 | config BRCMFMAC_USB | 40 | config BRCMFMAC_USB |
| 50 | bool "USB bus interface support for FullMAC driver" | 41 | bool "USB bus interface support for FullMAC driver" |
| 51 | depends on USB | 42 | depends on USB |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index aa51f370be49..4891e3df2058 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/mmc/sdio.h> | 25 | #include <linux/mmc/sdio.h> |
| 26 | #include <linux/mmc/sdio_func.h> | 26 | #include <linux/mmc/sdio_func.h> |
| 27 | #include <linux/mmc/card.h> | 27 | #include <linux/mmc/card.h> |
| 28 | #include <linux/platform_data/brcmfmac-sdio.h> | ||
| 28 | 29 | ||
| 29 | #include <defs.h> | 30 | #include <defs.h> |
| 30 | #include <brcm_hw_ids.h> | 31 | #include <brcm_hw_ids.h> |
| @@ -37,16 +38,15 @@ | |||
| 37 | 38 | ||
| 38 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 | 39 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 |
| 39 | 40 | ||
| 40 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | 41 | |
| 41 | static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id) | 42 | static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id) |
| 42 | { | 43 | { |
| 43 | struct brcmf_bus *bus_if = dev_get_drvdata(dev_id); | 44 | struct brcmf_bus *bus_if = dev_get_drvdata(dev_id); |
| 44 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 45 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
| 45 | 46 | ||
| 46 | brcmf_dbg(INTR, "oob intr triggered\n"); | 47 | brcmf_dbg(INTR, "OOB intr triggered\n"); |
| 47 | 48 | ||
| 48 | /* | 49 | /* out-of-band interrupt is level-triggered which won't |
| 49 | * out-of-band interrupt is level-triggered which won't | ||
| 50 | * be cleared until dpc | 50 | * be cleared until dpc |
| 51 | */ | 51 | */ |
| 52 | if (sdiodev->irq_en) { | 52 | if (sdiodev->irq_en) { |
| @@ -59,72 +59,12 @@ static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id) | |||
| 59 | return IRQ_HANDLED; | 59 | return IRQ_HANDLED; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | 62 | static void brcmf_sdio_ib_irqhandler(struct sdio_func *func) |
| 63 | { | ||
| 64 | int ret = 0; | ||
| 65 | u8 data; | ||
| 66 | unsigned long flags; | ||
| 67 | |||
| 68 | brcmf_dbg(SDIO, "Entering: irq %d\n", sdiodev->irq); | ||
| 69 | |||
| 70 | ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler, | ||
| 71 | sdiodev->irq_flags, "brcmf_oob_intr", | ||
| 72 | &sdiodev->func[1]->dev); | ||
| 73 | if (ret != 0) | ||
| 74 | return ret; | ||
| 75 | spin_lock_init(&sdiodev->irq_en_lock); | ||
| 76 | spin_lock_irqsave(&sdiodev->irq_en_lock, flags); | ||
| 77 | sdiodev->irq_en = true; | ||
| 78 | spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags); | ||
| 79 | |||
| 80 | ret = enable_irq_wake(sdiodev->irq); | ||
| 81 | if (ret != 0) | ||
| 82 | return ret; | ||
| 83 | sdiodev->irq_wake = true; | ||
| 84 | |||
| 85 | sdio_claim_host(sdiodev->func[1]); | ||
| 86 | |||
| 87 | /* must configure SDIO_CCCR_IENx to enable irq */ | ||
| 88 | data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret); | ||
| 89 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; | ||
| 90 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); | ||
| 91 | |||
| 92 | /* redirect, configure and enable io for interrupt signal */ | ||
| 93 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; | ||
| 94 | if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH) | ||
| 95 | data |= SDIO_SEPINT_ACT_HI; | ||
| 96 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); | ||
| 97 | |||
| 98 | sdio_release_host(sdiodev->func[1]); | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | ||
| 104 | { | ||
| 105 | brcmf_dbg(SDIO, "Entering\n"); | ||
| 106 | |||
| 107 | sdio_claim_host(sdiodev->func[1]); | ||
| 108 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); | ||
| 109 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); | ||
| 110 | sdio_release_host(sdiodev->func[1]); | ||
| 111 | |||
| 112 | if (sdiodev->irq_wake) { | ||
| 113 | disable_irq_wake(sdiodev->irq); | ||
| 114 | sdiodev->irq_wake = false; | ||
| 115 | } | ||
| 116 | free_irq(sdiodev->irq, &sdiodev->func[1]->dev); | ||
| 117 | sdiodev->irq_en = false; | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | #else /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
| 122 | static void brcmf_sdio_irqhandler(struct sdio_func *func) | ||
| 123 | { | 63 | { |
| 124 | struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev); | 64 | struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev); |
| 125 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 65 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
| 126 | 66 | ||
| 127 | brcmf_dbg(INTR, "ib intr triggered\n"); | 67 | brcmf_dbg(INTR, "IB intr triggered\n"); |
| 128 | 68 | ||
| 129 | brcmf_sdbrcm_isr(sdiodev->bus); | 69 | brcmf_sdbrcm_isr(sdiodev->bus); |
| 130 | } | 70 | } |
| @@ -136,12 +76,56 @@ static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func) | |||
| 136 | 76 | ||
| 137 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | 77 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) |
| 138 | { | 78 | { |
| 139 | brcmf_dbg(SDIO, "Entering\n"); | 79 | int ret = 0; |
| 80 | u8 data; | ||
| 81 | unsigned long flags; | ||
| 140 | 82 | ||
| 141 | sdio_claim_host(sdiodev->func[1]); | 83 | if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) { |
| 142 | sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler); | 84 | brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n", |
| 143 | sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler); | 85 | sdiodev->pdata->oob_irq_nr); |
| 144 | sdio_release_host(sdiodev->func[1]); | 86 | ret = request_irq(sdiodev->pdata->oob_irq_nr, |
| 87 | brcmf_sdio_oob_irqhandler, | ||
| 88 | sdiodev->pdata->oob_irq_flags, | ||
| 89 | "brcmf_oob_intr", | ||
| 90 | &sdiodev->func[1]->dev); | ||
| 91 | if (ret != 0) { | ||
| 92 | brcmf_err("request_irq failed %d\n", ret); | ||
| 93 | return ret; | ||
| 94 | } | ||
| 95 | sdiodev->oob_irq_requested = true; | ||
| 96 | spin_lock_init(&sdiodev->irq_en_lock); | ||
| 97 | spin_lock_irqsave(&sdiodev->irq_en_lock, flags); | ||
| 98 | sdiodev->irq_en = true; | ||
| 99 | spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags); | ||
| 100 | |||
| 101 | ret = enable_irq_wake(sdiodev->pdata->oob_irq_nr); | ||
