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 /drivers/net/wireless | |
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>
Diffstat (limited to 'drivers/net/wireless')
-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 |
5 files changed, 126 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); | ||
102 | if (ret != 0) { | ||
103 | brcmf_err("enable_irq_wake failed %d\n", ret); | ||
104 | return ret; | ||
105 | } | ||
106 | sdiodev->irq_wake = true; | ||
107 | |||
108 | sdio_claim_host(sdiodev->func[1]); | ||
109 | |||
110 | /* must configure SDIO_CCCR_IENx to enable irq */ | ||
111 | data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret); | ||
112 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; | ||
113 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); | ||
114 | |||
115 | /* redirect, configure and enable io for interrupt signal */ | ||
116 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; | ||
117 | if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH) | ||
118 | data |= SDIO_SEPINT_ACT_HI; | ||
119 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); | ||
120 | |||
121 | sdio_release_host(sdiodev->func[1]); | ||
122 | } else { | ||
123 | brcmf_dbg(SDIO, "Entering\n"); | ||
124 | sdio_claim_host(sdiodev->func[1]); | ||
125 | sdio_claim_irq(sdiodev->func[1], brcmf_sdio_ib_irqhandler); | ||
126 | sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler); | ||
127 | sdio_release_host(sdiodev->func[1]); | ||
128 | } | ||
145 | 129 | ||
146 | return 0; | 130 | return 0; |
147 | } | 131 | } |
@@ -150,14 +134,31 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | |||
150 | { | 134 | { |
151 | brcmf_dbg(SDIO, "Entering\n"); | 135 | brcmf_dbg(SDIO, "Entering\n"); |
152 | 136 | ||
153 | sdio_claim_host(sdiodev->func[1]); | 137 | if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) { |
154 | sdio_release_irq(sdiodev->func[2]); | 138 | sdio_claim_host(sdiodev->func[1]); |
155 | sdio_release_irq(sdiodev->func[1]); | 139 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); |
156 | sdio_release_host(sdiodev->func[1]); | 140 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); |
141 | sdio_release_host(sdiodev->func[1]); | ||
142 | |||
143 | if (sdiodev->oob_irq_requested) { | ||
144 | sdiodev->oob_irq_requested = false; | ||
145 | if (sdiodev->irq_wake) { | ||
146 | disable_irq_wake(sdiodev->pdata->oob_irq_nr); | ||
147 | sdiodev->irq_wake = false; | ||
148 | } | ||
149 | free_irq(sdiodev->pdata->oob_irq_nr, | ||
150 | &sdiodev->func[1]->dev); | ||
151 | sdiodev->irq_en = false; | ||
152 | } | ||
153 | } else { | ||
154 | sdio_claim_host(sdiodev->func[1]); | ||
155 | sdio_release_irq(sdiodev->func[2]); | ||
156 | sdio_release_irq(sdiodev->func[1]); | ||
157 | sdio_release_host(sdiodev->func[1]); | ||
158 | } | ||
157 | 159 | ||
158 | return 0; | 160 | return 0; |
159 | } | 161 | } |
160 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
161 | 162 | ||
162 | int | 163 | int |
163 | brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | 164 | brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index b1ea1036e825..44fa0cdbf97b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/sched.h> /* request_irq() */ | 26 | #include <linux/sched.h> /* request_irq() */ |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/platform_data/brcmfmac-sdio.h> | ||
29 | #include <net/cfg80211.h> | 30 | #include <net/cfg80211.h> |
30 | 31 | ||
31 | #include <defs.h> | 32 | #include <defs.h> |
@@ -62,14 +63,8 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { | |||
62 | }; | 63 | }; |
63 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | 64 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); |
64 | 65 | ||
65 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | 66 | static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata; |
66 | static struct list_head oobirq_lh; | 67 | |
67 | struct brcmf_sdio_oobirq { | ||
68 | unsigned int irq; | ||
69 | unsigned long flags; | ||
70 | struct list_head list; | ||
71 | }; | ||
72 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
73 | 68 | ||
74 | static bool | 69 | static bool |
75 | brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) | 70 | brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) |
@@ -428,33 +423,6 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) | |||
428 | 423 | ||
429 | } | 424 | } |
430 | 425 | ||
431 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | ||
432 | static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev) | ||
433 | { | ||
434 | struct brcmf_sdio_oobirq *oobirq_entry; | ||
435 | |||
436 | if (list_empty(&oobirq_lh)) { | ||
437 | brcmf_err("no valid oob irq resource\n"); | ||
438 | return -ENXIO; | ||
439 | } | ||
440 | |||
441 | oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq, | ||
442 | list); | ||
443 | |||
444 | sdiodev->irq = oobirq_entry->irq; | ||
445 | sdiodev->irq_flags = oobirq_entry->flags; | ||
446 | list_del(&oobirq_entry->list); | ||
447 | kfree(oobirq_entry); | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | #else | ||
452 | static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev) | ||
453 | { | ||
454 | return 0; | ||
455 | } | ||
456 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
457 | |||
458 | static int brcmf_ops_sdio_probe(struct sdio_func *func, | 426 | static int brcmf_ops_sdio_probe(struct sdio_func *func, |
459 | const struct sdio_device_id *id) | 427 | const struct sdio_device_id *id) |
460 | { | 428 | { |
@@ -495,15 +463,13 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
495 | dev_set_drvdata(&func->dev, bus_if); | 463 | dev_set_drvdata(&func->dev, bus_if); |
496 | dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); | 464 | dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); |
497 | sdiodev->dev = &sdiodev->func[1]->dev; | 465 | sdiodev->dev = &sdiodev->func[1]->dev; |
466 | sdiodev->pdata = brcmfmac_sdio_pdata; | ||
498 | 467 | ||
499 | atomic_set(&sdiodev->suspend, false); | 468 | atomic_set(&sdiodev->suspend, false); |
500 | init_waitqueue_head(&sdiodev->request_byte_wait); | 469 | init_waitqueue_head(&sdiodev->request_byte_wait); |
501 | init_waitqueue_head(&sdiodev->request_word_wait); | 470 | init_waitqueue_head(&sdiodev->request_word_wait); |
502 | init_waitqueue_head(&sdiodev->request_chain_wait); | 471 | init_waitqueue_head(&sdiodev->request_chain_wait); |
503 | init_waitqueue_head(&sdiodev->request_buffer_wait); | 472 | init_waitqueue_head(&sdiodev->request_buffer_wait); |
504 | err = brcmf_sdio_getintrcfg(sdiodev); | ||
505 | if (err) | ||
506 | goto fail; | ||
507 | 473 | ||
508 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n"); | 474 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n"); |
509 | err = brcmf_sdio_probe(sdiodev); | 475 | err = brcmf_sdio_probe(sdiodev); |
@@ -598,7 +564,7 @@ static const struct dev_pm_ops brcmf_sdio_pm_ops = { | |||
598 | static struct sdio_driver brcmf_sdmmc_driver = { | 564 | static struct sdio_driver brcmf_sdmmc_driver = { |
599 | .probe = brcmf_ops_sdio_probe, | 565 | .probe = brcmf_ops_sdio_probe, |
600 | .remove = brcmf_ops_sdio_remove, | 566 | .remove = brcmf_ops_sdio_remove, |
601 | .name = "brcmfmac", | 567 | .name = BRCMFMAC_SDIO_PDATA_NAME, |
602 | .id_table = brcmf_sdmmc_ids, | 568 | .id_table = brcmf_sdmmc_ids, |
603 | #ifdef CONFIG_PM_SLEEP | 569 | #ifdef CONFIG_PM_SLEEP |
604 | .drv = { | 570 | .drv = { |
@@ -607,72 +573,51 @@ static struct sdio_driver brcmf_sdmmc_driver = { | |||
607 | #endif /* CONFIG_PM_SLEEP */ | 573 | #endif /* CONFIG_PM_SLEEP */ |
608 | }; | 574 | }; |
609 | 575 | ||
610 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | ||
611 | static int brcmf_sdio_pd_probe(struct platform_device *pdev) | 576 | static int brcmf_sdio_pd_probe(struct platform_device *pdev) |
612 | { | 577 | { |
613 | struct resource *res; | 578 | int ret; |
614 | struct brcmf_sdio_oobirq *oobirq_entry; | ||
615 | int i, ret; | ||
616 | 579 | ||
617 | INIT_LIST_HEAD(&oobirq_lh); | 580 | brcmf_dbg(SDIO, "Enter\n"); |
618 | 581 | ||
619 | for (i = 0; ; i++) { | 582 | brcmfmac_sdio_pdata = pdev->dev.platform_data; |
620 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | ||
621 | if (!res) | ||
622 | break; | ||
623 | 583 | ||
624 | oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq), | 584 | if (brcmfmac_sdio_pdata->power_on) |
625 | GFP_KERNEL); | 585 | brcmfmac_sdio_pdata->power_on(); |
626 | if (!oobirq_entry) | ||
627 | return -ENOMEM; | ||
628 | oobirq_entry->irq = res->start; | ||
629 | oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK; | ||
630 | list_add_tail(&oobirq_entry->list, &oobirq_lh); | ||
631 | } | ||
632 | if (i == 0) | ||
633 | return -ENXIO; | ||
634 | 586 | ||
635 | ret = sdio_register_driver(&brcmf_sdmmc_driver); | 587 | ret = sdio_register_driver(&brcmf_sdmmc_driver); |
636 | |||
637 | if (ret) | 588 | if (ret) |
638 | brcmf_err("sdio_register_driver failed: %d\n", ret); | 589 | brcmf_err("sdio_register_driver failed: %d\n", ret); |
639 | 590 | ||
640 | return ret; | 591 | return ret; |
641 | } | 592 | } |
642 | 593 | ||
643 | static struct platform_driver brcmf_sdio_pd = { | 594 | static int brcmf_sdio_pd_remove(struct platform_device *pdev) |
644 | .probe = brcmf_sdio_pd_probe, | ||
645 | .driver = { | ||
646 | .name = "brcmf_sdio_pd" | ||
647 | } | ||
648 | }; | ||
649 | |||
650 | void brcmf_sdio_exit(void) | ||
651 | { | 595 | { |
652 | brcmf_dbg(SDIO, "Enter\n"); | 596 | brcmf_dbg(SDIO, "Enter\n"); |
653 | 597 | ||
598 | if (brcmfmac_sdio_pdata->power_off) | ||
599 | brcmfmac_sdio_pdata->power_off(); | ||
600 | |||
654 | sdio_unregister_driver(&brcmf_sdmmc_driver); | 601 | sdio_unregister_driver(&brcmf_sdmmc_driver); |
655 | 602 | ||
656 | platform_driver_unregister(&brcmf_sdio_pd); | 603 | return 0; |
657 | } | 604 | } |
658 | 605 | ||
659 | void brcmf_sdio_init(void) | 606 | static struct platform_driver brcmf_sdio_pd = { |
660 | { | 607 | .remove = brcmf_sdio_pd_remove, |
661 | int ret; | 608 | .driver = { |
662 | 609 | .name = BRCMFMAC_SDIO_PDATA_NAME | |
663 | brcmf_dbg(SDIO, "Enter\n"); | 610 | } |
664 | 611 | }; | |
665 | ret = platform_driver_register(&brcmf_sdio_pd); | ||
666 | 612 | ||
667 | if (ret) | ||
668 | brcmf_err("platform_driver_register failed: %d\n", ret); | ||
669 | } | ||
670 | #else | ||
671 | void brcmf_sdio_exit(void) | 613 | void brcmf_sdio_exit(void) |
672 | { | 614 | { |
673 | brcmf_dbg(SDIO, "Enter\n"); | 615 | brcmf_dbg(SDIO, "Enter\n"); |
674 | 616 | ||
675 | sdio_unregister_driver(&brcmf_sdmmc_driver); | 617 | if (brcmfmac_sdio_pdata) |
618 | platform_driver_unregister(&brcmf_sdio_pd); | ||
619 | else | ||
620 | sdio_unregister_driver(&brcmf_sdmmc_driver); | ||
676 | } | 621 | } |
677 | 622 | ||
678 | void brcmf_sdio_init(void) | 623 | void brcmf_sdio_init(void) |
@@ -681,9 +626,12 @@ void brcmf_sdio_init(void) | |||
681 | 626 | ||
682 | brcmf_dbg(SDIO, "Enter\n"); | 627 | brcmf_dbg(SDIO, "Enter\n"); |
683 | 628 | ||
684 | ret = sdio_register_driver(&brcmf_sdmmc_driver); | 629 | ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe); |
630 | if (ret == -ENODEV) { | ||
631 | brcmf_dbg(SDIO, "No platform data available, registering without.\n"); | ||
632 | ret = sdio_register_driver(&brcmf_sdmmc_driver); | ||
633 | } | ||
685 | 634 | ||
686 | if (ret) | 635 | if (ret) |
687 | brcmf_err("sdio_register_driver failed: %d\n", ret); | 636 | brcmf_err("driver registration failed: %d\n", ret); |
688 | } | 637 | } |
689 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index fd697ce3683c..d2487518bd2a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/bcma/bcma.h> | 31 | #include <linux/bcma/bcma.h> |
32 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
33 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
34 | #include <linux/platform_data/brcmfmac-sdio.h> | ||
34 | #include <asm/unaligned.h> | 35 | #include <asm/unaligned.h> |
35 | #include <defs.h> | 36 | #include <defs.h> |
36 | #include <brcmu_wifi.h> | 37 | #include <brcmu_wifi.h> |
@@ -517,7 +518,7 @@ static int qcount[NUMPRIO]; | |||
517 | static int tx_packets[NUMPRIO]; | 518 | static int tx_packets[NUMPRIO]; |
518 | #endif /* DEBUG */ | 519 | #endif /* DEBUG */ |
519 | 520 | ||
520 | #define SDIO_DRIVE_STRENGTH 6 /* in milliamps */ | 521 | #define DEFAULT_SDIO_DRIVE_STRENGTH 6 /* in milliamps */ |
521 | 522 | ||
522 | #define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) | 523 | #define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) |
523 | 524 | ||
@@ -2046,23 +2047,19 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
2046 | bus->tx_seq = bus->rx_seq = 0; | 2047 | bus->tx_seq = bus->rx_seq = 0; |
2047 | } | 2048 | } |
2048 | 2049 | ||
2049 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | ||
2050 | static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | 2050 | static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) |
2051 | { | 2051 | { |
2052 | unsigned long flags; | 2052 | unsigned long flags; |
2053 | 2053 | ||
2054 | spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); | 2054 | if (bus->sdiodev->oob_irq_requested) { |
2055 | if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) { | 2055 | spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); |
2056 | enable_irq(bus->sdiodev->irq); | 2056 | if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) { |
2057 | bus->sdiodev->irq_en = true; | 2057 | enable_irq(bus->sdiodev->pdata->oob_irq_nr); |
2058 | bus->sdiodev->irq_en = true; | ||
2059 | } | ||
2060 | spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags); | ||
2058 | } | 2061 | } |
2059 | spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags); | ||
2060 | } | ||
2061 | #else | ||
2062 | static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | ||
2063 | { | ||
2064 | } | 2062 | } |
2065 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
2066 | 2063 | ||
2067 | static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) | 2064 | static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) |
2068 | { | 2065 | { |
@@ -3639,6 +3636,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3639 | int err = 0; | 3636 | int err = 0; |
3640 | int reg_addr; | 3637 | int reg_addr; |
3641 | u32 reg_val; | 3638 | u32 reg_val; |
3639 | u32 drivestrength; | ||
3642 | 3640 | ||
3643 | bus->alp_only = true; | 3641 | bus->alp_only = true; |
3644 | 3642 | ||
@@ -3679,8 +3677,11 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3679 | goto fail; | 3677 | goto fail; |
3680 | } | 3678 | } |
3681 | 3679 | ||
3682 | brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, | 3680 | if ((bus->sdiodev->pdata) && (bus->sdiodev->pdata->drive_strength)) |
3683 | SDIO_DRIVE_STRENGTH); | 3681 | drivestrength = bus->sdiodev->pdata->drive_strength; |
3682 | else | ||
3683 | drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH; | ||
3684 | brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength); | ||
3684 | 3685 | ||
3685 | /* Get info on the SOCRAM cores... */ | 3686 | /* Get info on the SOCRAM cores... */ |
3686 | bus->ramsize = bus->ci->ramsize; | 3687 | bus->ramsize = bus->ci->ramsize; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 28ed3cc9f35a..7c1b6332747e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
@@ -174,13 +174,11 @@ struct brcmf_sdio_dev { | |||
174 | wait_queue_head_t request_buffer_wait; | 174 | wait_queue_head_t request_buffer_wait; |
175 | struct device *dev; | 175 | struct device *dev; |
176 | struct brcmf_bus *bus_if; | 176 | struct brcmf_bus *bus_if; |
177 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | 177 | struct brcmfmac_sdio_platform_data *pdata; |
178 | unsigned int irq; /* oob interrupt number */ | 178 | bool oob_irq_requested; |
179 | unsigned long irq_flags; /* board specific oob flags */ | ||
180 | bool irq_en; /* irq enable flags */ | 179 | bool irq_en; /* irq enable flags */ |
181 | spinlock_t irq_en_lock; | 180 | spinlock_t irq_en_lock; |
182 | bool irq_wake; /* irq wake enable flags */ | 181 | bool irq_wake; /* irq wake enable flags */ |
183 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
184 | }; | 182 | }; |
185 | 183 | ||
186 | /* Register/deregister interrupt handler. */ | 184 | /* Register/deregister interrupt handler. */ |