wl18xx: use %zu for size_t arguments in printk calls
[deliverable/linux.git] / drivers / net / wireless / ti / wlcore / sdio.c
CommitLineData
5129dffe
TP
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2009-2010 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/irq.h>
25#include <linux/module.h>
5129dffe 26#include <linux/vmalloc.h>
025aef8f 27#include <linux/platform_device.h>
197c6283 28#include <linux/mmc/sdio.h>
5129dffe
TP
29#include <linux/mmc/sdio_func.h>
30#include <linux/mmc/sdio_ids.h>
31#include <linux/mmc/card.h>
11251e7e 32#include <linux/mmc/host.h>
19b87173 33#include <linux/gpio.h>
09cecc34 34#include <linux/wl12xx.h>
00cbb3c5 35#include <linux/pm_runtime.h>
df472894 36#include <linux/printk.h>
5129dffe 37
c31be25a 38#include "wlcore.h"
5129dffe 39#include "wl12xx_80211.h"
00d20100 40#include "io.h"
5129dffe 41
5129dffe
TP
42#ifndef SDIO_VENDOR_ID_TI
43#define SDIO_VENDOR_ID_TI 0x0097
44#endif
45
46#ifndef SDIO_DEVICE_ID_TI_WL1271
47#define SDIO_DEVICE_ID_TI_WL1271 0x4076
48#endif
49
df472894
LC
50static bool dump = false;
51
fbe936bc
FB
52struct wl12xx_sdio_glue {
53 struct device *dev;
025aef8f 54 struct platform_device *core;
fbe936bc
FB
55};
56
33dd74c7 57static const struct sdio_device_id wl1271_devices[] __devinitconst = {
5129dffe
TP
58 { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
59 {}
60};
61MODULE_DEVICE_TABLE(sdio, wl1271_devices);
62
a390e85c
FB
63static void wl1271_sdio_set_block_size(struct device *child,
64 unsigned int blksz)
a81159ed 65{
a390e85c
FB
66 struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
67 struct sdio_func *func = dev_to_sdio_func(glue->dev);
5129dffe 68
a390e85c
FB
69 sdio_claim_host(func);
70 sdio_set_block_size(func, blksz);
71 sdio_release_host(func);
5129dffe
TP
72}
73
a390e85c 74static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
a3b8ea75 75 size_t len, bool fixed)
5129dffe
TP
76{
77 int ret;
a390e85c 78 struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
fbe936bc 79 struct sdio_func *func = dev_to_sdio_func(glue->dev);
5129dffe 80
b4748306
EP
81 sdio_claim_host(func);
82
df472894
LC
83 if (unlikely(dump)) {
84 printk(KERN_DEBUG "wlcore_sdio: READ from 0x%04x\n", addr);
85 print_hex_dump(KERN_DEBUG, "wlcore_sdio: READ ",
86 DUMP_PREFIX_OFFSET, 16, 1,
87 buf, len, false);
88 }
89
00782136 90 if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) {
5129dffe 91 ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
3c4d3868
LC
92 dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n",
93 addr, ((u8 *)buf)[0]);
5129dffe
TP
94 } else {
95 if (fixed)
96 ret = sdio_readsb(func, buf, addr, len);
97 else
98 ret = sdio_memcpy_fromio(func, buf, addr, len);
99
3c4d3868
LC
100 dev_dbg(child->parent, "sdio read 53 addr 0x%x, %zu bytes\n",
101 addr, len);
5129dffe
TP
102 }
103
b4748306
EP
104 sdio_release_host(func);
105
5129dffe 106 if (ret)
3c4d3868 107 dev_err(child->parent, "sdio read failed (%d)\n", ret);
5129dffe
TP
108}
109
a390e85c 110static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
a3b8ea75 111 size_t len, bool fixed)
5129dffe
TP
112{
113 int ret;
a390e85c 114 struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
fbe936bc 115 struct sdio_func *func = dev_to_sdio_func(glue->dev);
5129dffe 116
b4748306
EP
117 sdio_claim_host(func);
118
df472894
LC
119 if (unlikely(dump)) {
120 printk(KERN_DEBUG "wlcore_sdio: WRITE to 0x%04x\n", addr);
121 print_hex_dump(KERN_DEBUG, "wlcore_sdio: WRITE ",
122 DUMP_PREFIX_OFFSET, 16, 1,
123 buf, len, false);
124 }
125
00782136 126 if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) {
5129dffe 127 sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
3c4d3868
LC
128 dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n",
129 addr, ((u8 *)buf)[0]);
5129dffe 130 } else {
3c4d3868
LC
131 dev_dbg(child->parent, "sdio write 53 addr 0x%x, %zu bytes\n",
132 addr, len);
5129dffe
TP
133
134 if (fixed)
135 ret = sdio_writesb(func, addr, buf, len);
136 else
137 ret = sdio_memcpy_toio(func, addr, buf, len);
138 }
49063a0d 139
b4748306
EP
140 sdio_release_host(func);
141
5129dffe 142 if (ret)
3c4d3868 143 dev_err(child->parent, "sdio write failed (%d)\n", ret);
49063a0d
OBC
144}
145
a390e85c 146static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
49063a0d 147{
00cbb3c5 148 int ret;
fbe936bc 149 struct sdio_func *func = dev_to_sdio_func(glue->dev);
00cbb3c5 150
86046da4
OBC
151 /* If enabled, tell runtime PM not to power off the card */
152 if (pm_runtime_enabled(&func->dev)) {
153 ret = pm_runtime_get_sync(&func->dev);
a15f1c45 154 if (ret < 0)
86046da4 155 goto out;
b5d6e5f6
OBC
156 } else {
157 /* Runtime PM is disabled: power up the card manually */
158 ret = mmc_power_restore_host(func->card->host);
159 if (ret < 0)
160 goto out;
86046da4 161 }
5129dffe 162
49063a0d
OBC
163 sdio_claim_host(func);
164 sdio_enable_func(func);
b4748306 165 sdio_release_host(func);
2cc78ff7 166
00cbb3c5
OBC
167out:
168 return ret;
49063a0d
OBC
169}
170
a390e85c 171static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
49063a0d 172{
11251e7e 173 int ret;
fbe936bc 174 struct sdio_func *func = dev_to_sdio_func(glue->dev);
49063a0d 175
b4748306 176 sdio_claim_host(func);
49063a0d
OBC
177 sdio_disable_func(func);
178 sdio_release_host(func);
2cc78ff7 179
b5d6e5f6 180 /* Power off the card manually, even if runtime PM is enabled. */
11251e7e
IY
181 ret = mmc_power_save_host(func->card->host);
182 if (ret < 0)
183 return ret;
184
86046da4
OBC
185 /* If enabled, let runtime PM know the card is powered off */
186 if (pm_runtime_enabled(&func->dev))
187 ret = pm_runtime_put_sync(&func->dev);
188
189 return ret;
5129dffe
TP
190}
191
a390e85c 192static int wl12xx_sdio_set_power(struct device *child, bool enable)
becd551c 193{
a390e85c
FB
194 struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
195
49063a0d 196 if (enable)
a390e85c 197 return wl12xx_sdio_power_on(glue);
49063a0d 198 else
a390e85c 199 return wl12xx_sdio_power_off(glue);
becd551c
TP
200}
201
5129dffe 202static struct wl1271_if_operations sdio_ops = {
a390e85c
FB
203 .read = wl12xx_sdio_raw_read,
204 .write = wl12xx_sdio_raw_write,
205 .power = wl12xx_sdio_set_power,
a81159ed 206 .set_block_size = wl1271_sdio_set_block_size,
5129dffe
TP
207};
208
5129dffe
TP
209static int __devinit wl1271_probe(struct sdio_func *func,
210 const struct sdio_device_id *id)
211{
a390e85c 212 struct wl12xx_platform_data *wlan_data;
fbe936bc 213 struct wl12xx_sdio_glue *glue;
025aef8f 214 struct resource res[1];
f795ea8b 215 mmc_pm_flag_t mmcflags;
fbe936bc 216 int ret = -ENOMEM;
197c6283 217 const char *chip_family;
5129dffe
TP
218
219 /* We are only able to handle the wlan function */
220 if (func->num != 0x02)
221 return -ENODEV;
222
fbe936bc
FB
223 glue = kzalloc(sizeof(*glue), GFP_KERNEL);
224 if (!glue) {
3c4d3868 225 dev_err(&func->dev, "can't allocate glue\n");
fbe936bc
FB
226 goto out;
227 }
228
fbe936bc 229 glue->dev = &func->dev;
5129dffe 230
5129dffe
TP
231 /* Grab access to FN0 for ELP reg. */
232 func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
233
1d732e8c
AN
234 /* Use block mode for transferring over one block size of data */
235 func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
236
09cecc34
OBC
237 wlan_data = wl12xx_get_platform_data();
238 if (IS_ERR(wlan_data)) {
239 ret = PTR_ERR(wlan_data);
3c4d3868 240 dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
a390e85c 241 goto out_free_glue;
5129dffe
TP
242 }
243
a390e85c
FB
244 /* if sdio can keep power while host is suspended, enable wow */
245 mmcflags = sdio_get_host_pm_caps(func);
3c4d3868 246 dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags);
2c0f2463 247
a390e85c
FB
248 if (mmcflags & MMC_PM_KEEP_POWER)
249 wlan_data->pwr_in_suspend = true;
f795ea8b 250
a390e85c 251 wlan_data->ops = &sdio_ops;
5129dffe 252
fbe936bc 253 sdio_set_drvdata(func, glue);
49d7f6d8 254
00cbb3c5
OBC
255 /* Tell PM core that we don't need the card to be powered now */
256 pm_runtime_put_noidle(&func->dev);
257
197c6283
LC
258 /*
259 * Due to a hardware bug, we can't differentiate wl18xx from
260 * wl12xx, because both report the same device ID. The only
261 * way to differentiate is by checking the SDIO revision,
262 * which is 3.00 on the wl18xx chips.
263 */
264 if (func->card->cccr.sdio_vsn == SDIO_SDIO_REV_3_00)
265 chip_family = "wl18xx";
266 else
267 chip_family = "wl12xx";
268
269 glue->core = platform_device_alloc(chip_family, -1);
025aef8f 270 if (!glue->core) {
3c4d3868 271 dev_err(glue->dev, "can't allocate platform_device");
025aef8f 272 ret = -ENOMEM;
a390e85c 273 goto out_free_glue;
025aef8f
FB
274 }
275
276 glue->core->dev.parent = &func->dev;
277
278 memset(res, 0x00, sizeof(res));
279
280 res[0].start = wlan_data->irq;
281 res[0].flags = IORESOURCE_IRQ;
282 res[0].name = "irq";
283
284 ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res));
285 if (ret) {
3c4d3868 286 dev_err(glue->dev, "can't add resources\n");
025aef8f
FB
287 goto out_dev_put;
288 }
289
290 ret = platform_device_add_data(glue->core, wlan_data,
291 sizeof(*wlan_data));
292 if (ret) {
3c4d3868 293 dev_err(glue->dev, "can't add platform data\n");
025aef8f
FB
294 goto out_dev_put;
295 }
296
297 ret = platform_device_add(glue->core);
298 if (ret) {
3c4d3868 299 dev_err(glue->dev, "can't add platform device\n");
025aef8f
FB
300 goto out_dev_put;
301 }
5129dffe
TP
302 return 0;
303
025aef8f
FB
304out_dev_put:
305 platform_device_put(glue->core);
306
fbe936bc
FB
307out_free_glue:
308 kfree(glue);
a390e85c 309
fbe936bc 310out:
5129dffe
TP
311 return ret;
312}
313
314static void __devexit wl1271_remove(struct sdio_func *func)
315{
fbe936bc 316 struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
5129dffe 317
00cbb3c5
OBC
318 /* Undo decrement done above in wl1271_probe */
319 pm_runtime_get_noresume(&func->dev);
320
025aef8f
FB
321 platform_device_del(glue->core);
322 platform_device_put(glue->core);
fbe936bc 323 kfree(glue);
5129dffe
TP
324}
325
f634a4e7 326#ifdef CONFIG_PM
674f3058
OBC
327static int wl1271_suspend(struct device *dev)
328{
329 /* Tell MMC/SDIO core it's OK to power down the card
330 * (if it isn't already), but not to remove it completely */
039bdb14 331 struct sdio_func *func = dev_to_sdio_func(dev);
b6932894
ES
332 struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
333 struct wl1271 *wl = platform_get_drvdata(glue->core);
039bdb14
EP
334 mmc_pm_flag_t sdio_flags;
335 int ret = 0;
336
3c4d3868
LC
337 dev_dbg(dev, "wl1271 suspend. wow_enabled: %d\n",
338 wl->wow_enabled);
039bdb14
EP
339
340 /* check whether sdio should keep power */
341 if (wl->wow_enabled) {
342 sdio_flags = sdio_get_host_pm_caps(func);
343
344 if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
3c4d3868
LC
345 dev_err(dev, "can't keep power while host "
346 "is suspended\n");
039bdb14
EP
347 ret = -EINVAL;
348 goto out;
349 }
350
351 /* keep power while host suspended */
352 ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
353 if (ret) {
3c4d3868 354 dev_err(dev, "error while trying to keep power\n");
039bdb14
EP
355 goto out;
356 }
357 }
358out:
359 return ret;
674f3058
OBC
360}
361
362static int wl1271_resume(struct device *dev)
363{
3c4d3868 364 dev_dbg(dev, "wl1271 resume\n");
f44e5868 365
674f3058
OBC
366 return 0;
367}
368
369static const struct dev_pm_ops wl1271_sdio_pm_ops = {
370 .suspend = wl1271_suspend,
371 .resume = wl1271_resume,
372};
f634a4e7 373#endif
674f3058 374
5129dffe 375static struct sdio_driver wl1271_sdio_driver = {
f4b5d8d8 376 .name = "wl1271_sdio",
5129dffe
TP
377 .id_table = wl1271_devices,
378 .probe = wl1271_probe,
379 .remove = __devexit_p(wl1271_remove),
f634a4e7 380#ifdef CONFIG_PM
674f3058
OBC
381 .drv = {
382 .pm = &wl1271_sdio_pm_ops,
383 },
f634a4e7 384#endif
5129dffe
TP
385};
386
387static int __init wl1271_init(void)
388{
6bdaf796 389 return sdio_register_driver(&wl1271_sdio_driver);
5129dffe
TP
390}
391
392static void __exit wl1271_exit(void)
393{
394 sdio_unregister_driver(&wl1271_sdio_driver);
5129dffe
TP
395}
396
397module_init(wl1271_init);
398module_exit(wl1271_exit);
399
df472894
LC
400module_param(dump, bool, S_IRUSR | S_IWUSR);
401MODULE_PARM_DESC(dump, "Enable sdio read/write dumps.");
402
5129dffe 403MODULE_LICENSE("GPL");
5245e3a9 404MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
5129dffe 405MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
4549d09c
EP
406MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
407MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
3fcdab70 408MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
4549d09c
EP
409MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
410MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
3fcdab70 411MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
This page took 0.420827 seconds and 5 git commands to generate.