aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2009-08-07 06:33:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:13:38 -0400
commit3ec410d747fa1da035183c43775a64c0e285e399 (patch)
tree7a0d03a46cc8adf4f42eaa338b30dccb8ebbaf22
parentaf8c78ebbf2a15ecf9b2b6b7b051b0d4c3ba1163 (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/Kconfig11
-rw-r--r--drivers/net/wireless/wl12xx/Makefile1
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_sdio.c188
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
31config 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
31config WL1271 42config 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
6obj-$(CONFIG_WL1251) += wl1251.o 6obj-$(CONFIG_WL1251) += wl1251.o
7obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o 7obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o
8obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o
8 9
9wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ 10wl1271-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
46static struct sdio_func *wl_to_func(struct wl1251 *wl)
47{
48 return wl->if_priv;
49}
50
51static void wl1251_sdio_interrupt(struct sdio_func *func)
52{
53 wl1251_irq(0, sdio_get_drvdata(func));
54}
55
56static const struct sdio_device_id wl1251_devices[] = {
57 { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1251) },
58 {}
59};
60MODULE_DEVICE_TABLE(sdio, wl1251_devices);
61
62
63void 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
75void 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
87void wl1251_sdio_reset(struct wl1251 *wl)
88{
89}
90
91void wl1251_sdio_set_power(bool enable)
92{
93}
94
95struct wl1251_if_operations wl1251_sdio_ops = {
96 .read = wl1251_sdio_read,
97 .write = wl1251_sdio_write,
98 .reset = wl1251_sdio_reset,
99};
100
101int 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
139no_irq:
140 wl1251_free_hw(wl);
141disable:
142 sdio_disable_func(func);
143release:
144 sdio_release_host(func);
145 return ret;
146}
147
148static 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
160static 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
167static 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
177static void __exit wl1251_sdio_exit(void)
178{
179 sdio_unregister_driver(&wl1251_sdio_driver);
180 wl1251_notice("unloaded");
181}
182
183module_init(wl1251_sdio_init);
184module_exit(wl1251_sdio_exit);
185
186MODULE_LICENSE("GPL");
187MODULE_AUTHOR("Kalle Valo <Kalle.Valo@nokia.com>");
188MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");