diff options
author | Bob Copeland <me@bobcopeland.com> | 2009-08-07 06:33:42 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-14 09:13:38 -0400 |
commit | 3ec410d747fa1da035183c43775a64c0e285e399 (patch) | |
tree | 7a0d03a46cc8adf4f42eaa338b30dccb8ebbaf22 | |
parent | af8c78ebbf2a15ecf9b2b6b7b051b0d4c3ba1163 (diff) |
wl1251: add sdio support
This adds the wl1251_sdio module, enabling the SDIO interface for
wl1251, as used by the Google G1 phone and others.
Signed-off-by: Bob Copeland <me@bobcopeland.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/wl12xx/Kconfig | 11 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_sdio.c | 188 |
3 files changed, 200 insertions, 0 deletions
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index f8cb8b864ad2..7b14d5bc63d6 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
@@ -28,6 +28,17 @@ config WL1251_SPI | |||
28 | If you choose to build a module, it'll be called wl1251_spi. | 28 | If you choose to build a module, it'll be called wl1251_spi. |
29 | Say N if unsure. | 29 | Say N if unsure. |
30 | 30 | ||
31 | config WL1251_SDIO | ||
32 | tristate "TI wl1251 SDIO support" | ||
33 | depends on WL1251 && MMC | ||
34 | ---help--- | ||
35 | This module adds support for the SDIO interface of adapters using | ||
36 | TI wl1251 chipset. Select this if your platform is using | ||
37 | the SDIO bus. | ||
38 | |||
39 | If you choose to build a module, it'll be called | ||
40 | wl1251_sdio. Say N if unsure. | ||
41 | |||
31 | config WL1271 | 42 | config WL1271 |
32 | tristate "TI wl1271 support" | 43 | tristate "TI wl1271 support" |
33 | depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS | 44 | depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS |
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index ea0477f1d1da..207e85274bc3 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -5,6 +5,7 @@ wl1251-objs = wl1251_main.o wl1251_event.o \ | |||
5 | 5 | ||
6 | obj-$(CONFIG_WL1251) += wl1251.o | 6 | obj-$(CONFIG_WL1251) += wl1251.o |
7 | obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o | 7 | obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o |
8 | obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o | ||
8 | 9 | ||
9 | wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ | 10 | wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ |
10 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ | 11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ |
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c new file mode 100644 index 000000000000..f1d9e76e0484 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * wl12xx SDIO routines | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
16 | * 02110-1301 USA | ||
17 | * | ||
18 | * Copyright (C) 2005 Texas Instruments Incorporated | ||
19 | * Copyright (C) 2008 Google Inc | ||
20 | * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com) | ||
21 | */ | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/crc7.h> | ||
24 | #include <linux/mod_devicetable.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/mmc/sdio_func.h> | ||
27 | #include <linux/mmc/sdio_ids.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | |||
30 | #include "wl1251.h" | ||
31 | #include "wl12xx_80211.h" | ||
32 | #include "reg.h" | ||
33 | #include "wl1251_ps.h" | ||
34 | #include "wl1251_io.h" | ||
35 | #include "wl1251_tx.h" | ||
36 | #include "wl1251_debugfs.h" | ||
37 | |||
38 | #ifndef SDIO_VENDOR_ID_TI | ||
39 | #define SDIO_VENDOR_ID_TI 0x104c | ||
40 | #endif | ||
41 | |||
42 | #ifndef SDIO_DEVICE_ID_TI_WL1251 | ||
43 | #define SDIO_DEVICE_ID_TI_WL1251 0x9066 | ||
44 | #endif | ||
45 | |||
46 | static struct sdio_func *wl_to_func(struct wl1251 *wl) | ||
47 | { | ||
48 | return wl->if_priv; | ||
49 | } | ||
50 | |||
51 | static void wl1251_sdio_interrupt(struct sdio_func *func) | ||
52 | { | ||
53 | wl1251_irq(0, sdio_get_drvdata(func)); | ||
54 | } | ||
55 | |||
56 | static const struct sdio_device_id wl1251_devices[] = { | ||
57 | { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1251) }, | ||
58 | {} | ||
59 | }; | ||
60 | MODULE_DEVICE_TABLE(sdio, wl1251_devices); | ||
61 | |||
62 | |||
63 | void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len) | ||
64 | { | ||
65 | int ret; | ||
66 | struct sdio_func *func = wl_to_func(wl); | ||
67 | |||
68 | sdio_claim_host(func); | ||
69 | ret = sdio_memcpy_fromio(func, buf, addr, len); | ||
70 | if (ret) | ||
71 | wl1251_error("sdio read failed (%d)", ret); | ||
72 | sdio_release_host(func); | ||
73 | } | ||
74 | |||
75 | void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) | ||
76 | { | ||
77 | int ret; | ||
78 | struct sdio_func *func = wl_to_func(wl); | ||
79 | |||
80 | sdio_claim_host(func); | ||
81 | ret = sdio_memcpy_toio(func, addr, buf, len); | ||
82 | if (ret) | ||
83 | wl1251_error("sdio write failed (%d)", ret); | ||
84 | sdio_release_host(func); | ||
85 | } | ||
86 | |||
87 | void wl1251_sdio_reset(struct wl1251 *wl) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | void wl1251_sdio_set_power(bool enable) | ||
92 | { | ||
93 | } | ||
94 | |||
95 | struct wl1251_if_operations wl1251_sdio_ops = { | ||
96 | .read = wl1251_sdio_read, | ||
97 | .write = wl1251_sdio_write, | ||
98 | .reset = wl1251_sdio_reset, | ||
99 | }; | ||
100 | |||
101 | int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | ||
102 | { | ||
103 | int ret; | ||
104 | struct wl1251 *wl; | ||
105 | struct ieee80211_hw *hw; | ||
106 | |||
107 | hw = wl1251_alloc_hw(); | ||
108 | if (IS_ERR(hw)) | ||
109 | return PTR_ERR(hw); | ||
110 | |||
111 | wl = hw->priv; | ||
112 | |||
113 | sdio_claim_host(func); | ||
114 | ret = sdio_enable_func(func); | ||
115 | if (ret) | ||
116 | goto release; | ||
117 | |||
118 | sdio_set_block_size(func, 512); | ||
119 | |||
120 | SET_IEEE80211_DEV(hw, &func->dev); | ||
121 | wl->if_priv = func; | ||
122 | wl->if_ops = &wl1251_sdio_ops; | ||
123 | wl->set_power = wl1251_sdio_set_power; | ||
124 | |||
125 | sdio_release_host(func); | ||
126 | ret = wl1251_init_ieee80211(wl); | ||
127 | sdio_claim_host(func); | ||
128 | if (ret) | ||
129 | goto disable; | ||
130 | |||
131 | ret = sdio_claim_irq(func, wl1251_sdio_interrupt); | ||
132 | if (ret) | ||
133 | goto no_irq; | ||
134 | |||
135 | sdio_release_host(func); | ||
136 | sdio_set_drvdata(func, wl); | ||
137 | return ret; | ||
138 | |||
139 | no_irq: | ||
140 | wl1251_free_hw(wl); | ||
141 | disable: | ||
142 | sdio_disable_func(func); | ||
143 | release: | ||
144 | sdio_release_host(func); | ||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static void __devexit wl1251_sdio_remove(struct sdio_func *func) | ||
149 | { | ||
150 | struct wl1251 *wl = sdio_get_drvdata(func); | ||
151 | |||
152 | wl1251_free_hw(wl); | ||
153 | |||
154 | sdio_claim_host(func); | ||
155 | sdio_release_irq(func); | ||
156 | sdio_disable_func(func); | ||
157 | sdio_release_host(func); | ||
158 | } | ||
159 | |||
160 | static struct sdio_driver wl1251_sdio_driver = { | ||
161 | .name = "wl1251_sdio", | ||
162 | .id_table = wl1251_devices, | ||
163 | .probe = wl1251_sdio_probe, | ||
164 | .remove = __devexit_p(wl1251_sdio_remove), | ||
165 | }; | ||
166 | |||
167 | static int __init wl1251_sdio_init(void) | ||
168 | { | ||
169 | int err; | ||
170 | |||
171 | err = sdio_register_driver(&wl1251_sdio_driver); | ||
172 | if (err) | ||
173 | wl1251_error("failed to register sdio driver: %d", err); | ||
174 | return err; | ||
175 | } | ||
176 | |||
177 | static void __exit wl1251_sdio_exit(void) | ||
178 | { | ||
179 | sdio_unregister_driver(&wl1251_sdio_driver); | ||
180 | wl1251_notice("unloaded"); | ||
181 | } | ||
182 | |||
183 | module_init(wl1251_sdio_init); | ||
184 | module_exit(wl1251_sdio_exit); | ||
185 | |||
186 | MODULE_LICENSE("GPL"); | ||
187 | MODULE_AUTHOR("Kalle Valo <Kalle.Valo@nokia.com>"); | ||
188 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | ||