2 * Mac80211 SDIO driver for ST-Ericsson CW1200 device
4 * Copyright (c) 2010, ST-Ericsson
5 * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/version.h>
13 #include <linux/module.h>
14 #include <linux/gpio.h>
15 #include <linux/delay.h>
16 #include <linux/mmc/host.h>
17 #include <linux/mmc/sdio_func.h>
18 #include <linux/mmc/card.h>
19 #include <linux/mmc/sdio.h>
20 #include <net/mac80211.h>
24 #include <linux/cw1200_platform.h>
27 MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>");
28 MODULE_DESCRIPTION("mac80211 ST-Ericsson CW1200 SDIO driver");
29 MODULE_LICENSE("GPL");
31 #define SDIO_BLOCK_SIZE (512)
34 struct sdio_func
*func
;
35 struct cw1200_common
*core
;
36 const struct cw1200_platform_data_sdio
*pdata
;
39 #ifndef SDIO_VENDOR_ID_STE
40 #define SDIO_VENDOR_ID_STE 0x0020
43 #ifndef SDIO_DEVICE_ID_STE_CW1200
44 #define SDIO_DEVICE_ID_STE_CW1200 0x2280
47 static const struct sdio_device_id cw1200_sdio_ids
[] = {
48 { SDIO_DEVICE(SDIO_VENDOR_ID_STE
, SDIO_DEVICE_ID_STE_CW1200
) },
49 { /* end: all zeroes */ },
52 /* sbus_ops implemetation */
54 static int cw1200_sdio_memcpy_fromio(struct sbus_priv
*self
,
58 return sdio_memcpy_fromio(self
->func
, dst
, addr
, count
);
61 static int cw1200_sdio_memcpy_toio(struct sbus_priv
*self
,
63 const void *src
, int count
)
65 return sdio_memcpy_toio(self
->func
, addr
, (void *)src
, count
);
68 static void cw1200_sdio_lock(struct sbus_priv
*self
)
70 sdio_claim_host(self
->func
);
73 static void cw1200_sdio_unlock(struct sbus_priv
*self
)
75 sdio_release_host(self
->func
);
78 static void cw1200_sdio_irq_handler(struct sdio_func
*func
)
80 struct sbus_priv
*self
= sdio_get_drvdata(func
);
82 /* note: sdio_host already claimed here. */
84 cw1200_irq_handler(self
->core
);
87 static irqreturn_t
cw1200_gpio_hardirq(int irq
, void *dev_id
)
89 return IRQ_WAKE_THREAD
;
92 static irqreturn_t
cw1200_gpio_irq(int irq
, void *dev_id
)
94 struct sbus_priv
*self
= dev_id
;
97 sdio_claim_host(self
->func
);
98 cw1200_irq_handler(self
->core
);
99 sdio_release_host(self
->func
);
106 static int cw1200_request_irq(struct sbus_priv
*self
)
109 const struct resource
*irq
= self
->pdata
->irq
;
112 cccr
= sdio_f0_readb(self
->func
, SDIO_CCCR_IENx
, &ret
);
116 /* Master interrupt enable ... */
119 /* ... for our function */
120 cccr
|= BIT(self
->func
->num
);
122 sdio_f0_writeb(self
->func
, cccr
, SDIO_CCCR_IENx
, &ret
);
126 ret
= enable_irq_wake(irq
->start
);
130 /* Request the IRQ */
131 ret
= request_threaded_irq(irq
->start
, cw1200_gpio_hardirq
,
133 IRQF_TRIGGER_HIGH
| IRQF_ONESHOT
,
144 static int cw1200_sdio_irq_subscribe(struct sbus_priv
*self
)
148 pr_debug("SW IRQ subscribe\n");
149 sdio_claim_host(self
->func
);
150 if (self
->pdata
->irq
)
151 ret
= cw1200_request_irq(self
);
153 ret
= sdio_claim_irq(self
->func
, cw1200_sdio_irq_handler
);
155 sdio_release_host(self
->func
);
159 static int cw1200_sdio_irq_unsubscribe(struct sbus_priv
*self
)
163 pr_debug("SW IRQ unsubscribe\n");
165 if (self
->pdata
->irq
) {
166 disable_irq_wake(self
->pdata
->irq
->start
);
167 free_irq(self
->pdata
->irq
->start
, self
);
169 sdio_claim_host(self
->func
);
170 ret
= sdio_release_irq(self
->func
);
171 sdio_release_host(self
->func
);
176 static int cw1200_sdio_off(const struct cw1200_platform_data_sdio
*pdata
)
178 const struct resource
*reset
= pdata
->reset
;
181 gpio_set_value(reset
->start
, 0);
182 msleep(30); /* Min is 2 * CLK32K cycles */
183 gpio_free(reset
->start
);
186 if (pdata
->power_ctrl
)
187 pdata
->power_ctrl(pdata
, false);
189 pdata
->clk_ctrl(pdata
, false);
194 static int cw1200_sdio_on(const struct cw1200_platform_data_sdio
*pdata
)
196 const struct resource
*reset
= pdata
->reset
;
197 const struct resource
*powerup
= pdata
->reset
;
199 /* Ensure I/Os are pulled low */
201 gpio_request(reset
->start
, reset
->name
);
202 gpio_direction_output(reset
->start
, 0);
205 gpio_request(powerup
->start
, powerup
->name
);
206 gpio_direction_output(powerup
->start
, 0);
208 if (reset
|| powerup
)
209 msleep(50); /* Settle time */
211 /* Enable 3v3 and 1v8 to hardware */
212 if (pdata
->power_ctrl
) {
213 if (pdata
->power_ctrl(pdata
, true)) {
214 pr_err("power_ctrl() failed!\n");
220 if (pdata
->clk_ctrl
) {
221 if (pdata
->clk_ctrl(pdata
, true)) {
222 pr_err("clk_ctrl() failed!\n");
225 msleep(10); /* Delay until clock is stable for 2 cycles */
228 /* Enable POWERUP signal */
230 gpio_set_value(powerup
->start
, 1);
231 msleep(250); /* or more..? */
233 /* Enable RSTn signal */
235 gpio_set_value(reset
->start
, 1);
236 msleep(50); /* Or more..? */
241 static size_t cw1200_sdio_align_size(struct sbus_priv
*self
, size_t size
)
243 if (self
->pdata
->no_nptb
)
244 size
= round_up(size
, SDIO_BLOCK_SIZE
);
246 size
= sdio_align_size(self
->func
, size
);
251 static int cw1200_sdio_pm(struct sbus_priv
*self
, bool suspend
)
255 if (self
->pdata
->irq
)
256 ret
= irq_set_irq_wake(self
->pdata
->irq
->start
, suspend
);
260 static struct sbus_ops cw1200_sdio_sbus_ops
= {
261 .sbus_memcpy_fromio
= cw1200_sdio_memcpy_fromio
,
262 .sbus_memcpy_toio
= cw1200_sdio_memcpy_toio
,
263 .lock
= cw1200_sdio_lock
,
264 .unlock
= cw1200_sdio_unlock
,
265 .align_size
= cw1200_sdio_align_size
,
266 .power_mgmt
= cw1200_sdio_pm
,
269 /* Probe Function to be called by SDIO stack when device is discovered */
270 static int cw1200_sdio_probe(struct sdio_func
*func
,
271 const struct sdio_device_id
*id
)
273 struct sbus_priv
*self
;
276 pr_info("cw1200_wlan_sdio: Probe called\n");
278 /* We are only able to handle the wlan function */
279 if (func
->num
!= 0x01)
282 self
= kzalloc(sizeof(*self
), GFP_KERNEL
);
284 pr_err("Can't allocate SDIO sbus_priv.\n");
288 func
->card
->quirks
|= MMC_QUIRK_LENIENT_FN0
;
290 self
->pdata
= cw1200_get_platform_data();
292 sdio_set_drvdata(func
, self
);
293 sdio_claim_host(func
);
294 sdio_enable_func(func
);
295 sdio_release_host(func
);
297 status
= cw1200_sdio_irq_subscribe(self
);
299 status
= cw1200_core_probe(&cw1200_sdio_sbus_ops
,
300 self
, &func
->dev
, &self
->core
,
301 self
->pdata
->ref_clk
,
302 self
->pdata
->macaddr
,
303 self
->pdata
->sdd_file
,
304 self
->pdata
->have_5ghz
);
306 cw1200_sdio_irq_unsubscribe(self
);
307 sdio_claim_host(func
);
308 sdio_disable_func(func
);
309 sdio_release_host(func
);
310 sdio_set_drvdata(func
, NULL
);
317 /* Disconnect Function to be called by SDIO stack when
318 * device is disconnected */
319 static void cw1200_sdio_disconnect(struct sdio_func
*func
)
321 struct sbus_priv
*self
= sdio_get_drvdata(func
);
324 cw1200_sdio_irq_unsubscribe(self
);
326 cw1200_core_release(self
->core
);
329 sdio_claim_host(func
);
330 sdio_disable_func(func
);
331 sdio_release_host(func
);
332 sdio_set_drvdata(func
, NULL
);
337 static int cw1200_sdio_suspend(struct device
*dev
)
340 struct sdio_func
*func
= dev_to_sdio_func(dev
);
341 struct sbus_priv
*self
= sdio_get_drvdata(func
);
343 if (!cw1200_can_suspend(self
->core
))
346 /* Notify SDIO that CW1200 will remain powered during suspend */
347 ret
= sdio_set_host_pm_flags(func
, MMC_PM_KEEP_POWER
);
349 pr_err("Error setting SDIO pm flags: %i\n", ret
);
354 static int cw1200_sdio_resume(struct device
*dev
)
359 static const struct dev_pm_ops cw1200_pm_ops
= {
360 .suspend
= cw1200_sdio_suspend
,
361 .resume
= cw1200_sdio_resume
,
364 static struct sdio_driver sdio_driver
= {
365 .name
= "cw1200_wlan_sdio",
366 .id_table
= cw1200_sdio_ids
,
367 .probe
= cw1200_sdio_probe
,
368 .remove
= cw1200_sdio_disconnect
,
370 .pm
= &cw1200_pm_ops
,
374 /* Init Module function -> Called by insmod */
375 static int __init
cw1200_sdio_init(void)
377 const struct cw1200_platform_data_sdio
*pdata
;
380 pdata
= cw1200_get_platform_data();
382 if (cw1200_sdio_on(pdata
)) {
387 ret
= sdio_register_driver(&sdio_driver
);
394 cw1200_sdio_off(pdata
);
398 /* Called at Driver Unloading */
399 static void __exit
cw1200_sdio_exit(void)
401 const struct cw1200_platform_data_sdio
*pdata
;
402 pdata
= cw1200_get_platform_data();
403 sdio_unregister_driver(&sdio_driver
);
404 cw1200_sdio_off(pdata
);
408 module_init(cw1200_sdio_init
);
409 module_exit(cw1200_sdio_exit
);