2 * SDIO testing driver for wl12xx
4 * Copyright (C) 2010 Nokia Corporation
6 * Contact: Roger Quadros <roger.quadros@nokia.com>
8 * wl12xx read/write routines taken from the main module
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * version 2 as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 #include <linux/irq.h>
27 #include <linux/module.h>
28 #include <linux/crc7.h>
29 #include <linux/vmalloc.h>
30 #include <linux/mmc/sdio_func.h>
31 #include <linux/mmc/sdio_ids.h>
32 #include <linux/mmc/card.h>
33 #include <linux/gpio.h>
34 #include <linux/wl12xx.h>
35 #include <linux/kthread.h>
36 #include <linux/firmware.h>
37 #include <linux/pm_runtime.h>
43 #ifndef SDIO_VENDOR_ID_TI
44 #define SDIO_VENDOR_ID_TI 0x0097
47 #ifndef SDIO_DEVICE_ID_TI_WL1271
48 #define SDIO_DEVICE_ID_TI_WL1271 0x4076
53 module_param(rx
, bool, S_IRUGO
| S_IWUSR
);
54 MODULE_PARM_DESC(rx
, "Perform rx test. Default (0). "
55 "This test continuously reads data from the SDIO device.\n");
57 module_param(tx
, bool, S_IRUGO
| S_IWUSR
);
58 MODULE_PARM_DESC(tx
, "Perform tx test. Default (0). "
59 "This test continuously writes data to the SDIO device.\n");
63 struct task_struct
*test_task
;
66 static const struct sdio_device_id wl1271_devices
[] = {
67 { SDIO_DEVICE(SDIO_VENDOR_ID_TI
, SDIO_DEVICE_ID_TI_WL1271
) },
71 static inline struct sdio_func
*wl_to_func(struct wl1271
*wl
)
76 static struct device
*wl1271_sdio_wl_to_dev(struct wl1271
*wl
)
78 return &(wl_to_func(wl
)->dev
);
81 static void wl1271_sdio_raw_read(struct wl1271
*wl
, int addr
, void *buf
,
82 size_t len
, bool fixed
)
85 struct sdio_func
*func
= wl_to_func(wl
);
87 if (unlikely(addr
== HW_ACCESS_ELP_CTRL_REG_ADDR
)) {
88 ((u8
*)buf
)[0] = sdio_f0_readb(func
, addr
, &ret
);
89 wl1271_debug(DEBUG_SDIO
, "sdio read 52 addr 0x%x, byte 0x%02x",
90 addr
, ((u8
*)buf
)[0]);
93 ret
= sdio_readsb(func
, buf
, addr
, len
);
95 ret
= sdio_memcpy_fromio(func
, buf
, addr
, len
);
97 wl1271_debug(DEBUG_SDIO
, "sdio read 53 addr 0x%x, %zu bytes",
99 wl1271_dump_ascii(DEBUG_SDIO
, "data: ", buf
, len
);
103 wl1271_error("sdio read failed (%d)", ret
);
106 static void wl1271_sdio_raw_write(struct wl1271
*wl
, int addr
, void *buf
,
107 size_t len
, bool fixed
)
110 struct sdio_func
*func
= wl_to_func(wl
);
112 if (unlikely(addr
== HW_ACCESS_ELP_CTRL_REG_ADDR
)) {
113 sdio_f0_writeb(func
, ((u8
*)buf
)[0], addr
, &ret
);
114 wl1271_debug(DEBUG_SDIO
, "sdio write 52 addr 0x%x, byte 0x%02x",
115 addr
, ((u8
*)buf
)[0]);
117 wl1271_debug(DEBUG_SDIO
, "sdio write 53 addr 0x%x, %zu bytes",
119 wl1271_dump_ascii(DEBUG_SDIO
, "data: ", buf
, len
);
122 ret
= sdio_writesb(func
, addr
, buf
, len
);
124 ret
= sdio_memcpy_toio(func
, addr
, buf
, len
);
127 wl1271_error("sdio write failed (%d)", ret
);
131 static int wl1271_sdio_set_power(struct wl1271
*wl
, bool enable
)
133 struct sdio_func
*func
= wl_to_func(wl
);
136 /* Let the SDIO stack handle wlan_enable control, so we
137 * keep host claimed while wlan is in use to keep wl1271
141 /* Power up the card */
142 ret
= pm_runtime_get_sync(&func
->dev
);
145 sdio_claim_host(func
);
146 sdio_enable_func(func
);
147 sdio_release_host(func
);
149 sdio_claim_host(func
);
150 sdio_disable_func(func
);
151 sdio_release_host(func
);
153 /* Power down the card */
154 ret
= pm_runtime_put_sync(&func
->dev
);
161 static void wl1271_sdio_disable_interrupts(struct wl1271
*wl
)
165 static void wl1271_sdio_enable_interrupts(struct wl1271
*wl
)
170 static struct wl1271_if_operations sdio_ops
= {
171 .read
= wl1271_sdio_raw_read
,
172 .write
= wl1271_sdio_raw_write
,
173 .power
= wl1271_sdio_set_power
,
174 .dev
= wl1271_sdio_wl_to_dev
,
175 .enable_irq
= wl1271_sdio_enable_interrupts
,
176 .disable_irq
= wl1271_sdio_disable_interrupts
,
179 static void wl1271_fw_wakeup(struct wl1271
*wl
)
183 elp_reg
= ELPCTRL_WAKE_UP
;
184 wl1271_raw_write32(wl
, HW_ACCESS_ELP_CTRL_REG_ADDR
, elp_reg
);
187 static int wl1271_fetch_firmware(struct wl1271
*wl
)
189 const struct firmware
*fw
;
192 ret
= request_firmware(&fw
, WL1271_FW_NAME
, wl1271_wl_to_dev(wl
));
195 wl1271_error("could not get firmware: %d", ret
);
200 wl1271_error("firmware size is not multiple of 32 bits: %zu",
206 wl
->fw_len
= fw
->size
;
207 wl
->fw
= vmalloc(wl
->fw_len
);
210 wl1271_error("could not allocate memory for the firmware");
215 memcpy(wl
->fw
, fw
->data
, wl
->fw_len
);
220 release_firmware(fw
);
225 static int wl1271_fetch_nvs(struct wl1271
*wl
)
227 const struct firmware
*fw
;
230 ret
= request_firmware(&fw
, WL1271_NVS_NAME
, wl1271_wl_to_dev(wl
));
233 wl1271_error("could not get nvs file: %d", ret
);
237 wl
->nvs
= kmemdup(fw
->data
, sizeof(struct wl1271_nvs_file
), GFP_KERNEL
);
240 wl1271_error("could not allocate memory for the nvs file");
245 wl
->nvs_len
= fw
->size
;
248 release_firmware(fw
);
253 static int wl1271_chip_wakeup(struct wl1271
*wl
)
255 struct wl1271_partition_set partition
;
258 msleep(WL1271_PRE_POWER_ON_SLEEP
);
259 ret
= wl1271_power_on(wl
);
263 msleep(WL1271_POWER_ON_SLEEP
);
265 /* We don't need a real memory partition here, because we only want
266 * to use the registers at this point. */
267 memset(&partition
, 0, sizeof(partition
));
268 partition
.reg
.start
= REGISTERS_BASE
;
269 partition
.reg
.size
= REGISTERS_DOWN_SIZE
;
270 wl1271_set_partition(wl
, &partition
);
272 /* ELP module wake up */
273 wl1271_fw_wakeup(wl
);
275 /* whal_FwCtrl_BootSm() */
277 /* 0. read chip id from CHIP_ID */
278 wl
->chip
.id
= wl1271_read32(wl
, CHIP_ID_B
);
280 /* 1. check if chip id is valid */
282 switch (wl
->chip
.id
) {
283 case CHIP_ID_1271_PG10
:
284 wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
287 case CHIP_ID_1271_PG20
:
288 wl1271_notice("chip id 0x%x (1271 PG20)",
292 wl1271_warning("unsupported chip id: 0x%x", wl
->chip
.id
);
299 static struct wl1271_partition_set part_down
= {
305 .start
= REGISTERS_BASE
,
318 static int tester(void *data
)
320 struct wl1271
*wl
= data
;
321 struct sdio_func
*func
= wl_to_func(wl
);
322 struct device
*pdev
= &func
->dev
;
326 uint8_t *tx_buf
, *rx_buf
;
327 int test_size
= PAGE_SIZE
;
329 struct wl1271_partition_set partition
;
331 /* We assume chip is powered up and firmware fetched */
333 memcpy(&partition
, &part_down
, sizeof(partition
));
334 partition
.mem
.start
= addr
;
335 wl1271_set_partition(wl
, &partition
);
337 tx_buf
= kmalloc(test_size
, GFP_KERNEL
);
338 rx_buf
= kmalloc(test_size
, GFP_KERNEL
);
339 if (!tx_buf
|| !rx_buf
) {
341 "Could not allocate memory. Test will not run.\n");
346 memset(tx_buf
, 0x5a, test_size
);
348 /* write something in data area so we can read it back */
349 wl1271_write(wl
, addr
, tx_buf
, test_size
, false);
351 while (!kthread_should_stop()) {
352 if (rx
&& !rx_started
) {
353 dev_info(pdev
, "starting rx test\n");
355 } else if (!rx
&& rx_started
) {
356 dev_info(pdev
, "stopping rx test\n");
360 if (tx
&& !tx_started
) {
361 dev_info(pdev
, "starting tx test\n");
363 } else if (!tx
&& tx_started
) {
364 dev_info(pdev
, "stopping tx test\n");
369 wl1271_read(wl
, addr
, rx_buf
, test_size
, false);
372 wl1271_write(wl
, addr
, tx_buf
, test_size
, false);
374 if (!rx_started
&& !tx_started
)
384 static int __devinit
wl1271_probe(struct sdio_func
*func
,
385 const struct sdio_device_id
*id
)
387 const struct wl12xx_platform_data
*wlan_data
;
389 struct wl1271_test
*wl_test
;
392 /* wl1271 has 2 sdio functions we handle just the wlan part */
393 if (func
->num
!= 0x02)
396 wl_test
= kzalloc(sizeof(struct wl1271_test
), GFP_KERNEL
);
398 dev_err(&func
->dev
, "Could not allocate memory\n");
405 wl
->if_ops
= &sdio_ops
;
407 /* Grab access to FN0 for ELP reg. */
408 func
->card
->quirks
|= MMC_QUIRK_LENIENT_FN0
;
410 wlan_data
= wl12xx_get_platform_data();
411 if (IS_ERR(wlan_data
)) {
412 ret
= PTR_ERR(wlan_data
);
413 dev_err(&func
->dev
, "missing wlan platform data: %d\n", ret
);
417 wl
->irq
= wlan_data
->irq
;
418 wl
->ref_clock
= wlan_data
->board_ref_clock
;
420 sdio_set_drvdata(func
, wl_test
);
423 /* power up the device */
424 ret
= wl1271_chip_wakeup(wl
);
426 dev_err(&func
->dev
, "could not wake up chip\n");
430 if (wl
->fw
== NULL
) {
431 ret
= wl1271_fetch_firmware(wl
);
433 dev_err(&func
->dev
, "firmware fetch error\n");
439 if (wl
->nvs
== NULL
) {
440 ret
= wl1271_fetch_nvs(wl
);
442 dev_err(&func
->dev
, "NVS fetch error\n");
447 ret
= wl1271_load_firmware(wl
);
449 dev_err(&func
->dev
, "firmware load error: %d\n", ret
);
453 dev_info(&func
->dev
, "initialized\n");
455 /* I/O testing will be done in the tester thread */
457 wl_test
->test_task
= kthread_run(tester
, wl
, "sdio_tester");
458 if (IS_ERR(wl_test
->test_task
)) {
459 dev_err(&func
->dev
, "unable to create kernel thread\n");
460 ret
= PTR_ERR(wl_test
->test_task
);
467 /* power off the chip */
468 wl1271_power_off(wl
);
475 static void __devexit
wl1271_remove(struct sdio_func
*func
)
477 struct wl1271_test
*wl_test
= sdio_get_drvdata(func
);
479 /* stop the I/O test thread */
480 kthread_stop(wl_test
->test_task
);
482 /* power off the chip */
483 wl1271_power_off(&wl_test
->wl
);
485 vfree(wl_test
->wl
.fw
);
486 wl_test
->wl
.fw
= NULL
;
487 kfree(wl_test
->wl
.nvs
);
488 wl_test
->wl
.nvs
= NULL
;
493 static struct sdio_driver wl1271_sdio_driver
= {
494 .name
= "wl12xx_sdio_test",
495 .id_table
= wl1271_devices
,
496 .probe
= wl1271_probe
,
497 .remove
= __devexit_p(wl1271_remove
),
500 static int __init
wl1271_init(void)
504 ret
= sdio_register_driver(&wl1271_sdio_driver
);
506 pr_err("failed to register sdio driver: %d\n", ret
);
510 module_init(wl1271_init
);
512 static void __exit
wl1271_exit(void)
514 sdio_unregister_driver(&wl1271_sdio_driver
);
516 module_exit(wl1271_exit
);
518 MODULE_LICENSE("GPL");
519 MODULE_AUTHOR("Roger Quadros <roger.quadros@nokia.com>");