aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_sdio.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
index c561332e7009..b901b6135654 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -37,11 +37,17 @@
37#define SDIO_DEVICE_ID_TI_WL1251 0x9066 37#define SDIO_DEVICE_ID_TI_WL1251 0x9066
38#endif 38#endif
39 39
40struct wl1251_sdio {
41 struct sdio_func *func;
42 u32 elp_val;
43};
44
40static struct wl12xx_platform_data *wl12xx_board_data; 45static struct wl12xx_platform_data *wl12xx_board_data;
41 46
42static struct sdio_func *wl_to_func(struct wl1251 *wl) 47static struct sdio_func *wl_to_func(struct wl1251 *wl)
43{ 48{
44 return wl->if_priv; 49 struct wl1251_sdio *wl_sdio = wl->if_priv;
50 return wl_sdio->func;
45} 51}
46 52
47static void wl1251_sdio_interrupt(struct sdio_func *func) 53static void wl1251_sdio_interrupt(struct sdio_func *func)
@@ -90,10 +96,17 @@ static void wl1251_sdio_write(struct wl1251 *wl, int addr,
90static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) 96static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
91{ 97{
92 int ret = 0; 98 int ret = 0;
93 struct sdio_func *func = wl_to_func(wl); 99 struct wl1251_sdio *wl_sdio = wl->if_priv;
94 100 struct sdio_func *func = wl_sdio->func;
101
102 /*
103 * The hardware only supports RAW (read after write) access for
104 * reading, regular sdio_readb won't work here (it interprets
105 * the unused bits of CMD52 as write data even if we send read
106 * request).
107 */
95 sdio_claim_host(func); 108 sdio_claim_host(func);
96 *val = sdio_readb(func, addr, &ret); 109 *val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret);
97 sdio_release_host(func); 110 sdio_release_host(func);
98 111
99 if (ret) 112 if (ret)
@@ -103,7 +116,8 @@ static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
103static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) 116static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
104{ 117{
105 int ret = 0; 118 int ret = 0;
106 struct sdio_func *func = wl_to_func(wl); 119 struct wl1251_sdio *wl_sdio = wl->if_priv;
120 struct sdio_func *func = wl_sdio->func;
107 121
108 sdio_claim_host(func); 122 sdio_claim_host(func);
109 sdio_writeb(func, val, addr, &ret); 123 sdio_writeb(func, val, addr, &ret);
@@ -111,6 +125,8 @@ static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
111 125
112 if (ret) 126 if (ret)
113 wl1251_error("sdio_writeb failed (%d)", ret); 127 wl1251_error("sdio_writeb failed (%d)", ret);
128 else
129 wl_sdio->elp_val = val;
114} 130}
115 131
116static void wl1251_sdio_reset(struct wl1251 *wl) 132static void wl1251_sdio_reset(struct wl1251 *wl)
@@ -197,6 +213,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
197 int ret; 213 int ret;
198 struct wl1251 *wl; 214 struct wl1251 *wl;
199 struct ieee80211_hw *hw; 215 struct ieee80211_hw *hw;
216 struct wl1251_sdio *wl_sdio;
200 217
201 hw = wl1251_alloc_hw(); 218 hw = wl1251_alloc_hw();
202 if (IS_ERR(hw)) 219 if (IS_ERR(hw))
@@ -204,6 +221,12 @@ static int wl1251_sdio_probe(struct sdio_func *func,
204 221
205 wl = hw->priv; 222 wl = hw->priv;
206 223
224 wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL);
225 if (wl_sdio == NULL) {
226 ret = -ENOMEM;
227 goto out_free_hw;
228 }
229
207 sdio_claim_host(func); 230 sdio_claim_host(func);
208 ret = sdio_enable_func(func); 231 ret = sdio_enable_func(func);
209 if (ret) 232 if (ret)
@@ -213,7 +236,8 @@ static int wl1251_sdio_probe(struct sdio_func *func,
213 sdio_release_host(func); 236 sdio_release_host(func);
214 237
215 SET_IEEE80211_DEV(hw, &func->dev); 238 SET_IEEE80211_DEV(hw, &func->dev);
216 wl->if_priv = func; 239 wl_sdio->func = func;
240 wl->if_priv = wl_sdio;
217 wl->if_ops = &wl1251_sdio_ops; 241 wl->if_ops = &wl1251_sdio_ops;
218 wl->set_power = wl1251_sdio_set_power; 242 wl->set_power = wl1251_sdio_set_power;
219 243
@@ -259,6 +283,8 @@ disable:
259 sdio_disable_func(func); 283 sdio_disable_func(func);
260release: 284release:
261 sdio_release_host(func); 285 sdio_release_host(func);
286 kfree(wl_sdio);
287out_free_hw:
262 wl1251_free_hw(wl); 288 wl1251_free_hw(wl);
263 return ret; 289 return ret;
264} 290}
@@ -266,9 +292,11 @@ release:
266static void __devexit wl1251_sdio_remove(struct sdio_func *func) 292static void __devexit wl1251_sdio_remove(struct sdio_func *func)
267{ 293{
268 struct wl1251 *wl = sdio_get_drvdata(func); 294 struct wl1251 *wl = sdio_get_drvdata(func);
295 struct wl1251_sdio *wl_sdio = wl->if_priv;
269 296
270 if (wl->irq) 297 if (wl->irq)
271 free_irq(wl->irq, wl); 298 free_irq(wl->irq, wl);
299 kfree(wl_sdio);
272 wl1251_free_hw(wl); 300 wl1251_free_hw(wl);
273 301
274 sdio_claim_host(func); 302 sdio_claim_host(func);