]> Git Repo - linux.git/blame - drivers/net/wireless/ti/wlcore/sdio.c
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[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 <[email protected]>
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>
00cbb3c5 34#include <linux/pm_runtime.h>
df472894 35#include <linux/printk.h>
5ea5c518
EP
36#include <linux/of.h>
37#include <linux/of_irq.h>
5129dffe 38
c31be25a 39#include "wlcore.h"
5129dffe 40#include "wl12xx_80211.h"
00d20100 41#include "io.h"
5129dffe 42
5129dffe
TP
43#ifndef SDIO_VENDOR_ID_TI
44#define SDIO_VENDOR_ID_TI 0x0097
45#endif
46
47#ifndef SDIO_DEVICE_ID_TI_WL1271
48#define SDIO_DEVICE_ID_TI_WL1271 0x4076
49#endif
50
df472894
LC
51static bool dump = false;
52
fbe936bc
FB
53struct wl12xx_sdio_glue {
54 struct device *dev;
025aef8f 55 struct platform_device *core;
fbe936bc
FB
56};
57
b74324d1 58static const struct sdio_device_id wl1271_devices[] = {
5129dffe
TP
59 { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
60 {}
61};
62MODULE_DEVICE_TABLE(sdio, wl1271_devices);
63
a390e85c
FB
64static void wl1271_sdio_set_block_size(struct device *child,
65 unsigned int blksz)
a81159ed 66{
a390e85c
FB
67 struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
68 struct sdio_func *func = dev_to_sdio_func(glue->dev);
5129dffe 69
a390e85c
FB
70 sdio_claim_host(func);
71 sdio_set_block_size(func, blksz);
72 sdio_release_host(func);
5129dffe
TP
73}
74
f1a26e63
IY
75static int __must_check wl12xx_sdio_raw_read(struct device *child, int addr,
76 void *buf, size_t len, bool fixed)
5129dffe
TP
77{
78 int ret;
a390e85c 79 struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
fbe936bc 80 struct sdio_func *func = dev_to_sdio_func(glue->dev);
5129dffe 81
b4748306
EP
82 sdio_claim_host(func);
83
00782136 84 if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) {
5129dffe 85 ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
3c4d3868
LC
86 dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n",
87 addr, ((u8 *)buf)[0]);
5129dffe
TP
88 } else {
89 if (fixed)
90 ret = sdio_readsb(func, buf, addr, len);
91 else
92 ret = sdio_memcpy_fromio(func, buf, addr, len);
93
3c4d3868
LC
94 dev_dbg(child->parent, "sdio read 53 addr 0x%x, %zu bytes\n",
95 addr, len);
5129dffe
TP
96 }
97
b4748306
EP
98 sdio_release_host(func);
99
02eb1d9d 100 if (WARN_ON(ret))
3c4d3868 101 dev_err(child->parent, "sdio read failed (%d)\n", ret);
02eb1d9d 102
64ad0860
GM
103 if (unlikely(dump)) {
104 printk(KERN_DEBUG "wlcore_sdio: READ from 0x%04x\n", addr);
105 print_hex_dump(KERN_DEBUG, "wlcore_sdio: READ ",
106 DUMP_PREFIX_OFFSET, 16, 1,
107 buf, len, false);
108 }
109
02eb1d9d 110 return ret;
5129dffe
TP
111}
112
f1a26e63
IY
113static int __must_check wl12xx_sdio_raw_write(struct device *child, int addr,
114 void *buf, size_t len, bool fixed)
5129dffe
TP
115{
116 int ret;
a390e85c 117 struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
fbe936bc 118 struct sdio_func *func = dev_to_sdio_func(glue->dev);
5129dffe 119
b4748306
EP
120 sdio_claim_host(func);
121
df472894
LC
122 if (unlikely(dump)) {
123 printk(KERN_DEBUG "wlcore_sdio: WRITE to 0x%04x\n", addr);
124 print_hex_dump(KERN_DEBUG, "wlcore_sdio: WRITE ",
125 DUMP_PREFIX_OFFSET, 16, 1,
126 buf, len, false);
127 }
128
00782136 129 if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) {
5129dffe 130 sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
3c4d3868
LC
131 dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n",
132 addr, ((u8 *)buf)[0]);
5129dffe 133 } else {
3c4d3868
LC
134 dev_dbg(child->parent, "sdio write 53 addr 0x%x, %zu bytes\n",
135 addr, len);
5129dffe
TP
136
137 if (fixed)
138 ret = sdio_writesb(func, addr, buf, len);
139 else
140 ret = sdio_memcpy_toio(func, addr, buf, len);
141 }
49063a0d 142
b4748306
EP
143 sdio_release_host(func);
144
02eb1d9d 145 if (WARN_ON(ret))
3c4d3868 146 dev_err(child->parent, "sdio write failed (%d)\n", ret);
02eb1d9d
IY
147
148 return ret;
49063a0d
OBC
149}
150
a390e85c 151static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
49063a0d 152{
00cbb3c5 153 int ret;
fbe936bc 154 struct sdio_func *func = dev_to_sdio_func(glue->dev);
645865fc
IY
155 struct mmc_card *card = func->card;
156
157 ret = pm_runtime_get_sync(&card->dev);
60f36637
ER
158 if (ret < 0) {
159 pm_runtime_put_noidle(&card->dev);
160 dev_err(glue->dev, "%s: failed to get_sync(%d)\n",
161 __func__, ret);
728a9dc6
TL
162
163 return ret;
86046da4 164 }
5129dffe 165
49063a0d
OBC
166 sdio_claim_host(func);
167 sdio_enable_func(func);
b4748306 168 sdio_release_host(func);
2cc78ff7 169
728a9dc6 170 return 0;
49063a0d
OBC
171}
172
a390e85c 173static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
49063a0d 174{
fbe936bc 175 struct sdio_func *func = dev_to_sdio_func(glue->dev);
645865fc 176 struct mmc_card *card = func->card;
728a9dc6 177 int error;
49063a0d 178
b4748306 179 sdio_claim_host(func);
49063a0d
OBC
180 sdio_disable_func(func);
181 sdio_release_host(func);
2cc78ff7 182
645865fc 183 /* Let runtime PM know the card is powered off */
728a9dc6
TL
184 error = pm_runtime_put(&card->dev);
185 if (error < 0 && error != -EBUSY) {
186 dev_err(&card->dev, "%s failed: %i\n", __func__, error);
187
188 return error;
189 }
190
191 return 0;
5129dffe
TP
192}
193
a390e85c 194static int wl12xx_sdio_set_power(struct device *child, bool enable)
becd551c 195{
a390e85c
FB
196 struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
197
49063a0d 198 if (enable)
a390e85c 199 return wl12xx_sdio_power_on(glue);
49063a0d 200 else
a390e85c 201 return wl12xx_sdio_power_off(glue);
becd551c
TP
202}
203
5129dffe 204static struct wl1271_if_operations sdio_ops = {
a390e85c
FB
205 .read = wl12xx_sdio_raw_read,
206 .write = wl12xx_sdio_raw_write,
207 .power = wl12xx_sdio_set_power,
a81159ed 208 .set_block_size = wl1271_sdio_set_block_size,
5129dffe
TP
209};
210
5ea5c518 211#ifdef CONFIG_OF
d776fc86
TL
212
213static const struct wilink_family_data wl127x_data = {
214 .name = "wl127x",
215 .nvs_name = "ti-connectivity/wl127x-nvs.bin",
216};
217
218static const struct wilink_family_data wl128x_data = {
219 .name = "wl128x",
220 .nvs_name = "ti-connectivity/wl128x-nvs.bin",
221};
222
223static const struct wilink_family_data wl18xx_data = {
224 .name = "wl18xx",
225 .cfg_name = "ti-connectivity/wl18xx-conf.bin",
d382b9c0 226 .nvs_name = "ti-connectivity/wl1271-nvs.bin",
d776fc86
TL
227};
228
5ea5c518 229static const struct of_device_id wlcore_sdio_of_match_table[] = {
d776fc86
TL
230 { .compatible = "ti,wl1271", .data = &wl127x_data },
231 { .compatible = "ti,wl1273", .data = &wl127x_data },
232 { .compatible = "ti,wl1281", .data = &wl128x_data },
233 { .compatible = "ti,wl1283", .data = &wl128x_data },
078b30da 234 { .compatible = "ti,wl1285", .data = &wl128x_data },
d776fc86
TL
235 { .compatible = "ti,wl1801", .data = &wl18xx_data },
236 { .compatible = "ti,wl1805", .data = &wl18xx_data },
237 { .compatible = "ti,wl1807", .data = &wl18xx_data },
238 { .compatible = "ti,wl1831", .data = &wl18xx_data },
239 { .compatible = "ti,wl1835", .data = &wl18xx_data },
240 { .compatible = "ti,wl1837", .data = &wl18xx_data },
5ea5c518
EP
241 { }
242};
243
3c83dd57 244static int wlcore_probe_of(struct device *dev, int *irq, int *wakeirq,
83c3a7d4 245 struct wlcore_platdev_data *pdev_data)
5ea5c518
EP
246{
247 struct device_node *np = dev->of_node;
d776fc86 248 const struct of_device_id *of_id;
5ea5c518 249
d776fc86
TL
250 of_id = of_match_node(wlcore_sdio_of_match_table, np);
251 if (!of_id)
252 return -ENODEV;
253
254 pdev_data->family = of_id->data;
5ea5c518 255
83c3a7d4
EP
256 *irq = irq_of_parse_and_map(np, 0);
257 if (!*irq) {
5ea5c518 258 dev_err(dev, "No irq in platform data\n");
83c3a7d4 259 return -EINVAL;
5ea5c518
EP
260 }
261
3c83dd57
TL
262 *wakeirq = irq_of_parse_and_map(np, 1);
263
5ea5c518
EP
264 /* optional clock frequency params */
265 of_property_read_u32(np, "ref-clock-frequency",
83c3a7d4 266 &pdev_data->ref_clock_freq);
5ea5c518 267 of_property_read_u32(np, "tcxo-clock-frequency",
83c3a7d4 268 &pdev_data->tcxo_clock_freq);
5ea5c518 269
83c3a7d4 270 return 0;
5ea5c518
EP
271}
272#else
3c83dd57 273static int wlcore_probe_of(struct device *dev, int *irq, int *wakeirq,
83c3a7d4 274 struct wlcore_platdev_data *pdev_data)
5ea5c518 275{
83c3a7d4 276 return -ENODATA;
5ea5c518
EP
277}
278#endif
279
b74324d1 280static int wl1271_probe(struct sdio_func *func,
5129dffe
TP
281 const struct sdio_device_id *id)
282{
d776fc86 283 struct wlcore_platdev_data *pdev_data;
fbe936bc 284 struct wl12xx_sdio_glue *glue;
3c83dd57 285 struct resource res[2];
f795ea8b 286 mmc_pm_flag_t mmcflags;
fbe936bc 287 int ret = -ENOMEM;
b630806d 288 int irq, wakeirq, num_irqs;
197c6283 289 const char *chip_family;
5129dffe
TP
290
291 /* We are only able to handle the wlan function */
292 if (func->num != 0x02)
293 return -ENODEV;
294
d776fc86
TL
295 pdev_data = devm_kzalloc(&func->dev, sizeof(*pdev_data), GFP_KERNEL);
296 if (!pdev_data)
297 return -ENOMEM;
afb43e6d 298
d776fc86
TL
299 pdev_data->if_ops = &sdio_ops;
300
301 glue = devm_kzalloc(&func->dev, sizeof(*glue), GFP_KERNEL);
302 if (!glue)
303 return -ENOMEM;
fbe936bc 304
fbe936bc 305 glue->dev = &func->dev;
5129dffe 306
5129dffe
TP
307 /* Grab access to FN0 for ELP reg. */
308 func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
309
1d732e8c
AN
310 /* Use block mode for transferring over one block size of data */
311 func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
312
3c83dd57 313 ret = wlcore_probe_of(&func->dev, &irq, &wakeirq, pdev_data);
cf7d5a80 314 if (ret)
d776fc86 315 goto out;
5129dffe 316
a390e85c
FB
317 /* if sdio can keep power while host is suspended, enable wow */
318 mmcflags = sdio_get_host_pm_caps(func);
3c4d3868 319 dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags);
2c0f2463 320
a390e85c 321 if (mmcflags & MMC_PM_KEEP_POWER)
d776fc86 322 pdev_data->pwr_in_suspend = true;
f795ea8b 323
fbe936bc 324 sdio_set_drvdata(func, glue);
49d7f6d8 325
00cbb3c5
OBC
326 /* Tell PM core that we don't need the card to be powered now */
327 pm_runtime_put_noidle(&func->dev);
328
197c6283
LC
329 /*
330 * Due to a hardware bug, we can't differentiate wl18xx from
331 * wl12xx, because both report the same device ID. The only
332 * way to differentiate is by checking the SDIO revision,
333 * which is 3.00 on the wl18xx chips.
334 */
335 if (func->card->cccr.sdio_vsn == SDIO_SDIO_REV_3_00)
336 chip_family = "wl18xx";
337 else
338 chip_family = "wl12xx";
339
06ab4058 340 glue->core = platform_device_alloc(chip_family, PLATFORM_DEVID_AUTO);
025aef8f 341 if (!glue->core) {
3c4d3868 342 dev_err(glue->dev, "can't allocate platform_device");
025aef8f 343 ret = -ENOMEM;
d776fc86 344 goto out;
025aef8f
FB
345 }
346
347 glue->core->dev.parent = &func->dev;
348
349 memset(res, 0x00, sizeof(res));
350
83c3a7d4
EP
351 res[0].start = irq;
352 res[0].flags = IORESOURCE_IRQ |
353 irqd_get_trigger_type(irq_get_irq_data(irq));
025aef8f
FB
354 res[0].name = "irq";
355
3c83dd57 356
b630806d
JS
357 if (wakeirq > 0) {
358 res[1].start = wakeirq;
359 res[1].flags = IORESOURCE_IRQ |
360 irqd_get_trigger_type(irq_get_irq_data(wakeirq));
361 res[1].name = "wakeirq";
362 num_irqs = 2;
363 } else {
364 num_irqs = 1;
365 }
366 ret = platform_device_add_resources(glue->core, res, num_irqs);
025aef8f 367 if (ret) {
3c4d3868 368 dev_err(glue->dev, "can't add resources\n");
025aef8f
FB
369 goto out_dev_put;
370 }
371
d776fc86
TL
372 ret = platform_device_add_data(glue->core, pdev_data,
373 sizeof(*pdev_data));
025aef8f 374 if (ret) {
3c4d3868 375 dev_err(glue->dev, "can't add platform data\n");
025aef8f
FB
376 goto out_dev_put;
377 }
378
379 ret = platform_device_add(glue->core);
380 if (ret) {
3c4d3868 381 dev_err(glue->dev, "can't add platform device\n");
025aef8f
FB
382 goto out_dev_put;
383 }
5129dffe
TP
384 return 0;
385
025aef8f
FB
386out_dev_put:
387 platform_device_put(glue->core);
388
fbe936bc 389out:
5129dffe
TP
390 return ret;
391}
392
b74324d1 393static void wl1271_remove(struct sdio_func *func)
5129dffe 394{
fbe936bc 395 struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
5129dffe 396
00cbb3c5
OBC
397 /* Undo decrement done above in wl1271_probe */
398 pm_runtime_get_noresume(&func->dev);
399
200e9326 400 platform_device_unregister(glue->core);
5129dffe
TP
401}
402
f634a4e7 403#ifdef CONFIG_PM
674f3058
OBC
404static int wl1271_suspend(struct device *dev)
405{
406 /* Tell MMC/SDIO core it's OK to power down the card
407 * (if it isn't already), but not to remove it completely */
039bdb14 408 struct sdio_func *func = dev_to_sdio_func(dev);
b6932894
ES
409 struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
410 struct wl1271 *wl = platform_get_drvdata(glue->core);
039bdb14
EP
411 mmc_pm_flag_t sdio_flags;
412 int ret = 0;
413
6e91d483
ER
414 if (!wl) {
415 dev_err(dev, "no wilink module was probed\n");
416 goto out;
417 }
418
3c4d3868
LC
419 dev_dbg(dev, "wl1271 suspend. wow_enabled: %d\n",
420 wl->wow_enabled);
039bdb14
EP
421
422 /* check whether sdio should keep power */
423 if (wl->wow_enabled) {
424 sdio_flags = sdio_get_host_pm_caps(func);
425
426 if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
3c4d3868
LC
427 dev_err(dev, "can't keep power while host "
428 "is suspended\n");
039bdb14
EP
429 ret = -EINVAL;
430 goto out;
431 }
432
433 /* keep power while host suspended */
434 ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
435 if (ret) {
3c4d3868 436 dev_err(dev, "error while trying to keep power\n");
039bdb14
EP
437 goto out;
438 }
439 }
440out:
441 return ret;
674f3058
OBC
442}
443
444static int wl1271_resume(struct device *dev)
445{
3c4d3868 446 dev_dbg(dev, "wl1271 resume\n");
f44e5868 447
674f3058
OBC
448 return 0;
449}
450
451static const struct dev_pm_ops wl1271_sdio_pm_ops = {
452 .suspend = wl1271_suspend,
453 .resume = wl1271_resume,
454};
f634a4e7 455#endif
674f3058 456
5129dffe 457static struct sdio_driver wl1271_sdio_driver = {
f4b5d8d8 458 .name = "wl1271_sdio",
5129dffe
TP
459 .id_table = wl1271_devices,
460 .probe = wl1271_probe,
b74324d1 461 .remove = wl1271_remove,
f634a4e7 462#ifdef CONFIG_PM
674f3058
OBC
463 .drv = {
464 .pm = &wl1271_sdio_pm_ops,
465 },
f634a4e7 466#endif
5129dffe
TP
467};
468
469static int __init wl1271_init(void)
470{
6bdaf796 471 return sdio_register_driver(&wl1271_sdio_driver);
5129dffe
TP
472}
473
474static void __exit wl1271_exit(void)
475{
476 sdio_unregister_driver(&wl1271_sdio_driver);
5129dffe
TP
477}
478
479module_init(wl1271_init);
480module_exit(wl1271_exit);
481
2ef00c53 482module_param(dump, bool, 0600);
df472894
LC
483MODULE_PARM_DESC(dump, "Enable sdio read/write dumps.");
484
5129dffe 485MODULE_LICENSE("GPL");
5245e3a9 486MODULE_AUTHOR("Luciano Coelho <[email protected]>");
5129dffe 487MODULE_AUTHOR("Juuso Oikarinen <[email protected]>");
This page took 0.96877 seconds and 4 git commands to generate.