xref: /linux/drivers/net/wireless/st/cw1200/cw1200_sdio.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2560424e9SKalle Valo /*
3560424e9SKalle Valo  * Mac80211 SDIO driver for ST-Ericsson CW1200 device
4560424e9SKalle Valo  *
5560424e9SKalle Valo  * Copyright (c) 2010, ST-Ericsson
6560424e9SKalle Valo  * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
7560424e9SKalle Valo  */
8560424e9SKalle Valo 
9560424e9SKalle Valo #include <linux/module.h>
10282ccf6eSFlorian Westphal #include <linux/interrupt.h>
11*2719a9e7SLinus Walleij #include <linux/gpio/consumer.h>
12560424e9SKalle Valo #include <linux/delay.h>
13560424e9SKalle Valo #include <linux/mmc/host.h>
14560424e9SKalle Valo #include <linux/mmc/sdio_func.h>
15560424e9SKalle Valo #include <linux/mmc/card.h>
16560424e9SKalle Valo #include <linux/mmc/sdio.h>
1783cee4e6SPali Rohár #include <linux/mmc/sdio_ids.h>
18560424e9SKalle Valo #include <net/mac80211.h>
19560424e9SKalle Valo 
20560424e9SKalle Valo #include "cw1200.h"
21560424e9SKalle Valo #include "hwbus.h"
22560424e9SKalle Valo #include <linux/platform_data/net-cw1200.h>
23560424e9SKalle Valo #include "hwio.h"
24560424e9SKalle Valo 
25560424e9SKalle Valo MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>");
26560424e9SKalle Valo MODULE_DESCRIPTION("mac80211 ST-Ericsson CW1200 SDIO driver");
27560424e9SKalle Valo MODULE_LICENSE("GPL");
28560424e9SKalle Valo 
29560424e9SKalle Valo #define SDIO_BLOCK_SIZE (512)
30560424e9SKalle Valo 
31560424e9SKalle Valo /* Default platform data for Sagrad modules */
32560424e9SKalle Valo static struct cw1200_platform_data_sdio sagrad_109x_evk_platform_data = {
33560424e9SKalle Valo 	.ref_clk = 38400,
34560424e9SKalle Valo 	.have_5ghz = false,
35560424e9SKalle Valo 	.sdd_file = "sdd_sagrad_1091_1098.bin",
36560424e9SKalle Valo };
37560424e9SKalle Valo 
38560424e9SKalle Valo /* Allow platform data to be overridden */
39560424e9SKalle Valo static struct cw1200_platform_data_sdio *global_plat_data = &sagrad_109x_evk_platform_data;
40560424e9SKalle Valo 
cw1200_sdio_set_platform_data(struct cw1200_platform_data_sdio * pdata)41560424e9SKalle Valo void __init cw1200_sdio_set_platform_data(struct cw1200_platform_data_sdio *pdata)
42560424e9SKalle Valo {
43560424e9SKalle Valo 	global_plat_data = pdata;
44560424e9SKalle Valo }
45560424e9SKalle Valo 
46560424e9SKalle Valo struct hwbus_priv {
47560424e9SKalle Valo 	struct sdio_func	*func;
48560424e9SKalle Valo 	struct cw1200_common	*core;
49560424e9SKalle Valo 	const struct cw1200_platform_data_sdio *pdata;
50560424e9SKalle Valo };
51560424e9SKalle Valo 
52560424e9SKalle Valo static const struct sdio_device_id cw1200_sdio_ids[] = {
53560424e9SKalle Valo 	{ SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200) },
54560424e9SKalle Valo 	{ /* end: all zeroes */			},
55560424e9SKalle Valo };
56dd778f89SZou Wei MODULE_DEVICE_TABLE(sdio, cw1200_sdio_ids);
57560424e9SKalle Valo 
58560424e9SKalle Valo /* hwbus_ops implemetation */
59560424e9SKalle Valo 
cw1200_sdio_memcpy_fromio(struct hwbus_priv * self,unsigned int addr,void * dst,int count)60560424e9SKalle Valo static int cw1200_sdio_memcpy_fromio(struct hwbus_priv *self,
61560424e9SKalle Valo 				     unsigned int addr,
62560424e9SKalle Valo 				     void *dst, int count)
63560424e9SKalle Valo {
64560424e9SKalle Valo 	return sdio_memcpy_fromio(self->func, dst, addr, count);
65560424e9SKalle Valo }
66560424e9SKalle Valo 
cw1200_sdio_memcpy_toio(struct hwbus_priv * self,unsigned int addr,const void * src,int count)67560424e9SKalle Valo static int cw1200_sdio_memcpy_toio(struct hwbus_priv *self,
68560424e9SKalle Valo 				   unsigned int addr,
69560424e9SKalle Valo 				   const void *src, int count)
70560424e9SKalle Valo {
71560424e9SKalle Valo 	return sdio_memcpy_toio(self->func, addr, (void *)src, count);
72560424e9SKalle Valo }
73560424e9SKalle Valo 
cw1200_sdio_lock(struct hwbus_priv * self)74560424e9SKalle Valo static void cw1200_sdio_lock(struct hwbus_priv *self)
75560424e9SKalle Valo {
76560424e9SKalle Valo 	sdio_claim_host(self->func);
77560424e9SKalle Valo }
78560424e9SKalle Valo 
cw1200_sdio_unlock(struct hwbus_priv * self)79560424e9SKalle Valo static void cw1200_sdio_unlock(struct hwbus_priv *self)
80560424e9SKalle Valo {
81560424e9SKalle Valo 	sdio_release_host(self->func);
82560424e9SKalle Valo }
83560424e9SKalle Valo 
cw1200_sdio_irq_handler(struct sdio_func * func)84560424e9SKalle Valo static void cw1200_sdio_irq_handler(struct sdio_func *func)
85560424e9SKalle Valo {
86560424e9SKalle Valo 	struct hwbus_priv *self = sdio_get_drvdata(func);
87560424e9SKalle Valo 
88560424e9SKalle Valo 	/* note:  sdio_host already claimed here. */
89560424e9SKalle Valo 	if (self->core)
90560424e9SKalle Valo 		cw1200_irq_handler(self->core);
91560424e9SKalle Valo }
92560424e9SKalle Valo 
cw1200_gpio_hardirq(int irq,void * dev_id)93560424e9SKalle Valo static irqreturn_t cw1200_gpio_hardirq(int irq, void *dev_id)
94560424e9SKalle Valo {
95560424e9SKalle Valo 	return IRQ_WAKE_THREAD;
96560424e9SKalle Valo }
97560424e9SKalle Valo 
cw1200_gpio_irq(int irq,void * dev_id)98560424e9SKalle Valo static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id)
99560424e9SKalle Valo {
100560424e9SKalle Valo 	struct hwbus_priv *self = dev_id;
101560424e9SKalle Valo 
102560424e9SKalle Valo 	if (self->core) {
103560424e9SKalle Valo 		cw1200_sdio_lock(self);
104560424e9SKalle Valo 		cw1200_irq_handler(self->core);
105560424e9SKalle Valo 		cw1200_sdio_unlock(self);
106560424e9SKalle Valo 		return IRQ_HANDLED;
107560424e9SKalle Valo 	} else {
108560424e9SKalle Valo 		return IRQ_NONE;
109560424e9SKalle Valo 	}
110560424e9SKalle Valo }
111560424e9SKalle Valo 
cw1200_request_irq(struct hwbus_priv * self)112560424e9SKalle Valo static int cw1200_request_irq(struct hwbus_priv *self)
113560424e9SKalle Valo {
114560424e9SKalle Valo 	int ret;
115560424e9SKalle Valo 	u8 cccr;
116560424e9SKalle Valo 
117560424e9SKalle Valo 	cccr = sdio_f0_readb(self->func, SDIO_CCCR_IENx, &ret);
118560424e9SKalle Valo 	if (WARN_ON(ret))
119560424e9SKalle Valo 		goto err;
120560424e9SKalle Valo 
121560424e9SKalle Valo 	/* Master interrupt enable ... */
122560424e9SKalle Valo 	cccr |= BIT(0);
123560424e9SKalle Valo 
124560424e9SKalle Valo 	/* ... for our function */
125560424e9SKalle Valo 	cccr |= BIT(self->func->num);
126560424e9SKalle Valo 
127560424e9SKalle Valo 	sdio_f0_writeb(self->func, cccr, SDIO_CCCR_IENx, &ret);
128560424e9SKalle Valo 	if (WARN_ON(ret))
129560424e9SKalle Valo 		goto err;
130560424e9SKalle Valo 
131560424e9SKalle Valo 	ret = enable_irq_wake(self->pdata->irq);
132560424e9SKalle Valo 	if (WARN_ON(ret))
133560424e9SKalle Valo 		goto err;
134560424e9SKalle Valo 
135560424e9SKalle Valo 	/* Request the IRQ */
136560424e9SKalle Valo 	ret =  request_threaded_irq(self->pdata->irq, cw1200_gpio_hardirq,
137560424e9SKalle Valo 				    cw1200_gpio_irq,
138560424e9SKalle Valo 				    IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
139560424e9SKalle Valo 				    "cw1200_wlan_irq", self);
140560424e9SKalle Valo 	if (WARN_ON(ret))
141560424e9SKalle Valo 		goto err;
142560424e9SKalle Valo 
143560424e9SKalle Valo 	return 0;
144560424e9SKalle Valo 
145560424e9SKalle Valo err:
146560424e9SKalle Valo 	return ret;
147560424e9SKalle Valo }
148560424e9SKalle Valo 
cw1200_sdio_irq_subscribe(struct hwbus_priv * self)149560424e9SKalle Valo static int cw1200_sdio_irq_subscribe(struct hwbus_priv *self)
150560424e9SKalle Valo {
151560424e9SKalle Valo 	int ret = 0;
152560424e9SKalle Valo 
153560424e9SKalle Valo 	pr_debug("SW IRQ subscribe\n");
154560424e9SKalle Valo 	sdio_claim_host(self->func);
155560424e9SKalle Valo 	if (self->pdata->irq)
156560424e9SKalle Valo 		ret = cw1200_request_irq(self);
157560424e9SKalle Valo 	else
158560424e9SKalle Valo 		ret = sdio_claim_irq(self->func, cw1200_sdio_irq_handler);
159560424e9SKalle Valo 
160560424e9SKalle Valo 	sdio_release_host(self->func);
161560424e9SKalle Valo 	return ret;
162560424e9SKalle Valo }
163560424e9SKalle Valo 
cw1200_sdio_irq_unsubscribe(struct hwbus_priv * self)164560424e9SKalle Valo static int cw1200_sdio_irq_unsubscribe(struct hwbus_priv *self)
165560424e9SKalle Valo {
166560424e9SKalle Valo 	int ret = 0;
167560424e9SKalle Valo 
168560424e9SKalle Valo 	pr_debug("SW IRQ unsubscribe\n");
169560424e9SKalle Valo 
170560424e9SKalle Valo 	if (self->pdata->irq) {
171560424e9SKalle Valo 		disable_irq_wake(self->pdata->irq);
172560424e9SKalle Valo 		free_irq(self->pdata->irq, self);
173560424e9SKalle Valo 	} else {
174560424e9SKalle Valo 		sdio_claim_host(self->func);
175560424e9SKalle Valo 		ret = sdio_release_irq(self->func);
176560424e9SKalle Valo 		sdio_release_host(self->func);
177560424e9SKalle Valo 	}
178560424e9SKalle Valo 	return ret;
179560424e9SKalle Valo }
180560424e9SKalle Valo 
181*2719a9e7SLinus Walleij /* Like the rest of the driver, this only supports one device per system */
182*2719a9e7SLinus Walleij static struct gpio_desc *cw1200_reset;
183*2719a9e7SLinus Walleij static struct gpio_desc *cw1200_powerup;
184*2719a9e7SLinus Walleij 
cw1200_sdio_off(const struct cw1200_platform_data_sdio * pdata)185560424e9SKalle Valo static int cw1200_sdio_off(const struct cw1200_platform_data_sdio *pdata)
186560424e9SKalle Valo {
187*2719a9e7SLinus Walleij 	if (cw1200_reset) {
188*2719a9e7SLinus Walleij 		gpiod_set_value(cw1200_reset, 0);
189560424e9SKalle Valo 		msleep(30); /* Min is 2 * CLK32K cycles */
190560424e9SKalle Valo 	}
191560424e9SKalle Valo 
192560424e9SKalle Valo 	if (pdata->power_ctrl)
193560424e9SKalle Valo 		pdata->power_ctrl(pdata, false);
194560424e9SKalle Valo 	if (pdata->clk_ctrl)
195560424e9SKalle Valo 		pdata->clk_ctrl(pdata, false);
196560424e9SKalle Valo 
197560424e9SKalle Valo 	return 0;
198560424e9SKalle Valo }
199560424e9SKalle Valo 
cw1200_sdio_on(const struct cw1200_platform_data_sdio * pdata)200560424e9SKalle Valo static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata)
201560424e9SKalle Valo {
202*2719a9e7SLinus Walleij 	/* Ensure I/Os are pulled low (reset is active low) */
203*2719a9e7SLinus Walleij 	cw1200_reset = devm_gpiod_get_optional(NULL, "reset", GPIOD_OUT_HIGH);
204*2719a9e7SLinus Walleij 	if (IS_ERR(cw1200_reset)) {
205*2719a9e7SLinus Walleij 		pr_err("could not get CW1200 SDIO reset GPIO\n");
206*2719a9e7SLinus Walleij 		return PTR_ERR(cw1200_reset);
207560424e9SKalle Valo 	}
208*2719a9e7SLinus Walleij 	gpiod_set_consumer_name(cw1200_reset, "cw1200_wlan_reset");
209*2719a9e7SLinus Walleij 	cw1200_powerup = devm_gpiod_get_optional(NULL, "powerup", GPIOD_OUT_LOW);
210*2719a9e7SLinus Walleij 	if (IS_ERR(cw1200_powerup)) {
211*2719a9e7SLinus Walleij 		pr_err("could not get CW1200 SDIO powerup GPIO\n");
212*2719a9e7SLinus Walleij 		return PTR_ERR(cw1200_powerup);
213560424e9SKalle Valo 	}
214*2719a9e7SLinus Walleij 	gpiod_set_consumer_name(cw1200_powerup, "cw1200_wlan_powerup");
215*2719a9e7SLinus Walleij 
216*2719a9e7SLinus Walleij 	if (cw1200_reset || cw1200_powerup)
217560424e9SKalle Valo 		msleep(10); /* Settle time? */
218560424e9SKalle Valo 
219560424e9SKalle Valo 	/* Enable 3v3 and 1v8 to hardware */
220560424e9SKalle Valo 	if (pdata->power_ctrl) {
221560424e9SKalle Valo 		if (pdata->power_ctrl(pdata, true)) {
222560424e9SKalle Valo 			pr_err("power_ctrl() failed!\n");
223560424e9SKalle Valo 			return -1;
224560424e9SKalle Valo 		}
225560424e9SKalle Valo 	}
226560424e9SKalle Valo 
227560424e9SKalle Valo 	/* Enable CLK32K */
228560424e9SKalle Valo 	if (pdata->clk_ctrl) {
229560424e9SKalle Valo 		if (pdata->clk_ctrl(pdata, true)) {
230560424e9SKalle Valo 			pr_err("clk_ctrl() failed!\n");
231560424e9SKalle Valo 			return -1;
232560424e9SKalle Valo 		}
233560424e9SKalle Valo 		msleep(10); /* Delay until clock is stable for 2 cycles */
234560424e9SKalle Valo 	}
235560424e9SKalle Valo 
236560424e9SKalle Valo 	/* Enable POWERUP signal */
237*2719a9e7SLinus Walleij 	if (cw1200_powerup) {
238*2719a9e7SLinus Walleij 		gpiod_set_value(cw1200_powerup, 1);
239560424e9SKalle Valo 		msleep(250); /* or more..? */
240560424e9SKalle Valo 	}
241*2719a9e7SLinus Walleij 	/* Deassert RSTn signal, note active low */
242*2719a9e7SLinus Walleij 	if (cw1200_reset) {
243*2719a9e7SLinus Walleij 		gpiod_set_value(cw1200_reset, 0);
244560424e9SKalle Valo 		msleep(50); /* Or more..? */
245560424e9SKalle Valo 	}
246560424e9SKalle Valo 	return 0;
247560424e9SKalle Valo }
248560424e9SKalle Valo 
cw1200_sdio_align_size(struct hwbus_priv * self,size_t size)249560424e9SKalle Valo static size_t cw1200_sdio_align_size(struct hwbus_priv *self, size_t size)
250560424e9SKalle Valo {
251560424e9SKalle Valo 	if (self->pdata->no_nptb)
252560424e9SKalle Valo 		size = round_up(size, SDIO_BLOCK_SIZE);
253560424e9SKalle Valo 	else
254560424e9SKalle Valo 		size = sdio_align_size(self->func, size);
255560424e9SKalle Valo 
256560424e9SKalle Valo 	return size;
257560424e9SKalle Valo }
258560424e9SKalle Valo 
cw1200_sdio_pm(struct hwbus_priv * self,bool suspend)259560424e9SKalle Valo static int cw1200_sdio_pm(struct hwbus_priv *self, bool suspend)
260560424e9SKalle Valo {
261560424e9SKalle Valo 	int ret = 0;
262560424e9SKalle Valo 
263560424e9SKalle Valo 	if (self->pdata->irq)
264560424e9SKalle Valo 		ret = irq_set_irq_wake(self->pdata->irq, suspend);
265560424e9SKalle Valo 	return ret;
266560424e9SKalle Valo }
267560424e9SKalle Valo 
2683ac27dd3SBhumika Goyal static const struct hwbus_ops cw1200_sdio_hwbus_ops = {
269560424e9SKalle Valo 	.hwbus_memcpy_fromio	= cw1200_sdio_memcpy_fromio,
270560424e9SKalle Valo 	.hwbus_memcpy_toio	= cw1200_sdio_memcpy_toio,
271560424e9SKalle Valo 	.lock			= cw1200_sdio_lock,
272560424e9SKalle Valo 	.unlock			= cw1200_sdio_unlock,
273560424e9SKalle Valo 	.align_size		= cw1200_sdio_align_size,
274560424e9SKalle Valo 	.power_mgmt		= cw1200_sdio_pm,
275560424e9SKalle Valo };
276560424e9SKalle Valo 
277560424e9SKalle Valo /* Probe Function to be called by SDIO stack when device is discovered */
cw1200_sdio_probe(struct sdio_func * func,const struct sdio_device_id * id)278560424e9SKalle Valo static int cw1200_sdio_probe(struct sdio_func *func,
279560424e9SKalle Valo 			     const struct sdio_device_id *id)
280560424e9SKalle Valo {
281560424e9SKalle Valo 	struct hwbus_priv *self;
282560424e9SKalle Valo 	int status;
283560424e9SKalle Valo 
284560424e9SKalle Valo 	pr_info("cw1200_wlan_sdio: Probe called\n");
285560424e9SKalle Valo 
286560424e9SKalle Valo 	/* We are only able to handle the wlan function */
287560424e9SKalle Valo 	if (func->num != 0x01)
288560424e9SKalle Valo 		return -ENODEV;
289560424e9SKalle Valo 
290560424e9SKalle Valo 	self = kzalloc(sizeof(*self), GFP_KERNEL);
291560424e9SKalle Valo 	if (!self) {
292560424e9SKalle Valo 		pr_err("Can't allocate SDIO hwbus_priv.\n");
293560424e9SKalle Valo 		return -ENOMEM;
294560424e9SKalle Valo 	}
295560424e9SKalle Valo 
296560424e9SKalle Valo 	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
297560424e9SKalle Valo 
298560424e9SKalle Valo 	self->pdata = global_plat_data; /* FIXME */
299560424e9SKalle Valo 	self->func = func;
300560424e9SKalle Valo 	sdio_set_drvdata(func, self);
301560424e9SKalle Valo 	sdio_claim_host(func);
302560424e9SKalle Valo 	sdio_enable_func(func);
303560424e9SKalle Valo 	sdio_release_host(func);
304560424e9SKalle Valo 
305560424e9SKalle Valo 	status = cw1200_sdio_irq_subscribe(self);
306560424e9SKalle Valo 
307560424e9SKalle Valo 	status = cw1200_core_probe(&cw1200_sdio_hwbus_ops,
308560424e9SKalle Valo 				   self, &func->dev, &self->core,
309560424e9SKalle Valo 				   self->pdata->ref_clk,
310560424e9SKalle Valo 				   self->pdata->macaddr,
311560424e9SKalle Valo 				   self->pdata->sdd_file,
312560424e9SKalle Valo 				   self->pdata->have_5ghz);
313560424e9SKalle Valo 	if (status) {
314560424e9SKalle Valo 		cw1200_sdio_irq_unsubscribe(self);
315560424e9SKalle Valo 		sdio_claim_host(func);
316560424e9SKalle Valo 		sdio_disable_func(func);
317560424e9SKalle Valo 		sdio_release_host(func);
318560424e9SKalle Valo 		sdio_set_drvdata(func, NULL);
319560424e9SKalle Valo 		kfree(self);
320560424e9SKalle Valo 	}
321560424e9SKalle Valo 
322560424e9SKalle Valo 	return status;
323560424e9SKalle Valo }
324560424e9SKalle Valo 
325560424e9SKalle Valo /* Disconnect Function to be called by SDIO stack when
326560424e9SKalle Valo  * device is disconnected
327560424e9SKalle Valo  */
cw1200_sdio_disconnect(struct sdio_func * func)328560424e9SKalle Valo static void cw1200_sdio_disconnect(struct sdio_func *func)
329560424e9SKalle Valo {
330560424e9SKalle Valo 	struct hwbus_priv *self = sdio_get_drvdata(func);
331560424e9SKalle Valo 
332560424e9SKalle Valo 	if (self) {
333560424e9SKalle Valo 		cw1200_sdio_irq_unsubscribe(self);
334560424e9SKalle Valo 		if (self->core) {
335560424e9SKalle Valo 			cw1200_core_release(self->core);
336560424e9SKalle Valo 			self->core = NULL;
337560424e9SKalle Valo 		}
338560424e9SKalle Valo 		sdio_claim_host(func);
339560424e9SKalle Valo 		sdio_disable_func(func);
340560424e9SKalle Valo 		sdio_release_host(func);
341560424e9SKalle Valo 		sdio_set_drvdata(func, NULL);
342560424e9SKalle Valo 		kfree(self);
343560424e9SKalle Valo 	}
344560424e9SKalle Valo }
345560424e9SKalle Valo 
346560424e9SKalle Valo #ifdef CONFIG_PM
cw1200_sdio_suspend(struct device * dev)347560424e9SKalle Valo static int cw1200_sdio_suspend(struct device *dev)
348560424e9SKalle Valo {
349560424e9SKalle Valo 	int ret;
350560424e9SKalle Valo 	struct sdio_func *func = dev_to_sdio_func(dev);
351560424e9SKalle Valo 	struct hwbus_priv *self = sdio_get_drvdata(func);
352560424e9SKalle Valo 
353560424e9SKalle Valo 	if (!cw1200_can_suspend(self->core))
354560424e9SKalle Valo 		return -EAGAIN;
355560424e9SKalle Valo 
356560424e9SKalle Valo 	/* Notify SDIO that CW1200 will remain powered during suspend */
357560424e9SKalle Valo 	ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
358560424e9SKalle Valo 	if (ret)
359560424e9SKalle Valo 		pr_err("Error setting SDIO pm flags: %i\n", ret);
360560424e9SKalle Valo 
361560424e9SKalle Valo 	return ret;
362560424e9SKalle Valo }
363560424e9SKalle Valo 
cw1200_sdio_resume(struct device * dev)364560424e9SKalle Valo static int cw1200_sdio_resume(struct device *dev)
365560424e9SKalle Valo {
366560424e9SKalle Valo 	return 0;
367560424e9SKalle Valo }
368560424e9SKalle Valo 
369560424e9SKalle Valo static const struct dev_pm_ops cw1200_pm_ops = {
370560424e9SKalle Valo 	.suspend = cw1200_sdio_suspend,
371560424e9SKalle Valo 	.resume = cw1200_sdio_resume,
372560424e9SKalle Valo };
373560424e9SKalle Valo #endif
374560424e9SKalle Valo 
375560424e9SKalle Valo static struct sdio_driver sdio_driver = {
376560424e9SKalle Valo 	.name		= "cw1200_wlan_sdio",
377560424e9SKalle Valo 	.id_table	= cw1200_sdio_ids,
378560424e9SKalle Valo 	.probe		= cw1200_sdio_probe,
379560424e9SKalle Valo 	.remove		= cw1200_sdio_disconnect,
380560424e9SKalle Valo #ifdef CONFIG_PM
381560424e9SKalle Valo 	.drv = {
382560424e9SKalle Valo 		.pm = &cw1200_pm_ops,
383560424e9SKalle Valo 	}
384560424e9SKalle Valo #endif
385560424e9SKalle Valo };
386560424e9SKalle Valo 
387560424e9SKalle Valo /* Init Module function -> Called by insmod */
cw1200_sdio_init(void)388560424e9SKalle Valo static int __init cw1200_sdio_init(void)
389560424e9SKalle Valo {
390560424e9SKalle Valo 	const struct cw1200_platform_data_sdio *pdata;
391560424e9SKalle Valo 	int ret;
392560424e9SKalle Valo 
393560424e9SKalle Valo 	/* FIXME -- this won't support multiple devices */
394560424e9SKalle Valo 	pdata = global_plat_data;
395560424e9SKalle Valo 
396560424e9SKalle Valo 	if (cw1200_sdio_on(pdata)) {
397560424e9SKalle Valo 		ret = -1;
398560424e9SKalle Valo 		goto err;
399560424e9SKalle Valo 	}
400560424e9SKalle Valo 
401560424e9SKalle Valo 	ret = sdio_register_driver(&sdio_driver);
402560424e9SKalle Valo 	if (ret)
403560424e9SKalle Valo 		goto err;
404560424e9SKalle Valo 
405560424e9SKalle Valo 	return 0;
406560424e9SKalle Valo 
407560424e9SKalle Valo err:
408560424e9SKalle Valo 	cw1200_sdio_off(pdata);
409560424e9SKalle Valo 	return ret;
410560424e9SKalle Valo }
411560424e9SKalle Valo 
412560424e9SKalle Valo /* Called at Driver Unloading */
cw1200_sdio_exit(void)413560424e9SKalle Valo static void __exit cw1200_sdio_exit(void)
414560424e9SKalle Valo {
415560424e9SKalle Valo 	const struct cw1200_platform_data_sdio *pdata;
416560424e9SKalle Valo 
417560424e9SKalle Valo 	/* FIXME -- this won't support multiple devices */
418560424e9SKalle Valo 	pdata = global_plat_data;
419560424e9SKalle Valo 	sdio_unregister_driver(&sdio_driver);
420560424e9SKalle Valo 	cw1200_sdio_off(pdata);
421560424e9SKalle Valo }
422560424e9SKalle Valo 
423560424e9SKalle Valo 
424560424e9SKalle Valo module_init(cw1200_sdio_init);
425560424e9SKalle Valo module_exit(cw1200_sdio_exit);
426