blob: 1967a1454a4d82044887183077ed2bc15578af6e [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13/*
14 * SDIO-Abstraction-Layer Module.
15 *
16 * To be used with Qualcomm's SDIO-Client connected to this host.
17 */
18#include <sdio_al_private.h>
19
20#include <linux/module.h>
21#include <linux/scatterlist.h>
22#include <linux/workqueue.h>
23#include <linux/wait.h>
24#include <linux/delay.h>
25#include <linux/fs.h>
26#include <linux/slab.h>
27#include <linux/wakelock.h>
28#include <linux/mmc/core.h>
29#include <linux/mmc/card.h>
30#include <linux/mmc/host.h>
31#include <linux/mmc/mmc.h>
32#include <linux/mmc/sdio.h>
33#include <linux/mmc/sdio_func.h>
34#include <linux/mmc/sdio_ids.h>
35#include <linux/gpio.h>
36#include <linux/dma-mapping.h>
37#include <linux/earlysuspend.h>
38#include <linux/debugfs.h>
39#include <linux/uaccess.h>
40#include <linux/syscalls.h>
Krishna Kondaa7af6062011-09-01 18:34:38 -070041#include <linux/time.h>
42#include <linux/spinlock.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043
44#include <mach/dma.h>
45#include <mach/gpio.h>
46#include <mach/subsystem_notif.h>
47
48#include "../../../drivers/mmc/host/msm_sdcc.h"
49
50/**
51 * Func#0 has SDIO standard registers
52 * Func#1 is for Mailbox.
53 * Functions 2..7 are for channels.
54 * Currently only functions 2..5 are active due to SDIO-Client
55 * number of pipes.
56 *
57 */
58#define SDIO_AL_MAX_CHANNELS 6
59
60/** Func 1..5 */
61#define SDIO_AL_MAX_FUNCS (SDIO_AL_MAX_CHANNELS+1)
62#define SDIO_AL_WAKEUP_FUNC 6
63
64/** Number of SDIO-Client pipes */
65#define SDIO_AL_MAX_PIPES 16
66#define SDIO_AL_ACTIVE_PIPES 8
67
68/** CMD53/CMD54 Block size */
Yaniv Gardie5370b82011-07-27 11:46:51 +030069#define SDIO_AL_BLOCK_SIZE 256
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070070
71/** Func#1 hardware Mailbox base address */
72#define HW_MAILBOX_ADDR 0x1000
73
74/** Func#1 peer sdioc software version.
75 * The header is duplicated also to the mailbox of the other
76 * functions. It can be used before other functions are enabled. */
77#define SDIOC_SW_HEADER_ADDR 0x0400
78
79/** Func#2..7 software Mailbox base address at 16K */
80#define SDIOC_SW_MAILBOX_ADDR 0x4000
81
82/** Some Mailbox registers address, written by host for
83 control */
84#define PIPES_THRESHOLD_ADDR 0x01000
85
86#define PIPES_0_7_IRQ_MASK_ADDR 0x01048
87
88#define PIPES_8_15_IRQ_MASK_ADDR 0x0104C
89
90#define FUNC_1_4_MASK_IRQ_ADDR 0x01040
91#define FUNC_5_7_MASK_IRQ_ADDR 0x01044
92#define FUNC_1_4_USER_IRQ_ADDR 0x01050
93#define FUNC_5_7_USER_IRQ_ADDR 0x01054
94
95#define EOT_PIPES_ENABLE 0x00
96
97/** Maximum read/write data available is SDIO-Client limitation */
98#define MAX_DATA_AVAILABLE (16*1024)
99#define INVALID_DATA_AVAILABLE (0x8000)
100
101/** SDIO-Client HW threshold to generate interrupt to the
102 * SDIO-Host on write available bytes.
103 */
104#define DEFAULT_WRITE_THRESHOLD (1024)
105
106/** SDIO-Client HW threshold to generate interrupt to the
107 * SDIO-Host on read available bytes, for streaming (non
108 * packet) rx data.
109 */
110#define DEFAULT_READ_THRESHOLD (1024)
111
Maya Erez8ed0a9a2011-07-19 14:46:53 +0300112/* Extra bytes to ensure getting the rx threshold interrupt on stream channels
113 when restoring the threshold after sleep */
114#define THRESHOLD_CHANGE_EXTRA_BYTES (100)
115
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700116/** SW threshold to trigger reading the mailbox. */
117#define DEFAULT_MIN_WRITE_THRESHOLD (1024)
118#define DEFAULT_MIN_WRITE_THRESHOLD_STREAMING (1600)
119
120#define THRESHOLD_DISABLE_VAL (0xFFFFFFFF)
121
122
123/** Mailbox polling time for packet channels */
124#define DEFAULT_POLL_DELAY_MSEC 10
125/** Mailbox polling time for streaming channels */
126#define DEFAULT_POLL_DELAY_NOPACKET_MSEC 30
127
128/** The SDIO-Client prepares N buffers of size X per Tx pipe.
129 * Even when the transfer fills a partial buffer,
130 * that buffer becomes unusable for the next transfer. */
131#define DEFAULT_PEER_TX_BUF_SIZE (128)
132
133#define ROUND_UP(x, n) (((x + n - 1) / n) * n)
134
135/** Func#2..7 FIFOs are r/w via
136 sdio_readsb() & sdio_writesb(),when inc_addr=0 */
137#define PIPE_RX_FIFO_ADDR 0x00
138#define PIPE_TX_FIFO_ADDR 0x00
139
140/** Inactivity time to go to sleep in mseconds */
141#define INACTIVITY_TIME_MSEC 30
142#define INITIAL_INACTIVITY_TIME_MSEC 5000
143
144/** Context validity check */
145#define SDIO_AL_SIGNATURE 0xAABBCCDD
146
147/* Vendor Specific Command */
148#define SD_IO_RW_EXTENDED_QCOM 54
149
150#define TIME_TO_WAIT_US 500
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300151#define SDIO_CLOSE_FLUSH_TIMEOUT_MSEC (10000)
Maya Erez5795e0d2011-09-12 20:20:06 +0300152#define RX_FLUSH_BUFFER_SIZE (16*1024)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153
154#define SDIO_TEST_POSTFIX "_TEST"
155
Krishna Kondaa7af6062011-09-01 18:34:38 -0700156#define DATA_DEBUG(x, y...) \
157 do { \
158 if (sdio_al->debug.debug_data_on) \
159 pr_info(y); \
160 sdio_al_log(x, y); \
161 } while (0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700162
Krishna Kondaa7af6062011-09-01 18:34:38 -0700163#define LPM_DEBUG(x, y...) \
164 do { \
165 if (sdio_al->debug.debug_lpm_on) \
166 pr_info(y); \
167 sdio_al_log(x, y); \
168 } while (0)
169
170#define sdio_al_loge(x, y...) \
171 do { \
172 pr_err(y); \
173 sdio_al_log(x, y); \
174 } while (0)
175
176#define sdio_al_logi(x, y...) \
177 do { \
178 pr_info(y); \
179 sdio_al_log(x, y); \
180 } while (0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700181
Maya Erez7ad06d82011-10-02 15:47:57 +0200182#define CLOSE_DEBUG(x, y...) \
183 do { \
184 if (sdio_al->debug.debug_close_on) \
185 pr_info(y); \
186 sdio_al_log(x, y); \
187 } while (0)
188
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700189/* The index of the SDIO card used for the sdio_al_dloader */
190#define SDIO_BOOTLOADER_CARD_INDEX 1
191
192
193/* SDIO card state machine */
194enum sdio_al_device_state {
195 CARD_INSERTED,
196 CARD_REMOVED,
197 MODEM_RESTART
198};
199
200struct sdio_al_debug {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700201 u8 debug_lpm_on;
202 u8 debug_data_on;
Maya Erez7ad06d82011-10-02 15:47:57 +0200203 u8 debug_close_on;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204 struct dentry *sdio_al_debug_root;
205 struct dentry *sdio_al_debug_lpm_on;
206 struct dentry *sdio_al_debug_data_on;
Maya Erez7ad06d82011-10-02 15:47:57 +0200207 struct dentry *sdio_al_debug_close_on;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700208 struct dentry *sdio_al_debug_info;
Krishna Kondaa7af6062011-09-01 18:34:38 -0700209 struct dentry *sdio_al_debug_log_buffers[MAX_NUM_OF_SDIO_DEVICES + 1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700210};
211
212/* Polling time for the inactivity timer for devices that doesn't have
213 * a streaming channel
214 */
215#define SDIO_AL_POLL_TIME_NO_STREAMING 30
216
217#define CHAN_TO_FUNC(x) ((x) + 2 - 1)
218
219/**
220 * Mailbox structure.
221 * The Mailbox is located on the SDIO-Client Function#1.
222 * The mailbox size is 128 bytes, which is one block.
223 * The mailbox allows the host ton:
224 * 1. Get the number of available bytes on the pipes.
225 * 2. Enable/Disable SDIO-Client interrupt, related to pipes.
226 * 3. Set the Threshold for generating interrupt.
227 *
228 */
229struct sdio_mailbox {
230 u32 pipe_bytes_threshold[SDIO_AL_MAX_PIPES]; /* Addr 0x1000 */
231
232 /* Mask USER interrupts generated towards host - Addr 0x1040 */
233 u32 mask_irq_func_1:8; /* LSB */
234 u32 mask_irq_func_2:8;
235 u32 mask_irq_func_3:8;
236 u32 mask_irq_func_4:8;
237
238 u32 mask_irq_func_5:8;
239 u32 mask_irq_func_6:8;
240 u32 mask_irq_func_7:8;
241 u32 mask_mutex_irq:8;
242
243 /* Mask PIPE interrupts generated towards host - Addr 0x1048 */
244 u32 mask_eot_pipe_0_7:8;
245 u32 mask_thresh_above_limit_pipe_0_7:8;
246 u32 mask_overflow_pipe_0_7:8;
247 u32 mask_underflow_pipe_0_7:8;
248
249 u32 mask_eot_pipe_8_15:8;
250 u32 mask_thresh_above_limit_pipe_8_15:8;
251 u32 mask_overflow_pipe_8_15:8;
252 u32 mask_underflow_pipe_8_15:8;
253
254 /* Status of User interrupts generated towards host - Addr 0x1050 */
255 u32 user_irq_func_1:8;
256 u32 user_irq_func_2:8;
257 u32 user_irq_func_3:8;
258 u32 user_irq_func_4:8;
259
260 u32 user_irq_func_5:8;
261 u32 user_irq_func_6:8;
262 u32 user_irq_func_7:8;
263 u32 user_mutex_irq:8;
264
265 /* Status of PIPE interrupts generated towards host */
266 /* Note: All sources are cleared once they read. - Addr 0x1058 */
267 u32 eot_pipe_0_7:8;
268 u32 thresh_above_limit_pipe_0_7:8;
269 u32 overflow_pipe_0_7:8;
270 u32 underflow_pipe_0_7:8;
271
272 u32 eot_pipe_8_15:8;
273 u32 thresh_above_limit_pipe_8_15:8;
274 u32 overflow_pipe_8_15:8;
275 u32 underflow_pipe_8_15:8;
276
277 u16 pipe_bytes_avail[SDIO_AL_MAX_PIPES];
278};
279
280/** Track pending Rx Packet size */
281struct rx_packet_size {
282 u32 size; /* in bytes */
283 struct list_head list;
284};
285
286#define PEER_SDIOC_SW_MAILBOX_SIGNATURE 0xFACECAFE
287#define PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE 0x5D107E57
288#define PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE 0xDEADBEEF
289
290/* Allow support in old sdio version */
291#define PEER_SDIOC_OLD_VERSION_MAJOR 0x0002
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700292#define INVALID_SDIO_CHAN 0xFF
293
294/**
295 * Peer SDIO-Client software header.
296 */
297struct peer_sdioc_sw_header {
298 u32 signature;
299 u32 version;
300 u32 max_channels;
301 char channel_names[SDIO_AL_MAX_CHANNELS][PEER_CHANNEL_NAME_SIZE];
302 u32 reserved[23];
303};
304
305struct peer_sdioc_boot_sw_header {
306 u32 signature;
307 u32 version;
308 u32 boot_ch_num;
309 u32 reserved[29]; /* 32 - previous fields */
310};
311
312/**
313 * Peer SDIO-Client software mailbox.
314 */
315struct peer_sdioc_sw_mailbox {
316 struct peer_sdioc_sw_header sw_header;
317 struct peer_sdioc_channel_config ch_config[SDIO_AL_MAX_CHANNELS];
318};
319
Krishna Kondaa7af6062011-09-01 18:34:38 -0700320#define SDIO_AL_DEBUG_LOG_SIZE 3000
321struct sdio_al_local_log {
322 char buffer[SDIO_AL_DEBUG_LOG_SIZE];
323 unsigned int buf_cur_pos;
324 spinlock_t log_lock;
325};
326
327#define SDIO_AL_DEBUG_TMP_LOG_SIZE 250
328static int sdio_al_log(struct sdio_al_local_log *, const char *fmt, ...);
329
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700330/**
331 * SDIO Abstraction Layer driver context.
332 *
333 * @pdata -
334 * @debug -
335 * @devices - an array of the the devices claimed by sdio_al
336 * @unittest_mode - a flag to indicate if sdio_al is in
337 * unittest mode
338 * @bootloader_dev - the device which is used for the
339 * bootloader
340 * @subsys_notif_handle - handle for modem restart
341 * notifications
342 *
343 */
344struct sdio_al {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700345 struct sdio_al_local_log gen_log;
346 struct sdio_al_local_log device_log[MAX_NUM_OF_SDIO_DEVICES];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700347 struct sdio_al_platform_data *pdata;
348 struct sdio_al_debug debug;
349 struct sdio_al_device *devices[MAX_NUM_OF_SDIO_DEVICES];
350 int unittest_mode;
351 struct sdio_al_device *bootloader_dev;
352 void *subsys_notif_handle;
353 int sdioc_major;
354};
355
356struct sdio_al_work {
357 struct work_struct work;
358 struct sdio_al_device *sdio_al_dev;
359};
360
361
362/**
363 * SDIO Abstraction Layer device context.
364 *
365 * @card - card claimed.
366 *
367 * @mailbox - A shadow of the SDIO-Client mailbox.
368 *
369 * @channel - Channels context.
370 *
371 * @workqueue - workqueue to read the mailbox and handle
372 * pending requests. Reading the mailbox should not happen
373 * in interrupt context.
374 *
375 * @work - work to submit to workqueue.
376 *
377 * @is_ready - driver is ready.
378 *
379 * @ask_mbox - Flag to request reading the mailbox,
380 * for different reasons.
381 *
382 * @wake_lock - Lock when can't sleep.
383 *
384 * @lpm_chan - Channel to use for LPM (low power mode)
385 * communication.
386 *
387 * @is_ok_to_sleep - Mark if driver is OK with going to sleep
388 * (no pending transactions).
389 *
390 * @inactivity_time - time allowed to be in inactivity before
391 * going to sleep
392 *
393 * @timer - timer to use for polling the mailbox.
394 *
395 * @poll_delay_msec - timer delay for polling the mailbox.
396 *
397 * @is_err - error detected.
398 *
399 * @signature - Context Validity Check.
400 *
401 * @flashless_boot_on - flag to indicate if sdio_al is in
402 * flshless boot mode
403 *
404 */
405struct sdio_al_device {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700406 struct sdio_al_local_log *dev_log;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700407 struct mmc_card *card;
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200408 struct mmc_host *host;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700409 struct sdio_mailbox *mailbox;
410 struct sdio_channel channel[SDIO_AL_MAX_CHANNELS];
411
412 struct peer_sdioc_sw_header *sdioc_sw_header;
413 struct peer_sdioc_boot_sw_header *sdioc_boot_sw_header;
414
415 struct workqueue_struct *workqueue;
416 struct sdio_al_work sdio_al_work;
417 struct sdio_al_work boot_work;
418
419 int is_ready;
420
421 wait_queue_head_t wait_mbox;
422 int ask_mbox;
423 int bootloader_done;
424
425 struct wake_lock wake_lock;
426 int lpm_chan;
427 int is_ok_to_sleep;
428 unsigned long inactivity_time;
429
430 struct timer_list timer;
431 u32 poll_delay_msec;
432 int is_timer_initialized;
433
434 int is_err;
435
436 u32 signature;
437
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700438 unsigned int is_suspended;
439
440 int flashless_boot_on;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300441 int ch_close_supported;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700442 int state;
443 int (*lpm_callback)(void *, int);
Maya Erez7b1ebd22011-08-20 20:53:24 +0300444
445 int print_after_interrupt;
Maya Erez5795e0d2011-09-12 20:20:06 +0300446
447 u8 *rx_flush_buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700448};
449
450/*
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300451 * Host operation:
452 * lower 16bits are operation code
453 * upper 16bits are operation state
454 */
455#define PEER_OPERATION(op_code , op_state) ((op_code) | ((op_state) << 16))
456#define GET_PEER_OPERATION_CODE(op) ((op) & 0xffff)
457#define GET_PEER_OPERATION_STATE(op) ((op) >> 16)
458
459enum peer_op_code {
460 PEER_OP_CODE_CLOSE = 1
461};
462
463enum peer_op_state {
464 PEER_OP_STATE_INIT = 0,
465 PEER_OP_STATE_START = 1
466};
467
468
469/*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700470 * On the kernel command line specify
471 * sdio_al.debug_lpm_on=1 to enable the LPM debug messages
472 * By default the LPM debug messages are turned off
473 */
474static int debug_lpm_on;
475module_param(debug_lpm_on, int, 0);
476
477/*
478 * On the kernel command line specify
479 * sdio_al.debug_data_on=1 to enable the DATA debug messages
480 * By default the DATA debug messages are turned off
481 */
482static int debug_data_on;
483module_param(debug_data_on, int, 0);
484
Maya Erez7ad06d82011-10-02 15:47:57 +0200485/*
486 * Enables / disables open close debug messages
487 */
488static int debug_close_on = 1;
489module_param(debug_close_on, int, 0);
490
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700491/** The driver context */
492static struct sdio_al *sdio_al;
493
494/* Static functions declaration */
495static int enable_eot_interrupt(struct sdio_al_device *sdio_al_dev,
496 int pipe_index, int enable);
497static int enable_threshold_interrupt(struct sdio_al_device *sdio_al_dev,
498 int pipe_index, int enable);
499static void sdio_func_irq(struct sdio_func *func);
500static void sdio_al_timer_handler(unsigned long data);
501static int get_min_poll_time_msec(struct sdio_al_device *sdio_al_dev);
502static u32 check_pending_rx_packet(struct sdio_channel *ch, u32 eot);
503static u32 remove_handled_rx_packet(struct sdio_channel *ch);
504static int set_pipe_threshold(struct sdio_al_device *sdio_al_dev,
505 int pipe_index, int threshold);
506static int sdio_al_wake_up(struct sdio_al_device *sdio_al_dev,
Maya Erez7b1ebd22011-08-20 20:53:24 +0300507 u32 not_from_int, struct sdio_channel *ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700508static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev);
509static int enable_mask_irq(struct sdio_al_device *sdio_al_dev,
510 int func_num, int enable, u8 bit_offset);
511static int sdio_al_enable_func_retry(struct sdio_func *func, const char *name);
512static void sdio_al_print_info(void);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300513static int sdio_read_internal(struct sdio_channel *ch, void *data, int len);
Maya Erez5795e0d2011-09-12 20:20:06 +0300514static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len);
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200515static void stop_and_del_timer(struct sdio_al_device *sdio_al_dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700516
517#define SDIO_AL_ERR(func) \
518 do { \
519 printk_once(KERN_ERR MODULE_NAME \
520 ":In Error state, ignore %s\n", \
521 func); \
522 sdio_al_print_info(); \
523 } while (0)
524
525#ifdef CONFIG_DEBUG_FS
526static int debug_info_open(struct inode *inode, struct file *file)
527{
528 file->private_data = inode->i_private;
529 return 0;
530}
531
532static ssize_t debug_info_write(struct file *file,
533 const char __user *buf, size_t count, loff_t *ppos)
534{
535 sdio_al_print_info();
536 return 1;
537}
538
539const struct file_operations debug_info_ops = {
540 .open = debug_info_open,
541 .write = debug_info_write,
542};
543
Krishna Kondaa7af6062011-09-01 18:34:38 -0700544struct debugfs_blob_wrapper sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES + 1];
545
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700546/*
547*
548* Trigger on/off for debug messages
549* for trigger off the data messages debug level use:
550* echo 0 > /sys/kernel/debugfs/sdio_al/debug_data_on
551* for trigger on the data messages debug level use:
552* echo 1 > /sys/kernel/debugfs/sdio_al/debug_data_on
553* for trigger off the lpm messages debug level use:
554* echo 0 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
555* for trigger on the lpm messages debug level use:
556* echo 1 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
557*/
558static int sdio_al_debugfs_init(void)
559{
Krishna Kondaa7af6062011-09-01 18:34:38 -0700560 int i, blob_errs = 0;
561
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700562 sdio_al->debug.sdio_al_debug_root = debugfs_create_dir("sdio_al", NULL);
563 if (!sdio_al->debug.sdio_al_debug_root)
564 return -ENOENT;
565
566 sdio_al->debug.sdio_al_debug_lpm_on = debugfs_create_u8("debug_lpm_on",
567 S_IRUGO | S_IWUGO,
568 sdio_al->debug.sdio_al_debug_root,
569 &sdio_al->debug.debug_lpm_on);
570
571 sdio_al->debug.sdio_al_debug_data_on = debugfs_create_u8(
572 "debug_data_on",
573 S_IRUGO | S_IWUGO,
574 sdio_al->debug.sdio_al_debug_root,
575 &sdio_al->debug.debug_data_on);
576
Maya Erez7ad06d82011-10-02 15:47:57 +0200577 sdio_al->debug.sdio_al_debug_close_on = debugfs_create_u8(
578 "debug_close_on",
579 S_IRUGO | S_IWUGO,
580 sdio_al->debug.sdio_al_debug_root,
581 &sdio_al->debug.debug_close_on);
582
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583 sdio_al->debug.sdio_al_debug_info = debugfs_create_file(
584 "sdio_debug_info",
585 S_IRUGO | S_IWUGO,
586 sdio_al->debug.sdio_al_debug_root,
587 NULL,
588 &debug_info_ops);
589
Krishna Kondaa7af6062011-09-01 18:34:38 -0700590 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
591 char temp[18];
592
593 scnprintf(temp, 18, "sdio_al_log_dev_%d", i + 1);
594 sdio_al->debug.sdio_al_debug_log_buffers[i] =
595 debugfs_create_blob(temp,
596 S_IRUGO | S_IWUGO,
597 sdio_al->debug.sdio_al_debug_root,
598 &sdio_al_dbgfs_log[i]);
599 }
600
601 sdio_al->debug.sdio_al_debug_log_buffers[MAX_NUM_OF_SDIO_DEVICES] =
602 debugfs_create_blob("sdio_al_gen_log",
603 S_IRUGO | S_IWUGO,
604 sdio_al->debug.sdio_al_debug_root,
605 &sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES]);
606
607 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i) {
608 if (!sdio_al->debug.sdio_al_debug_log_buffers[i]) {
609 pr_err(MODULE_NAME ": Failed to create debugfs buffer"
610 " entry for "
611 "sdio_al->debug.sdio_al_debug_log_buffers[%d]",
612 i);
613 blob_errs = 1;
614 }
615 }
616
617 if (blob_errs) {
618 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i)
619 if (sdio_al->debug.sdio_al_debug_log_buffers[i])
620 debugfs_remove(
621 sdio_al->
622 debug.sdio_al_debug_log_buffers[i]);
623 }
624
625
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700626 if ((!sdio_al->debug.sdio_al_debug_data_on) &&
627 (!sdio_al->debug.sdio_al_debug_lpm_on) &&
Maya Erez7ad06d82011-10-02 15:47:57 +0200628 (!sdio_al->debug.sdio_al_debug_close_on) &&
Krishna Kondaa7af6062011-09-01 18:34:38 -0700629 (!sdio_al->debug.sdio_al_debug_info) &&
630 blob_errs) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700631 debugfs_remove(sdio_al->debug.sdio_al_debug_root);
632 sdio_al->debug.sdio_al_debug_root = NULL;
633 return -ENOENT;
634 }
Krishna Kondaa7af6062011-09-01 18:34:38 -0700635
636 sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES].data =
637 sdio_al->gen_log.buffer;
638 sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES].size =
639 SDIO_AL_DEBUG_LOG_SIZE;
640
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700641 return 0;
642}
643
644static void sdio_al_debugfs_cleanup(void)
645{
Krishna Kondaa7af6062011-09-01 18:34:38 -0700646 int i;
647
648 debugfs_remove(sdio_al->debug.sdio_al_debug_lpm_on);
649 debugfs_remove(sdio_al->debug.sdio_al_debug_data_on);
Maya Erez7ad06d82011-10-02 15:47:57 +0200650 debugfs_remove(sdio_al->debug.sdio_al_debug_close_on);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651 debugfs_remove(sdio_al->debug.sdio_al_debug_info);
Krishna Kondaa7af6062011-09-01 18:34:38 -0700652
653 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i)
654 debugfs_remove(sdio_al->debug.sdio_al_debug_log_buffers[i]);
655
656 debugfs_remove(sdio_al->debug.sdio_al_debug_root);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700657}
658#endif
659
Krishna Kondaa7af6062011-09-01 18:34:38 -0700660static int sdio_al_log(struct sdio_al_local_log *log, const char *fmt, ...)
661{
662 va_list args;
663 int r;
664 char *tp, *log_buf;
665 unsigned int *log_cur_pos;
666 struct timeval kt;
667 unsigned long flags;
668 static char sdio_al_log_tmp[SDIO_AL_DEBUG_TMP_LOG_SIZE];
669
670 spin_lock_irqsave(&log->log_lock, flags);
671
672 kt = ktime_to_timeval(ktime_get());
673 r = scnprintf(sdio_al_log_tmp, SDIO_AL_DEBUG_TMP_LOG_SIZE,
674 "[%8ld.%6ld] ", kt.tv_sec, kt.tv_usec);
675
676 va_start(args, fmt);
677 r += vscnprintf(&sdio_al_log_tmp[r], (SDIO_AL_DEBUG_TMP_LOG_SIZE - r),
678 fmt, args);
679 va_end(args);
680
681 log_buf = log->buffer;
682 log_cur_pos = &(log->buf_cur_pos);
683
684 for (tp = sdio_al_log_tmp; tp < (sdio_al_log_tmp + r); tp++) {
685 log_buf[(*log_cur_pos)++] = *tp;
686 if ((*log_cur_pos) == SDIO_AL_DEBUG_LOG_SIZE)
687 *log_cur_pos = 0;
688 }
689
690 spin_unlock_irqrestore(&log->log_lock, flags);
691
692 return r;
693}
694
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700695static int sdio_al_verify_func1(struct sdio_al_device *sdio_al_dev,
696 char const *func)
697{
698 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700699 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
700 "sdio_al_dev\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700701 return -ENODEV;
702 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200703
704 if (sdio_al_dev->signature != SDIO_AL_SIGNATURE) {
705 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
706 "signature\n", func);
707 return -ENODEV;
708 }
709
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700710 if (!sdio_al_dev->card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700711 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
712 "card\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700713 return -ENODEV;
714 }
715 if (!sdio_al_dev->card->sdio_func[0]) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700716 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
717 "func1\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700718 return -ENODEV;
719 }
720 return 0;
721}
722
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200723static int sdio_al_claim_mutex(struct sdio_al_device *sdio_al_dev,
724 char const *func)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700725{
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200726 if (!sdio_al_dev) {
727 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
728 "device\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700729 return -ENODEV;
730 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200731
732 if (sdio_al_dev->signature != SDIO_AL_SIGNATURE) {
733 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
734 "device signature\n", func);
735 return -ENODEV;
736 }
737
738 if (!sdio_al_dev->host) {
739 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
740 "host\n", func);
741 return -ENODEV;
742 }
743
744 mmc_claim_host(sdio_al_dev->host);
745
746 return 0;
747}
748
749static int sdio_al_release_mutex(struct sdio_al_device *sdio_al_dev,
750 char const *func)
751{
752 if (!sdio_al_dev) {
753 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
754 "device\n", func);
755 return -ENODEV;
756 }
757
758 if (sdio_al_dev->signature != SDIO_AL_SIGNATURE) {
759 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
760 "device signature\n", func);
761 return -ENODEV;
762 }
763
764 if (!sdio_al_dev->host) {
765 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
766 "host\n", func);
767 return -ENODEV;
768 }
769
770 mmc_release_host(sdio_al_dev->host);
771
772 return 0;
773}
774
775static int sdio_al_claim_mutex_and_verify_dev(
776 struct sdio_al_device *sdio_al_dev,
777 char const *func)
778{
779 if (sdio_al_claim_mutex(sdio_al_dev, __func__))
780 return -ENODEV;
781
782 if (sdio_al_dev->state != CARD_INSERTED) {
783 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
784 "device state %d\n", func, sdio_al_dev->state);
785 sdio_al_release_mutex(sdio_al_dev, __func__);
786 return -ENODEV;
787 }
788
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700789 return 0;
790}
791
792static void sdio_al_get_into_err_state(struct sdio_al_device *sdio_al_dev)
793{
794 if ((!sdio_al) || (!sdio_al_dev))
795 return;
796
797 sdio_al_dev->is_err = true;
798 sdio_al->debug.debug_data_on = 0;
799 sdio_al->debug.debug_lpm_on = 0;
800 sdio_al_print_info();
801}
802
803void sdio_al_register_lpm_cb(void *device_handle,
804 int(*lpm_callback)(void *, int))
805{
806 struct sdio_al_device *sdio_al_dev =
807 (struct sdio_al_device *) device_handle;
808
809 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700810 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - "
811 "device_handle is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700812 return;
813 }
814
815 if (lpm_callback) {
816 sdio_al_dev->lpm_callback = lpm_callback;
817 lpm_callback((void *)sdio_al_dev,
818 sdio_al_dev->is_ok_to_sleep);
819 }
Krishna Kondaa7af6062011-09-01 18:34:38 -0700820
821 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - device %d "
822 "registered for wakeup callback\n", __func__,
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200823 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700824}
825
826void sdio_al_unregister_lpm_cb(void *device_handle)
827{
828 struct sdio_al_device *sdio_al_dev =
829 (struct sdio_al_device *) device_handle;
830
831 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700832 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - "
833 "device_handle is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700834 return;
835 }
836
837 sdio_al_dev->lpm_callback = NULL;
Krishna Kondaa7af6062011-09-01 18:34:38 -0700838 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - device %d "
839 "unregister for wakeup callback\n", __func__,
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200840 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841}
842
843static void sdio_al_vote_for_sleep(struct sdio_al_device *sdio_al_dev,
844 int is_vote_for_sleep)
845{
846 pr_debug(MODULE_NAME ": %s()", __func__);
847
Yaniv Gardi3e327762011-07-27 11:11:04 +0300848 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700849 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - sdio_al_dev"
850 " is NULL\n", __func__);
Yaniv Gardi3e327762011-07-27 11:11:04 +0300851 return;
852 }
853
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700854 if (is_vote_for_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +0300855 pr_debug(MODULE_NAME ": %s - sdio vote for Sleep", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700856 wake_unlock(&sdio_al_dev->wake_lock);
857 } else {
Maya Erez7b1ebd22011-08-20 20:53:24 +0300858 pr_debug(MODULE_NAME ": %s - sdio vote against sleep",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700859 __func__);
860 wake_lock(&sdio_al_dev->wake_lock);
861 }
862
863 if (sdio_al_dev->lpm_callback != NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700864 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - "
865 "is_vote_for_sleep=%d for card#%d, "
866 "calling callback...", __func__,
867 is_vote_for_sleep,
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200868 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700869 sdio_al_dev->lpm_callback((void *)sdio_al_dev,
870 is_vote_for_sleep);
871 }
872}
873
874/**
875 * Write SDIO-Client lpm information
876 * Should only be called with host claimed.
877 */
878static int write_lpm_info(struct sdio_al_device *sdio_al_dev)
879{
880 struct sdio_func *lpm_func =
881 sdio_al_dev->card->sdio_func[sdio_al_dev->lpm_chan+1];
882 int offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
883 sizeof(struct peer_sdioc_channel_config) *
884 sdio_al_dev->lpm_chan+
885 offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
886 int ret;
887
888 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700889 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
890 "lpm_chan for card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200891 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700892 return -EINVAL;
893 }
894
895 pr_debug(MODULE_NAME ":write_lpm_info is_ok_to_sleep=%d, device %d\n",
896 sdio_al_dev->is_ok_to_sleep,
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200897 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700898
899 ret = sdio_memcpy_toio(lpm_func, SDIOC_SW_MAILBOX_ADDR+offset,
900 &sdio_al_dev->is_ok_to_sleep, sizeof(u32));
901 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700902 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
903 "write lpm info for card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200904 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700905 return ret;
906 }
907
908 return 0;
909}
910
911/* Set inactivity counter to intial value to allow clients come up */
912static inline void start_inactive_time(struct sdio_al_device *sdio_al_dev)
913{
914 sdio_al_dev->inactivity_time = jiffies +
915 msecs_to_jiffies(INITIAL_INACTIVITY_TIME_MSEC);
916}
917
918static inline void restart_inactive_time(struct sdio_al_device *sdio_al_dev)
919{
920 sdio_al_dev->inactivity_time = jiffies +
921 msecs_to_jiffies(INACTIVITY_TIME_MSEC);
922}
923
924static inline int is_inactive_time_expired(struct sdio_al_device *sdio_al_dev)
925{
926 return time_after(jiffies, sdio_al_dev->inactivity_time);
927}
928
929
930static int is_user_irq_enabled(struct sdio_al_device *sdio_al_dev,
931 int func_num)
932{
933 int ret = 0;
934 struct sdio_func *func1;
935 u32 user_irq = 0;
936 u32 addr = 0;
937 u32 offset = 0;
938 u32 masked_user_irq = 0;
939
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200940 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700941 return 0;
942 func1 = sdio_al_dev->card->sdio_func[0];
943
944 if (func_num < 4) {
945 addr = FUNC_1_4_USER_IRQ_ADDR;
946 offset = func_num * 8;
947 } else {
948 addr = FUNC_5_7_USER_IRQ_ADDR;
949 offset = (func_num - 4) * 8;
950 }
951
952 user_irq = sdio_readl(func1, addr, &ret);
953 if (ret) {
954 pr_debug(MODULE_NAME ":read_user_irq fail\n");
955 return 0;
956 }
957
958 masked_user_irq = (user_irq >> offset) && 0xFF;
959 if (masked_user_irq == 0x1) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700960 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":user_irq "
961 "enabled\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700962 return 1;
963 }
964
965 return 0;
966}
967
968static void sdio_al_sleep(struct sdio_al_device *sdio_al_dev,
969 struct mmc_host *host)
970{
971 int i;
972
973 /* Go to sleep */
Maya Erez7b1ebd22011-08-20 20:53:24 +0300974 pr_debug(MODULE_NAME ":Inactivity timer expired."
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700975 " Going to sleep\n");
976 /* Stop mailbox timer */
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200977 stop_and_del_timer(sdio_al_dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700978 /* Make sure we get interrupt for non-packet-mode right away */
979 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
980 struct sdio_channel *ch = &sdio_al_dev->channel[i];
Maya Erez5795e0d2011-09-12 20:20:06 +0300981 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
982 (ch->state != SDIO_CHANNEL_STATE_CLOSED)) {
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300983 pr_debug(MODULE_NAME ":continue for channel %s in"
984 " state %d\n", ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700985 continue;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300986 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700987 if (ch->is_packet_mode == false) {
988 ch->read_threshold = 1;
989 set_pipe_threshold(sdio_al_dev,
990 ch->rx_pipe_index,
991 ch->read_threshold);
992 }
993 }
Maya Erezfd915312011-07-14 13:45:34 +0300994 /* Prevent modem to go to sleep until we get the PROG_DONE on
995 the dummy CMD52 */
Maya Erez86cebda2011-10-11 11:13:40 +0200996 msmsdcc_set_pwrsave(sdio_al_dev->host, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700997 /* Mark HOST_OK_TOSLEEP */
998 sdio_al_dev->is_ok_to_sleep = 1;
999 write_lpm_info(sdio_al_dev);
1000
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001001 msmsdcc_lpm_enable(host);
Krishna Kondaa7af6062011-09-01 18:34:38 -07001002 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Finished sleep sequence"
1003 " for card %d. Sleep now.\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001004 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001005 /* Release wakelock */
1006 sdio_al_vote_for_sleep(sdio_al_dev, 1);
1007}
1008
1009
1010/**
1011 * Read SDIO-Client Mailbox from Function#1.thresh_pipe
1012 *
1013 * The mailbox contain the bytes available per pipe,
1014 * and the End-Of-Transfer indication per pipe (if available).
1015 *
1016 * WARNING: Each time the Mailbox is read from the client, the
1017 * read_bytes_avail is incremented with another pending
1018 * transfer. Therefore, a pending rx-packet should be added to a
1019 * list before the next read of the mailbox.
1020 *
1021 * This function should run from a workqueue context since it
1022 * notifies the clients.
1023 *
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001024 * This function assumes that sdio_al_claim_mutex was called before
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001025 * calling it.
1026 *
1027 */
1028static int read_mailbox(struct sdio_al_device *sdio_al_dev, int from_isr)
1029{
1030 int ret;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001031 struct sdio_func *func1 = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001032 struct sdio_mailbox *mailbox = sdio_al_dev->mailbox;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001033 struct mmc_host *host = sdio_al_dev->host;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001034 u32 new_write_avail = 0;
1035 u32 old_write_avail = 0;
1036 u32 any_read_avail = 0;
1037 u32 any_write_pending = 0;
1038 int i;
1039 u32 rx_notify_bitmask = 0;
1040 u32 tx_notify_bitmask = 0;
1041 u32 eot_pipe = 0;
1042 u32 thresh_pipe = 0;
1043 u32 overflow_pipe = 0;
1044 u32 underflow_pipe = 0;
1045 u32 thresh_intr_mask = 0;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001046 int is_closing = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001047
1048 if (sdio_al_dev->is_err) {
1049 SDIO_AL_ERR(__func__);
1050 return 0;
1051 }
1052
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001053 if (sdio_al_verify_func1(sdio_al_dev, __func__))
1054 return -ENODEV;
1055 func1 = sdio_al_dev->card->sdio_func[0];
1056
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001057 pr_debug(MODULE_NAME ":start %s from_isr = %d for card %d.\n"
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001058 , __func__, from_isr, sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001059
1060 pr_debug(MODULE_NAME ":before sdio_memcpy_fromio.\n");
Maya Erez320a7ca2011-08-03 09:41:27 +03001061 memset(mailbox, 0, sizeof(struct sdio_mailbox));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001062 ret = sdio_memcpy_fromio(func1, mailbox,
1063 HW_MAILBOX_ADDR, sizeof(*mailbox));
1064 pr_debug(MODULE_NAME ":after sdio_memcpy_fromio.\n");
Maya Erez320a7ca2011-08-03 09:41:27 +03001065 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001066 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to read "
1067 "Mailbox for card %d, goto error state\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001068 sdio_al_dev->host->index);
Maya Erez320a7ca2011-08-03 09:41:27 +03001069 sdio_al_get_into_err_state(sdio_al_dev);
Maya Erez320a7ca2011-08-03 09:41:27 +03001070 goto exit_err;
1071 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001072
1073 eot_pipe = (mailbox->eot_pipe_0_7) |
1074 (mailbox->eot_pipe_8_15<<8);
1075 thresh_pipe = (mailbox->thresh_above_limit_pipe_0_7) |
1076 (mailbox->thresh_above_limit_pipe_8_15<<8);
1077
1078 overflow_pipe = (mailbox->overflow_pipe_0_7) |
1079 (mailbox->overflow_pipe_8_15<<8);
1080 underflow_pipe = mailbox->underflow_pipe_0_7 |
1081 (mailbox->underflow_pipe_8_15<<8);
1082 thresh_intr_mask =
1083 (mailbox->mask_thresh_above_limit_pipe_0_7) |
1084 (mailbox->mask_thresh_above_limit_pipe_8_15<<8);
1085
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001086 if (overflow_pipe || underflow_pipe)
Krishna Kondaa7af6062011-09-01 18:34:38 -07001087 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Mailbox ERROR "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001088 "overflow=0x%x, underflow=0x%x\n",
1089 overflow_pipe, underflow_pipe);
1090
1091 /* In case of modem reset we would like to read the daya from the modem
1092 to clear the interrupts but do not process it */
1093 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001094 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_device"
1095 " (card %d) is in invalid state %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001096 sdio_al_dev->host->index,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001097 sdio_al_dev->state);
1098 return -ENODEV;
1099 }
1100
1101 pr_debug(MODULE_NAME ":card %d: eot=0x%x, thresh=0x%x\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001102 sdio_al_dev->host->index,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001103 eot_pipe, thresh_pipe);
1104
1105 /* Scan for Rx Packets available and update read available bytes */
1106 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1107 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1108 u32 old_read_avail;
1109 u32 read_avail;
1110 u32 new_packet_size = 0;
1111
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001112 if (ch->state == SDIO_CHANNEL_STATE_CLOSING)
1113 is_closing = true; /* used to prevent sleep */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001114
1115 old_read_avail = ch->read_avail;
1116 read_avail = mailbox->pipe_bytes_avail[ch->rx_pipe_index];
1117
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001118 if ((ch->state == SDIO_CHANNEL_STATE_CLOSED) &&
1119 (read_avail > 0)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001120 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1121 ":%s: Invalid read_avail 0x%x, for CLOSED ch %s\n",
Maya Erez5795e0d2011-09-12 20:20:06 +03001122 __func__, read_avail, ch->name);
1123 sdio_read_from_closed_ch(ch, read_avail);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001124 }
1125 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
1126 (ch->state != SDIO_CHANNEL_STATE_CLOSING))
1127 continue;
1128
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001129 if (read_avail > INVALID_DATA_AVAILABLE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001130 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001131 ":Invalid read_avail 0x%x for pipe %d\n",
1132 read_avail, ch->rx_pipe_index);
1133 continue;
1134 }
1135 any_read_avail |= read_avail | old_read_avail;
1136 ch->statistics.last_any_read_avail = any_read_avail;
1137 ch->statistics.last_read_avail = read_avail;
1138 ch->statistics.last_old_read_avail = old_read_avail;
1139
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001140 if (ch->is_packet_mode) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001141 if ((eot_pipe & (1<<ch->rx_pipe_index)) &&
1142 sdio_al_dev->print_after_interrupt) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001143 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME
1144 ":Interrupt on ch %s, "
1145 "card %d", ch->name,
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001146 sdio_al_dev->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03001147 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001148 new_packet_size = check_pending_rx_packet(ch, eot_pipe);
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001149 } else {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001150 if ((thresh_pipe & (1<<ch->rx_pipe_index)) &&
1151 sdio_al_dev->print_after_interrupt) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001152 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME
1153 ":Interrupt on ch %s, "
1154 "card %d", ch->name,
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001155 sdio_al_dev->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03001156 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001157 ch->read_avail = read_avail;
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001158 /* Restore default thresh for non packet channels */
1159 if ((ch->read_threshold != ch->def_read_threshold) &&
1160 (read_avail >= ch->threshold_change_cnt)) {
1161 ch->read_threshold = ch->def_read_threshold;
1162 set_pipe_threshold(sdio_al_dev,
1163 ch->rx_pipe_index,
1164 ch->read_threshold);
1165 }
1166 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001167
1168 if ((ch->is_packet_mode) && (new_packet_size > 0)) {
1169 rx_notify_bitmask |= (1<<ch->num);
1170 ch->statistics.total_notifs++;
1171 }
1172
1173 if ((!ch->is_packet_mode) && (ch->read_avail > 0) &&
1174 (old_read_avail == 0)) {
1175 rx_notify_bitmask |= (1<<ch->num);
1176 ch->statistics.total_notifs++;
1177 }
1178 }
Maya Erez7b1ebd22011-08-20 20:53:24 +03001179 sdio_al_dev->print_after_interrupt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001180
1181 /* Update Write available */
1182 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1183 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1184
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001185 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
1186 (ch->state != SDIO_CHANNEL_STATE_CLOSING))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001187 continue;
1188
1189 new_write_avail = mailbox->pipe_bytes_avail[ch->tx_pipe_index];
1190
1191 if (new_write_avail > INVALID_DATA_AVAILABLE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001192 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001193 ":Invalid write_avail 0x%x for pipe %d\n",
1194 new_write_avail, ch->tx_pipe_index);
1195 continue;
1196 }
1197
1198 old_write_avail = ch->write_avail;
1199 ch->write_avail = new_write_avail;
1200
1201 if ((old_write_avail <= ch->min_write_avail) &&
1202 (new_write_avail >= ch->min_write_avail))
1203 tx_notify_bitmask |= (1<<ch->num);
1204
1205 /* There is not enough write avail for this channel.
1206 We need to keep reading mailbox to wait for the appropriate
1207 write avail and cannot sleep. Ignore SMEM channel that has
1208 only one direction. */
1209 if (strcmp(ch->name, "SDIO_SMEM"))
1210 any_write_pending |=
1211 (new_write_avail < ch->ch_config.max_tx_threshold);
1212 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001213 /* notify clients */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001214 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1215 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1216
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001217 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) ||
1218 (ch->notify == NULL))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001219 continue;
1220
1221 if (rx_notify_bitmask & (1<<ch->num))
1222 ch->notify(ch->priv,
1223 SDIO_EVENT_DATA_READ_AVAIL);
1224
1225 if (tx_notify_bitmask & (1<<ch->num))
1226 ch->notify(ch->priv,
1227 SDIO_EVENT_DATA_WRITE_AVAIL);
1228 }
1229
1230
1231 if ((rx_notify_bitmask == 0) && (tx_notify_bitmask == 0) &&
1232 !any_read_avail && !any_write_pending) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001233 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Nothing to "
1234 "Notify for card %d, is_closing=%d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001235 sdio_al_dev->host->index, is_closing);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001236 if (is_closing)
1237 restart_inactive_time(sdio_al_dev);
1238 else if (is_inactive_time_expired(sdio_al_dev))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001239 sdio_al_sleep(sdio_al_dev, host);
1240 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001241 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Notify bitmask"
1242 " for card %d rx=0x%x, tx=0x%x.\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001243 sdio_al_dev->host->index,
Krishna Kondaa7af6062011-09-01 18:34:38 -07001244 rx_notify_bitmask, tx_notify_bitmask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001245 /* Restart inactivity timer if any activity on the channel */
1246 restart_inactive_time(sdio_al_dev);
1247 }
1248
1249 pr_debug(MODULE_NAME ":end %s.\n", __func__);
1250
1251exit_err:
1252 return ret;
1253}
1254
1255/**
1256 * Check pending rx packet when reading the mailbox.
1257 */
1258static u32 check_pending_rx_packet(struct sdio_channel *ch, u32 eot)
1259{
1260 u32 rx_pending;
1261 u32 rx_avail;
1262 u32 new_packet_size = 0;
1263 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
1264
1265
1266 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001267 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
1268 " for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001269 return -EINVAL;
1270 }
1271
1272 mutex_lock(&ch->ch_lock);
1273
1274 rx_pending = ch->rx_pending_bytes;
1275 rx_avail = sdio_al_dev->mailbox->pipe_bytes_avail[ch->rx_pipe_index];
1276
1277 pr_debug(MODULE_NAME ":pipe %d of card %d rx_avail=0x%x, "
1278 "rx_pending=0x%x\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001279 ch->rx_pipe_index, sdio_al_dev->host->index, rx_avail,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001280 rx_pending);
1281
1282
1283 /* new packet detected */
1284 if (eot & (1<<ch->rx_pipe_index)) {
1285 struct rx_packet_size *p = NULL;
1286 new_packet_size = rx_avail - rx_pending;
1287
1288 if ((rx_avail <= rx_pending)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001289 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1290 ": Invalid new packet size."
1291 " rx_avail=%d.\n", rx_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001292 new_packet_size = 0;
1293 goto exit_err;
1294 }
1295
1296 p = kzalloc(sizeof(*p), GFP_KERNEL);
Maya Erezd9cc2292011-08-04 09:20:31 +03001297 if (p == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001298 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1299 ": failed to allocate item for "
1300 "rx_pending list. rx_avail=%d, "
1301 "rx_pending=%d.\n",
1302 rx_avail, rx_pending);
Maya Erezd9cc2292011-08-04 09:20:31 +03001303 new_packet_size = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001304 goto exit_err;
Maya Erezd9cc2292011-08-04 09:20:31 +03001305 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001306 p->size = new_packet_size;
1307 /* Add new packet as last */
1308 list_add_tail(&p->list, &ch->rx_size_list_head);
1309 ch->rx_pending_bytes += new_packet_size;
1310
1311 if (ch->read_avail == 0)
1312 ch->read_avail = new_packet_size;
1313 }
1314
1315exit_err:
1316 mutex_unlock(&ch->ch_lock);
1317
1318 return new_packet_size;
1319}
1320
1321
1322
1323/**
1324 * Remove first pending packet from the list.
1325 */
1326static u32 remove_handled_rx_packet(struct sdio_channel *ch)
1327{
1328 struct rx_packet_size *p = NULL;
1329
1330 mutex_lock(&ch->ch_lock);
1331
1332 ch->rx_pending_bytes -= ch->read_avail;
1333
1334 if (!list_empty(&ch->rx_size_list_head)) {
1335 p = list_first_entry(&ch->rx_size_list_head,
1336 struct rx_packet_size, list);
1337 list_del(&p->list);
1338 kfree(p);
Maya Erezd9cc2292011-08-04 09:20:31 +03001339 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001340 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: ch "
1341 "%s: unexpected empty list!!\n",
1342 __func__, ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001343 }
1344
1345 if (list_empty(&ch->rx_size_list_head)) {
1346 ch->read_avail = 0;
1347 } else {
1348 p = list_first_entry(&ch->rx_size_list_head,
1349 struct rx_packet_size, list);
1350 ch->read_avail = p->size;
1351 }
1352
1353 mutex_unlock(&ch->ch_lock);
1354
1355 return ch->read_avail;
1356}
1357
1358
1359/**
1360 * Bootloader worker function.
1361 *
1362 * @note: clear the bootloader_done flag only after reading the
1363 * mailbox, to ignore more requests while reading the mailbox.
1364 */
1365static void boot_worker(struct work_struct *work)
1366{
1367 int ret = 0;
1368 int func_num = 0;
1369 int i;
1370 struct sdio_al_device *sdio_al_dev = NULL;
1371 struct sdio_al_work *sdio_al_work = container_of(work,
1372 struct sdio_al_work,
1373 work);
1374
1375 if (sdio_al_work == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001376 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1377 "sdio_al_work\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001378 return;
1379 }
1380
1381 sdio_al_dev = sdio_al_work->sdio_al_dev;
1382 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001383 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1384 "sdio_al_dev\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001385 return;
1386 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07001387 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":Bootloader Worker Started"
1388 ", wait for bootloader_done event..\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001389 wait_event(sdio_al_dev->wait_mbox,
1390 sdio_al_dev->bootloader_done);
Krishna Kondaa7af6062011-09-01 18:34:38 -07001391 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":Got bootloader_done "
1392 "event..\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001393 /* Do polling until MDM is up */
1394 for (i = 0; i < 5000; ++i) {
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001395 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001396 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001397 if (is_user_irq_enabled(sdio_al_dev, func_num)) {
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001398 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001399 sdio_al_dev->bootloader_done = 0;
1400 ret = sdio_al_client_setup(sdio_al_dev);
1401 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001402 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1403 ": sdio_al_client_setup failed, "
1404 "for card %d ret=%d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001405 sdio_al_dev->host->index, ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001406 sdio_al_get_into_err_state(sdio_al_dev);
1407 }
1408 goto done;
1409 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001410 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001411 msleep(100);
1412 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07001413 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Timeout waiting for "
1414 "user_irq for card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001415 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001416 sdio_al_get_into_err_state(sdio_al_dev);
1417
1418done:
1419 pr_debug(MODULE_NAME ":Boot Worker for card %d Exit!\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001420 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001421}
1422
1423/**
1424 * Worker function.
1425 *
1426 * @note: clear the ask_mbox flag only after
1427 * reading the mailbox, to ignore more requests while
1428 * reading the mailbox.
1429 */
1430static void worker(struct work_struct *work)
1431{
1432 int ret = 0;
1433 struct sdio_al_device *sdio_al_dev = NULL;
1434 struct sdio_al_work *sdio_al_work = container_of(work,
1435 struct sdio_al_work,
1436 work);
1437 if (sdio_al_work == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001438 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": worker: NULL "
1439 "sdio_al_work\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001440 return;
1441 }
1442
1443 sdio_al_dev = sdio_al_work->sdio_al_dev;
1444 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001445 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": worker: NULL "
1446 "sdio_al_dev\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001447 return;
1448 }
1449 pr_debug(MODULE_NAME ":Worker Started..\n");
1450 while ((sdio_al_dev->is_ready) && (ret == 0)) {
1451 pr_debug(MODULE_NAME ":Wait for read mailbox request..\n");
1452 wait_event(sdio_al_dev->wait_mbox, sdio_al_dev->ask_mbox);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001453 if (!sdio_al_dev->is_ready)
1454 break;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001455 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
1456 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001457 if (sdio_al_dev->is_ok_to_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001458 ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001459 if (ret) {
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001460 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001461 return;
1462 }
1463 }
1464 ret = read_mailbox(sdio_al_dev, false);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001465 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001466 sdio_al_dev->ask_mbox = false;
1467 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001468
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001469 pr_debug(MODULE_NAME ":Worker Exit!\n");
1470}
1471
1472/**
1473 * Write command using CMD54 rather than CMD53.
1474 * Writing with CMD54 generate EOT interrupt at the
1475 * SDIO-Client.
1476 * Based on mmc_io_rw_extended()
1477 */
1478static int sdio_write_cmd54(struct mmc_card *card, unsigned fn,
1479 unsigned addr, const u8 *buf,
1480 unsigned blocks, unsigned blksz)
1481{
1482 struct mmc_request mrq;
1483 struct mmc_command cmd;
1484 struct mmc_data data;
1485 struct scatterlist sg;
1486 int incr_addr = 1; /* MUST */
1487 int write = 1;
1488
1489 BUG_ON(!card);
1490 BUG_ON(fn > 7);
1491 BUG_ON(blocks == 1 && blksz > 512);
1492 WARN_ON(blocks == 0);
1493 WARN_ON(blksz == 0);
1494
1495 write = true;
1496 pr_debug(MODULE_NAME ":sdio_write_cmd54()"
1497 "fn=%d,buf=0x%x,blocks=%d,blksz=%d\n",
1498 fn, (u32) buf, blocks, blksz);
1499
1500 memset(&mrq, 0, sizeof(struct mmc_request));
1501 memset(&cmd, 0, sizeof(struct mmc_command));
1502 memset(&data, 0, sizeof(struct mmc_data));
1503
1504 mrq.cmd = &cmd;
1505 mrq.data = &data;
1506
1507 cmd.opcode = SD_IO_RW_EXTENDED_QCOM;
1508
1509 cmd.arg = write ? 0x80000000 : 0x00000000;
1510 cmd.arg |= fn << 28;
1511 cmd.arg |= incr_addr ? 0x04000000 : 0x00000000;
1512 cmd.arg |= addr << 9;
1513 if (blocks == 1 && blksz <= 512)
1514 cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */
1515 else
1516 cmd.arg |= 0x08000000 | blocks; /* block mode */
1517 cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
1518
1519 data.blksz = blksz;
1520 data.blocks = blocks;
1521 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
1522 data.sg = &sg;
1523 data.sg_len = 1;
1524
1525 sg_init_one(&sg, buf, blksz * blocks);
1526
1527 mmc_set_data_timeout(&data, card);
1528
1529 mmc_wait_for_req(card->host, &mrq);
1530
1531 if (cmd.error)
1532 return cmd.error;
1533 if (data.error)
1534 return data.error;
1535
1536 if (mmc_host_is_spi(card->host)) {
1537 /* host driver already reported errors */
1538 } else {
1539 if (cmd.resp[0] & R5_ERROR) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001540 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1541 ":%s: R5_ERROR for card %d",
1542 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001543 return -EIO;
1544 }
1545 if (cmd.resp[0] & R5_FUNCTION_NUMBER) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001546 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1547 ":%s: R5_FUNCTION_NUMBER for card %d",
1548 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001549 return -EINVAL;
1550 }
1551 if (cmd.resp[0] & R5_OUT_OF_RANGE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001552 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1553 ":%s: R5_OUT_OF_RANGE for card %d",
1554 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001555 return -ERANGE;
1556 }
1557 }
1558
1559 return 0;
1560}
1561
1562
1563/**
1564 * Write data to channel.
1565 * Handle different data size types.
1566 *
1567 */
1568static int sdio_ch_write(struct sdio_channel *ch, const u8 *buf, u32 len)
1569{
1570 int ret = 0;
1571 unsigned blksz = ch->func->cur_blksize;
1572 int blocks = len / blksz;
1573 int remain_bytes = len % blksz;
1574 struct mmc_card *card = NULL;
1575 u32 fn = ch->func->num;
1576
Krishna Kondaa7af6062011-09-01 18:34:38 -07001577 if (!ch) {
1578 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1579 "channel\n", __func__);
1580 return -ENODEV;
1581 }
1582
1583 if (!ch->sdio_al_dev) {
1584 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1585 "sdio_al_dev\n", __func__);
1586 return -ENODEV;
1587 }
1588
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001589 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001590 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":channel "
1591 "%s trying to write 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001592 return -EINVAL;
1593 }
1594
1595 card = ch->func->card;
1596
1597 if (remain_bytes) {
1598 /* CMD53 */
1599 if (blocks) {
1600 ret = sdio_memcpy_toio(ch->func, PIPE_TX_FIFO_ADDR,
1601 (void *) buf, blocks*blksz);
1602 if (ret != 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001603 sdio_al_loge(ch->sdio_al_dev->dev_log,
1604 MODULE_NAME ":%s: sdio_memcpy_toio "
1605 "failed for channel %s\n",
1606 __func__, ch->name);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001607 sdio_al_get_into_err_state(ch->sdio_al_dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001608 return ret;
1609 }
1610 }
1611
1612 buf += (blocks*blksz);
1613
1614 ret = sdio_write_cmd54(card, fn, PIPE_TX_FIFO_ADDR,
1615 buf, 1, remain_bytes);
1616 } else {
1617 ret = sdio_write_cmd54(card, fn, PIPE_TX_FIFO_ADDR,
1618 buf, blocks, blksz);
1619 }
1620
1621 if (ret != 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001622 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
1623 "sdio_write_cmd54 failed for channel %s\n",
1624 __func__, ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001625 ch->sdio_al_dev->is_err = true;
1626 return ret;
1627 }
1628
1629 return ret;
1630}
1631
1632static int sdio_al_bootloader_completed(void)
1633{
1634 int i;
1635
1636 pr_debug(MODULE_NAME ":sdio_al_bootloader_completed was called\n");
1637
1638 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
1639 struct sdio_al_device *dev = NULL;
1640 if (sdio_al->devices[i] == NULL)
1641 continue;
1642 dev = sdio_al->devices[i];
1643 dev->bootloader_done = 1;
1644 wake_up(&dev->wait_mbox);
1645 }
1646
1647 return 0;
1648}
1649
1650static int sdio_al_wait_for_bootloader_comp(struct sdio_al_device *sdio_al_dev)
1651{
1652 int ret = 0;
1653
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001654 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001655 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001656
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001657 /*
1658 * Enable function 0 interrupt mask to allow 9k to raise this interrupt
1659 * in power-up. When sdio_downloader will notify its completion
1660 * we will poll on this interrupt to wait for 9k power-up
1661 */
1662 ret = enable_mask_irq(sdio_al_dev, 0, 1, 0);
1663 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001664 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1665 ": Enable_mask_irq for card %d failed, "
1666 "ret=%d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001667 sdio_al_dev->host->index, ret);
1668 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001669 return ret;
1670 }
1671
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001672 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001673
1674 /*
1675 * Start bootloader worker that will wait for the bootloader
1676 * completion
1677 */
1678 sdio_al_dev->boot_work.sdio_al_dev = sdio_al_dev;
1679 INIT_WORK(&sdio_al_dev->boot_work.work, boot_worker);
1680 sdio_al_dev->bootloader_done = 0;
1681 queue_work(sdio_al_dev->workqueue, &sdio_al_dev->boot_work.work);
1682
1683 return 0;
1684}
1685
1686static int sdio_al_bootloader_setup(void)
1687{
1688 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001689 struct sdio_al_device *bootloader_dev = sdio_al->bootloader_dev;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001690 struct sdio_func *func1 = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001691
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001692 if (sdio_al_claim_mutex_and_verify_dev(bootloader_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001693 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001694
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001695 if (bootloader_dev->flashless_boot_on) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001696 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":Already "
1697 "in boot process.\n");
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001698 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001699 return 0;
1700 }
1701
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001702 bootloader_dev->sdioc_boot_sw_header
1703 = kzalloc(sizeof(*bootloader_dev->sdioc_boot_sw_header),
1704 GFP_KERNEL);
1705 if (bootloader_dev->sdioc_boot_sw_header == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001706 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":fail to "
1707 "allocate sdioc boot sw header.\n");
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001708 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001709 return -ENOMEM;
1710 }
1711
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001712 if (sdio_al_verify_func1(bootloader_dev, __func__)) {
1713 sdio_al_release_mutex(bootloader_dev, __func__);
1714 goto exit_err;
1715 }
1716 func1 = bootloader_dev->card->sdio_func[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001717
1718 ret = sdio_memcpy_fromio(func1,
1719 bootloader_dev->sdioc_boot_sw_header,
1720 SDIOC_SW_HEADER_ADDR,
1721 sizeof(struct peer_sdioc_boot_sw_header));
1722 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001723 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":fail to "
1724 "read sdioc boot sw header.\n");
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001725 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001726 goto exit_err;
1727 }
1728
1729 if (bootloader_dev->sdioc_boot_sw_header->signature !=
1730 (u32) PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001731 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":invalid "
1732 "mailbox signature 0x%x.\n",
1733 bootloader_dev->sdioc_boot_sw_header->signature);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001734 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001735 ret = -EINVAL;
1736 goto exit_err;
1737 }
1738
1739 /* Upper byte has to be equal - no backward compatibility for unequal */
1740 if ((bootloader_dev->sdioc_boot_sw_header->version >> 16) !=
1741 (sdio_al->pdata->peer_sdioc_boot_version_major)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001742 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ": HOST(0x%x)"
1743 " and CLIENT(0x%x) SDIO_AL BOOT VERSION don't match\n",
1744 ((sdio_al->pdata->peer_sdioc_boot_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001745 sdio_al->pdata->peer_sdioc_boot_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001746 bootloader_dev->sdioc_boot_sw_header->version);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001747 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001748 ret = -EIO;
1749 goto exit_err;
1750 }
1751
Krishna Kondaa7af6062011-09-01 18:34:38 -07001752 sdio_al_logi(bootloader_dev->dev_log, MODULE_NAME ": SDIOC BOOT SW "
1753 "version 0x%x\n",
1754 bootloader_dev->sdioc_boot_sw_header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001755
1756 bootloader_dev->flashless_boot_on = true;
1757
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001758 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001759
1760 ret = sdio_al_wait_for_bootloader_comp(bootloader_dev);
1761 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001762 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
1763 ": sdio_al_wait_for_bootloader_comp failed, "
1764 "err=%d\n", ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001765 goto exit_err;
1766 }
1767
1768 ret = sdio_downloader_setup(bootloader_dev->card, 1,
1769 bootloader_dev->sdioc_boot_sw_header->boot_ch_num,
1770 sdio_al_bootloader_completed);
1771
1772 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001773 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
1774 ": sdio_downloader_setup failed, err=%d\n", ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001775 goto exit_err;
1776 }
1777
Krishna Kondaa7af6062011-09-01 18:34:38 -07001778 sdio_al_logi(bootloader_dev->dev_log, MODULE_NAME ":In Flashless boot,"
1779 " waiting for its completion\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001780
1781
1782exit_err:
Krishna Kondaa7af6062011-09-01 18:34:38 -07001783 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":free "
1784 "sdioc_boot_sw_header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785 kfree(bootloader_dev->sdioc_boot_sw_header);
1786 bootloader_dev->sdioc_boot_sw_header = NULL;
1787 bootloader_dev = NULL;
1788
1789 return ret;
1790}
1791
1792
1793/**
1794 * Read SDIO-Client software header
1795 *
1796 */
1797static int read_sdioc_software_header(struct sdio_al_device *sdio_al_dev,
1798 struct peer_sdioc_sw_header *header)
1799{
1800 int ret;
1801 int i;
1802 int test_version = 0;
1803 int sdioc_test_version = 0;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001804 struct sdio_func *func1 = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001805
1806 pr_debug(MODULE_NAME ":reading sdioc sw header.\n");
1807
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001808 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001809 return -ENODEV;
1810
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001811 func1 = sdio_al_dev->card->sdio_func[0];
1812
1813 ret = sdio_memcpy_fromio(func1, header,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001814 SDIOC_SW_HEADER_ADDR, sizeof(*header));
1815 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001816 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
1817 "sdioc sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001818 goto exit_err;
1819 }
1820
1821 if (header->signature == (u32)PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001822 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW "
1823 "unittest signature. 0x%x\n",
1824 header->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001825 sdio_al->unittest_mode = true;
1826 /* Verify test code compatibility with the modem */
1827 sdioc_test_version = (header->version & 0xFF00) >> 8;
1828 test_version = sdio_al->pdata->peer_sdioc_version_minor >> 8;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001829 if (test_version != sdioc_test_version) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001830 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1831 ": HOST(0x%x) and CLIENT(0x%x) "
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001832 "testing VERSION don't match\n",
Krishna Kondaa7af6062011-09-01 18:34:38 -07001833 test_version,
1834 sdioc_test_version);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001835 msleep(500);
1836 BUG();
1837 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001838 }
1839
1840 if ((header->signature != (u32) PEER_SDIOC_SW_MAILBOX_SIGNATURE) &&
1841 (header->signature != (u32) PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001842 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW "
1843 "invalid signature. 0x%x\n", header->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001844 goto exit_err;
1845 }
1846 /* Upper byte has to be equal - no backward compatibility for unequal */
1847 sdio_al->sdioc_major = header->version >> 16;
1848 if (sdio_al->pdata->allow_sdioc_version_major_2) {
1849 if ((sdio_al->sdioc_major !=
1850 sdio_al->pdata->peer_sdioc_version_major) &&
1851 (sdio_al->sdioc_major != PEER_SDIOC_OLD_VERSION_MAJOR)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001852 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1853 ": HOST(0x%x) and CLIENT(0x%x) "
1854 "SDIO_AL VERSION don't match\n",
1855 ((sdio_al->pdata->peer_sdioc_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001856 sdio_al->pdata->peer_sdioc_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001857 header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001858 goto exit_err;
1859 }
1860 } else {
1861 if (sdio_al->sdioc_major !=
1862 sdio_al->pdata->peer_sdioc_version_major) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001863 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1864 ": HOST(0x%x) and CLIENT(0x%x) "
1865 "SDIO_AL VERSION don't match\n",
1866 ((sdio_al->pdata->peer_sdioc_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001867 sdio_al->pdata->peer_sdioc_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001868 header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001869 goto exit_err;
1870 }
1871 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001872 sdio_al_dev->ch_close_supported = (header->version & 0x000F) >=
1873 (sdio_al->pdata->peer_sdioc_version_minor & 0xF);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001874
Krishna Kondaa7af6062011-09-01 18:34:38 -07001875 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW version 0x%x,"
1876 " sdio_al major 0x%x minor 0x%x\n", header->version,
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001877 sdio_al->sdioc_major,
1878 sdio_al->pdata->peer_sdioc_version_minor);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001879
1880 sdio_al_dev->flashless_boot_on = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001881 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1882 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1883
1884 /* Set default values */
1885 ch->read_threshold = DEFAULT_READ_THRESHOLD;
1886 ch->write_threshold = DEFAULT_WRITE_THRESHOLD;
1887 ch->min_write_avail = DEFAULT_MIN_WRITE_THRESHOLD;
1888 ch->is_packet_mode = true;
1889 ch->peer_tx_buf_size = DEFAULT_PEER_TX_BUF_SIZE;
1890 ch->poll_delay_msec = 0;
1891
1892 ch->num = i;
1893
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001894 ch->func = sdio_al_dev->card->sdio_func[ch->num+1];
1895 ch->rx_pipe_index = ch->num*2;
1896 ch->tx_pipe_index = ch->num*2+1;
1897
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001898 memset(ch->name, 0, sizeof(ch->name));
1899
1900 if (header->channel_names[i][0]) {
1901 memcpy(ch->name, SDIO_PREFIX,
1902 strlen(SDIO_PREFIX));
1903 memcpy(ch->name + strlen(SDIO_PREFIX),
1904 header->channel_names[i],
1905 PEER_CHANNEL_NAME_SIZE);
1906
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001907 ch->state = SDIO_CHANNEL_STATE_IDLE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001908 ch->sdio_al_dev = sdio_al_dev;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001909 } else {
1910 ch->state = SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001911 }
1912
Krishna Kondaa7af6062011-09-01 18:34:38 -07001913 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":Channel=%s, "
1914 "state=%d\n", ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001915 }
1916
1917 return 0;
1918
1919exit_err:
1920 sdio_al_get_into_err_state(sdio_al_dev);
1921 memset(header, 0, sizeof(*header));
1922
1923 return -EIO;
1924}
1925
1926/**
1927 * Read SDIO-Client channel configuration
1928 *
1929 */
1930static int read_sdioc_channel_config(struct sdio_channel *ch)
1931{
1932 int ret;
1933 struct peer_sdioc_sw_mailbox *sw_mailbox = NULL;
1934 struct peer_sdioc_channel_config *ch_config = NULL;
1935 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
1936
1937 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001938 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
1939 " for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001940 return -EINVAL;
1941 }
1942
1943 if (sdio_al_dev->sdioc_sw_header->version == 0)
1944 return -1;
1945
1946 pr_debug(MODULE_NAME ":reading sw mailbox %s channel.\n", ch->name);
1947
1948 sw_mailbox = kzalloc(sizeof(*sw_mailbox), GFP_KERNEL);
1949 if (sw_mailbox == NULL)
1950 return -ENOMEM;
1951
1952 ret = sdio_memcpy_fromio(ch->func, sw_mailbox,
1953 SDIOC_SW_MAILBOX_ADDR, sizeof(*sw_mailbox));
1954 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001955 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
1956 "sw mailbox.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001957 goto exit_err;
1958 }
1959
1960 ch_config = &sw_mailbox->ch_config[ch->num];
1961 memcpy(&ch->ch_config, ch_config,
1962 sizeof(struct peer_sdioc_channel_config));
1963
1964 if (!ch_config->is_ready) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001965 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sw mailbox "
1966 "channel not ready.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001967 goto exit_err;
1968 }
1969
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001970 /* Aggregation up to 90% of the maximum size */
1971 ch->read_threshold = (ch_config->max_rx_threshold * 9) / 10;
1972 /* Threshold on 50% of the maximum size , sdioc uses double-buffer */
1973 ch->write_threshold = (ch_config->max_tx_threshold * 5) / 10;
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001974 ch->threshold_change_cnt = ch->ch_config.max_rx_threshold -
1975 ch->read_threshold + THRESHOLD_CHANGE_EXTRA_BYTES;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001976
1977 ch->def_read_threshold = ch->read_threshold;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001978 ch->is_packet_mode = ch_config->is_packet_mode;
1979 if (!ch->is_packet_mode) {
1980 ch->poll_delay_msec = DEFAULT_POLL_DELAY_NOPACKET_MSEC;
1981 ch->min_write_avail = DEFAULT_MIN_WRITE_THRESHOLD_STREAMING;
1982 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001983 /* The max_packet_size is set by the modem in version 3 and on */
1984 if (sdio_al->sdioc_major > PEER_SDIOC_OLD_VERSION_MAJOR)
1985 ch->min_write_avail = ch_config->max_packet_size;
1986
1987 if (ch->min_write_avail > ch->write_threshold)
1988 ch->min_write_avail = ch->write_threshold;
1989
Maya Erez7ad06d82011-10-02 15:47:57 +02001990 CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":ch %s "
Krishna Kondaa7af6062011-09-01 18:34:38 -07001991 "read_threshold=%d, write_threshold=%d,"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001992 " min_write_avail=%d, max_rx_threshold=%d,"
1993 " max_tx_threshold=%d\n", ch->name, ch->read_threshold,
1994 ch->write_threshold, ch->min_write_avail,
1995 ch_config->max_rx_threshold,
1996 ch_config->max_tx_threshold);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001997
1998 ch->peer_tx_buf_size = ch_config->tx_buf_size;
1999
2000 kfree(sw_mailbox);
2001
2002 return 0;
2003
2004exit_err:
Krishna Kondaa7af6062011-09-01 18:34:38 -07002005 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":Reading SW Mailbox "
2006 "error.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002007 kfree(sw_mailbox);
2008
2009 return -1;
2010}
2011
2012
2013/**
2014 * Enable/Disable EOT interrupt of a pipe.
2015 *
2016 */
2017static int enable_eot_interrupt(struct sdio_al_device *sdio_al_dev,
2018 int pipe_index, int enable)
2019{
2020 int ret = 0;
2021 struct sdio_func *func1;
2022 u32 mask;
2023 u32 pipe_mask;
2024 u32 addr;
2025
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002026 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002027 return -ENODEV;
2028 func1 = sdio_al_dev->card->sdio_func[0];
2029
2030 if (pipe_index < 8) {
2031 addr = PIPES_0_7_IRQ_MASK_ADDR;
2032 pipe_mask = (1<<pipe_index);
2033 } else {
2034 addr = PIPES_8_15_IRQ_MASK_ADDR;
2035 pipe_mask = (1<<(pipe_index-8));
2036 }
2037
2038 mask = sdio_readl(func1, addr, &ret);
2039 if (ret) {
2040 pr_debug(MODULE_NAME ":enable_eot_interrupt fail\n");
2041 goto exit_err;
2042 }
2043
2044 if (enable)
2045 mask &= (~pipe_mask); /* 0 = enable */
2046 else
2047 mask |= (pipe_mask); /* 1 = disable */
2048
2049 sdio_writel(func1, mask, addr, &ret);
2050
2051exit_err:
2052 return ret;
2053}
2054
2055
2056/**
2057 * Enable/Disable mask interrupt of a function.
2058 *
2059 */
2060static int enable_mask_irq(struct sdio_al_device *sdio_al_dev,
2061 int func_num, int enable, u8 bit_offset)
2062{
2063 int ret = 0;
2064 struct sdio_func *func1 = NULL;
2065 u32 mask = 0;
2066 u32 func_mask = 0;
2067 u32 addr = 0;
2068 u32 offset = 0;
2069
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002070 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002071 return -ENODEV;
2072 func1 = sdio_al_dev->card->sdio_func[0];
2073
2074 if (func_num < 4) {
2075 addr = FUNC_1_4_MASK_IRQ_ADDR;
2076 offset = func_num * 8 + bit_offset;
2077 } else {
2078 addr = FUNC_5_7_MASK_IRQ_ADDR;
2079 offset = (func_num - 4) * 8 + bit_offset;
2080 }
2081
2082 func_mask = 1<<offset;
2083
2084 mask = sdio_readl(func1, addr, &ret);
2085 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002086 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2087 "enable_mask_irq fail\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002088 goto exit_err;
2089 }
2090
2091 if (enable)
2092 mask &= (~func_mask); /* 0 = enable */
2093 else
2094 mask |= (func_mask); /* 1 = disable */
2095
2096 pr_debug(MODULE_NAME ":enable_mask_irq, writing mask = 0x%x\n", mask);
2097
2098 sdio_writel(func1, mask, addr, &ret);
2099
2100exit_err:
2101 return ret;
2102}
2103
2104/**
2105 * Enable/Disable Threshold interrupt of a pipe.
2106 *
2107 */
2108static int enable_threshold_interrupt(struct sdio_al_device *sdio_al_dev,
2109 int pipe_index, int enable)
2110{
2111 int ret = 0;
2112 struct sdio_func *func1;
2113 u32 mask;
2114 u32 pipe_mask;
2115 u32 addr;
2116
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002117 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002118 return -ENODEV;
2119 func1 = sdio_al_dev->card->sdio_func[0];
2120
2121 if (pipe_index < 8) {
2122 addr = PIPES_0_7_IRQ_MASK_ADDR;
2123 pipe_mask = (1<<pipe_index);
2124 } else {
2125 addr = PIPES_8_15_IRQ_MASK_ADDR;
2126 pipe_mask = (1<<(pipe_index-8));
2127 }
2128
2129 mask = sdio_readl(func1, addr, &ret);
2130 if (ret) {
2131 pr_debug(MODULE_NAME ":enable_threshold_interrupt fail\n");
2132 goto exit_err;
2133 }
2134
2135 pipe_mask = pipe_mask<<8; /* Threshold bits 8..15 */
2136 if (enable)
2137 mask &= (~pipe_mask); /* 0 = enable */
2138 else
2139 mask |= (pipe_mask); /* 1 = disable */
2140
2141 sdio_writel(func1, mask, addr, &ret);
2142
2143exit_err:
2144 return ret;
2145}
2146
2147/**
2148 * Set the threshold to trigger interrupt from SDIO-Card on
2149 * pipe available bytes.
2150 *
2151 */
2152static int set_pipe_threshold(struct sdio_al_device *sdio_al_dev,
2153 int pipe_index, int threshold)
2154{
2155 int ret = 0;
2156 struct sdio_func *func1;
2157
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002158 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002159 return -ENODEV;
2160 func1 = sdio_al_dev->card->sdio_func[0];
2161
2162 sdio_writel(func1, threshold,
2163 PIPES_THRESHOLD_ADDR+pipe_index*4, &ret);
2164 if (ret)
Krishna Kondaa7af6062011-09-01 18:34:38 -07002165 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2166 "set_pipe_threshold err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002167
2168 return ret;
2169}
2170
2171/**
2172 * Enable func w/ retries
2173 *
2174 */
2175static int sdio_al_enable_func_retry(struct sdio_func *func, const char *name)
2176{
2177 int ret, i;
2178 for (i = 0; i < 200; i++) {
2179 ret = sdio_enable_func(func);
2180 if (ret) {
2181 pr_debug(MODULE_NAME ":retry enable %s func#%d "
2182 "ret=%d\n",
2183 name, func->num, ret);
2184 msleep(10);
2185 } else
2186 break;
2187 }
2188
2189 return ret;
2190}
2191
2192/**
2193 * Open Channel
2194 *
2195 * 1. Init Channel Context.
2196 * 2. Init the Channel SDIO-Function.
2197 * 3. Init the Channel Pipes on Mailbox.
2198 */
2199static int open_channel(struct sdio_channel *ch)
2200{
2201 int ret = 0;
2202 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
2203
2204 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002205 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL "
2206 "sdio_al_dev for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002207 return -EINVAL;
2208 }
2209
2210 /* Init channel Context */
2211 /** Func#1 is reserved for mailbox */
2212 ch->func = sdio_al_dev->card->sdio_func[ch->num+1];
2213 ch->rx_pipe_index = ch->num*2;
2214 ch->tx_pipe_index = ch->num*2+1;
2215 ch->signature = SDIO_AL_SIGNATURE;
2216
2217 ch->total_rx_bytes = 0;
2218 ch->total_tx_bytes = 0;
2219
2220 ch->write_avail = 0;
2221 ch->read_avail = 0;
2222 ch->rx_pending_bytes = 0;
2223
2224 mutex_init(&ch->ch_lock);
2225
2226 pr_debug(MODULE_NAME ":open_channel %s func#%d\n",
2227 ch->name, ch->func->num);
2228
2229 INIT_LIST_HEAD(&(ch->rx_size_list_head));
2230
2231 /* Init SDIO Function */
2232 ret = sdio_al_enable_func_retry(ch->func, ch->name);
2233 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002234 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2235 "sdio_enable_func() err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002236 goto exit_err;
2237 }
2238
2239 /* Note: Patch Func CIS tuple issue */
2240 ret = sdio_set_block_size(ch->func, SDIO_AL_BLOCK_SIZE);
2241 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002242 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2243 "sdio_set_block_size()failed, err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002244 goto exit_err;
2245 }
2246
2247 ch->func->max_blksize = SDIO_AL_BLOCK_SIZE;
2248
2249 sdio_set_drvdata(ch->func, ch);
2250
2251 /* Get channel parameters from the peer SDIO-Client */
2252 read_sdioc_channel_config(ch);
2253
2254 /* Set Pipes Threshold on Mailbox */
2255 ret = set_pipe_threshold(sdio_al_dev,
2256 ch->rx_pipe_index, ch->read_threshold);
2257 if (ret)
2258 goto exit_err;
2259 ret = set_pipe_threshold(sdio_al_dev,
2260 ch->tx_pipe_index, ch->write_threshold);
2261 if (ret)
2262 goto exit_err;
2263
2264 /* Set flag before interrupts are enabled to allow notify */
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002265 ch->state = SDIO_CHANNEL_STATE_OPEN;
2266 pr_debug(MODULE_NAME ":channel %s is in OPEN state now\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002267
2268 sdio_al_dev->poll_delay_msec = get_min_poll_time_msec(sdio_al_dev);
2269
2270 /* lpm mechanism lives under the assumption there is always a timer */
2271 /* Check if need to start the timer */
2272 if ((sdio_al_dev->poll_delay_msec) &&
2273 (sdio_al_dev->is_timer_initialized == false)) {
2274
2275 init_timer(&sdio_al_dev->timer);
2276 sdio_al_dev->timer.data = (unsigned long) sdio_al_dev;
2277 sdio_al_dev->timer.function = sdio_al_timer_handler;
2278 sdio_al_dev->timer.expires = jiffies +
2279 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2280 add_timer(&sdio_al_dev->timer);
2281 sdio_al_dev->is_timer_initialized = true;
2282 }
2283
2284 /* Enable Pipes Interrupts */
2285 enable_eot_interrupt(sdio_al_dev, ch->rx_pipe_index, true);
2286 enable_eot_interrupt(sdio_al_dev, ch->tx_pipe_index, true);
2287
2288 enable_threshold_interrupt(sdio_al_dev, ch->rx_pipe_index, true);
2289 enable_threshold_interrupt(sdio_al_dev, ch->tx_pipe_index, true);
2290
2291exit_err:
2292
2293 return ret;
2294}
2295
2296/**
2297 * Ask the worker to read the mailbox.
2298 */
2299static void ask_reading_mailbox(struct sdio_al_device *sdio_al_dev)
2300{
2301 if (!sdio_al_dev->ask_mbox) {
2302 pr_debug(MODULE_NAME ":ask_reading_mailbox for card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002303 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002304 sdio_al_dev->ask_mbox = true;
2305 wake_up(&sdio_al_dev->wait_mbox);
2306 }
2307}
2308
2309/**
2310 * Start the timer
2311 */
2312static void start_timer(struct sdio_al_device *sdio_al_dev)
2313{
2314 if ((sdio_al_dev->poll_delay_msec) &&
2315 (sdio_al_dev->state == CARD_INSERTED)) {
2316 sdio_al_dev->timer.expires = jiffies +
2317 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2318 add_timer(&sdio_al_dev->timer);
2319 }
2320}
2321
2322/**
2323 * Restart(postpone) the already working timer
2324 */
2325static void restart_timer(struct sdio_al_device *sdio_al_dev)
2326{
2327 if ((sdio_al_dev->poll_delay_msec) &&
2328 (sdio_al_dev->state == CARD_INSERTED)) {
2329 ulong expires = jiffies +
2330 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2331 mod_timer(&sdio_al_dev->timer, expires);
2332 }
2333}
2334
2335/**
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002336 * Stop and delete the timer
2337 */
2338static void stop_and_del_timer(struct sdio_al_device *sdio_al_dev)
2339{
2340 if (sdio_al_dev->is_timer_initialized) {
2341 sdio_al_dev->poll_delay_msec = 0;
2342 del_timer_sync(&sdio_al_dev->timer);
2343 }
2344}
2345
2346/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002347 * Do the wakup sequence.
2348 * This function should be called after claiming the host!
2349 * The caller is responsible for releasing the host.
2350 *
2351 * Wake up sequence
2352 * 1. Get lock
2353 * 2. Enable wake up function if needed
2354 * 3. Mark NOT OK to sleep and write it
2355 * 4. Restore default thresholds
2356 * 5. Start the mailbox and inactivity timer again
2357 */
2358static int sdio_al_wake_up(struct sdio_al_device *sdio_al_dev,
Maya Erez7b1ebd22011-08-20 20:53:24 +03002359 u32 not_from_int, struct sdio_channel *ch)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002360{
Maya Erez8ed0a9a2011-07-19 14:46:53 +03002361 int ret = 0;
Maya Erez86cebda2011-10-11 11:13:40 +02002362 struct sdio_func *wk_func = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002363 unsigned long time_to_wait;
Maya Erez86cebda2011-10-11 11:13:40 +02002364 struct mmc_host *host = sdio_al_dev->host;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002365
2366 if (sdio_al_dev->is_err) {
2367 SDIO_AL_ERR(__func__);
2368 return -ENODEV;
2369 }
2370
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002371 if (!sdio_al_dev->is_ok_to_sleep) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002372 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":card %d "
2373 "already awake, no need to wake up\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002374 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002375 return 0;
2376 }
Maya Erez7b1ebd22011-08-20 20:53:24 +03002377
2378 /* Wake up sequence */
2379 if (not_from_int) {
2380 if (ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002381 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up"
2382 " card %d (not by interrupt), ch %s",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002383 sdio_al_dev->host->index,
Krishna Kondaa7af6062011-09-01 18:34:38 -07002384 ch->name);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002385 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002386 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up"
2387 " card %d (not by interrupt)",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002388 sdio_al_dev->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002389 }
2390 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002391 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up card "
2392 "%d by interrupt",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002393 sdio_al_dev->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002394 sdio_al_dev->print_after_interrupt = 1;
2395 }
2396
Yaniv Gardi3e327762011-07-27 11:11:04 +03002397 sdio_al_vote_for_sleep(sdio_al_dev, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002398
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002399 msmsdcc_lpm_disable(host);
Maya Erez86cebda2011-10-11 11:13:40 +02002400 msmsdcc_set_pwrsave(host, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002401 /* Poll the GPIO */
2402 time_to_wait = jiffies + msecs_to_jiffies(1000);
2403 while (time_before(jiffies, time_to_wait)) {
2404 if (sdio_al->pdata->get_mdm2ap_status())
2405 break;
2406 udelay(TIME_TO_WAIT_US);
2407 }
Yaniv Gardi3e327762011-07-27 11:11:04 +03002408
Maya Erez7b1ebd22011-08-20 20:53:24 +03002409 pr_debug(MODULE_NAME ":GPIO mdm2ap_status=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002410 sdio_al->pdata->get_mdm2ap_status());
2411
2412 /* Here get_mdm2ap_status() returning 0 is not an error condition */
2413 if (sdio_al->pdata->get_mdm2ap_status() == 0)
Krishna Kondaa7af6062011-09-01 18:34:38 -07002414 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": "
2415 "get_mdm2ap_status() is 0\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002416
2417 /* Enable Wake up Function */
Maya Erez86cebda2011-10-11 11:13:40 +02002418 if (!sdio_al_dev->card ||
2419 !sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1]) {
2420 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2421 ": NULL card or wk_func\n");
2422 return -ENODEV;
2423 }
2424 wk_func = sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002425 ret = sdio_al_enable_func_retry(wk_func, "wakeup func");
2426 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002427 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2428 "sdio_enable_func() err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002429 goto error_exit;
2430 }
2431 /* Mark NOT OK_TOSLEEP */
2432 sdio_al_dev->is_ok_to_sleep = 0;
2433 ret = write_lpm_info(sdio_al_dev);
2434 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002435 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2436 "write_lpm_info() failed, err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002437 sdio_al_dev->is_ok_to_sleep = 1;
2438 sdio_disable_func(wk_func);
2439 goto error_exit;
2440 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002441 sdio_disable_func(wk_func);
2442
2443 /* Start the timer again*/
2444 restart_inactive_time(sdio_al_dev);
2445 sdio_al_dev->poll_delay_msec = get_min_poll_time_msec(sdio_al_dev);
2446 start_timer(sdio_al_dev);
2447
Krishna Kondaa7af6062011-09-01 18:34:38 -07002448 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME "Finished Wake up sequence"
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002449 " for card %d", sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002450
Maya Erez86cebda2011-10-11 11:13:40 +02002451 msmsdcc_set_pwrsave(host, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002452 pr_debug(MODULE_NAME ":Turn clock off\n");
2453
2454 return ret;
2455error_exit:
2456 sdio_al_vote_for_sleep(sdio_al_dev, 1);
Maya Erez86cebda2011-10-11 11:13:40 +02002457 msmsdcc_set_pwrsave(host, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002458 WARN_ON(ret);
2459 sdio_al_get_into_err_state(sdio_al_dev);
2460 return ret;
2461}
2462
2463
2464/**
2465 * SDIO Function Interrupt handler.
2466 *
2467 * Interrupt shall be triggered by SDIO-Client when:
2468 * 1. End-Of-Transfer (EOT) detected in packet mode.
2469 * 2. Bytes-available reached the threshold.
2470 *
2471 * Reading the mailbox clears the EOT/Threshold interrupt
2472 * source.
2473 * The interrupt source should be cleared before this ISR
2474 * returns. This ISR is called from IRQ Thread and not
2475 * interrupt, so it may sleep.
2476 *
2477 */
2478static void sdio_func_irq(struct sdio_func *func)
2479{
2480 struct sdio_al_device *sdio_al_dev = sdio_get_drvdata(func);
2481
2482 pr_debug(MODULE_NAME ":start %s.\n", __func__);
2483
2484 if (sdio_al_dev == NULL) {
Maya Erez86cebda2011-10-11 11:13:40 +02002485 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL device");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002486 return;
2487 }
2488
2489 if (sdio_al_dev->is_ok_to_sleep)
Maya Erez7b1ebd22011-08-20 20:53:24 +03002490 sdio_al_wake_up(sdio_al_dev, 0, NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002491 else
2492 restart_timer(sdio_al_dev);
2493
2494 read_mailbox(sdio_al_dev, true);
2495
2496 pr_debug(MODULE_NAME ":end %s.\n", __func__);
2497}
2498
2499/**
2500 * Timer Expire Handler
2501 *
2502 */
2503static void sdio_al_timer_handler(unsigned long data)
2504{
2505 struct sdio_al_device *sdio_al_dev = (struct sdio_al_device *)data;
2506 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002507 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": NULL "
2508 "sdio_al_dev for data %lu\n", data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002509 return;
2510 }
2511 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002512 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": sdio_al_dev "
2513 "is in invalid state %d\n", sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002514 return;
2515 }
2516 pr_debug(MODULE_NAME " Timer Expired\n");
2517
2518 ask_reading_mailbox(sdio_al_dev);
2519
2520 restart_timer(sdio_al_dev);
2521}
2522
2523/**
2524 * Driver Setup.
2525 *
2526 */
2527static int sdio_al_setup(struct sdio_al_device *sdio_al_dev)
2528{
2529 int ret = 0;
2530 struct mmc_card *card = sdio_al_dev->card;
2531 struct sdio_func *func1 = NULL;
2532 int i = 0;
2533 int fn = 0;
2534
Maya Erez86cebda2011-10-11 11:13:40 +02002535 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002536 return -ENODEV;
Maya Erez86cebda2011-10-11 11:13:40 +02002537 func1 = card->sdio_func[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002538
Krishna Kondaa7af6062011-09-01 18:34:38 -07002539 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_setup for "
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002540 "card %d\n", sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002541
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002542 ret = sdio_al->pdata->config_mdm2ap_status(1);
2543 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002544 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME "Could not "
2545 "request GPIO\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002546 return ret;
2547 }
2548
2549 INIT_WORK(&sdio_al_dev->sdio_al_work.work, worker);
2550 /* disable all pipes interrupts before claim irq.
2551 since all are enabled by default. */
2552 for (i = 0 ; i < SDIO_AL_MAX_PIPES; i++) {
2553 enable_eot_interrupt(sdio_al_dev, i, false);
2554 enable_threshold_interrupt(sdio_al_dev, i, false);
2555 }
2556
2557 /* Disable all SDIO Functions before claim irq. */
2558 for (fn = 1 ; fn <= card->sdio_funcs; fn++)
2559 sdio_disable_func(card->sdio_func[fn-1]);
2560
2561 sdio_set_drvdata(func1, sdio_al_dev);
Krishna Kondaa7af6062011-09-01 18:34:38 -07002562 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":claim IRQ for card "
Maya Erez86cebda2011-10-11 11:13:40 +02002563 "%d\n", sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002564
2565 ret = sdio_claim_irq(func1, sdio_func_irq);
2566 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002567 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to claim"
2568 " IRQ for card %d\n",
Maya Erez86cebda2011-10-11 11:13:40 +02002569 sdio_al_dev->host->index);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002570 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002571 }
2572
2573 sdio_al_dev->is_ready = true;
2574
2575 /* Start worker before interrupt might happen */
2576 queue_work(sdio_al_dev->workqueue, &sdio_al_dev->sdio_al_work.work);
2577
2578 start_inactive_time(sdio_al_dev);
2579
2580 pr_debug(MODULE_NAME ":Ready.\n");
2581
2582 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002583}
2584
2585/**
2586 * Driver Tear-Down.
2587 *
2588 */
2589static void sdio_al_tear_down(void)
2590{
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002591 int i, j;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002592 struct sdio_al_device *sdio_al_dev = NULL;
2593 struct sdio_func *func1;
2594
2595 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
2596 if (sdio_al->devices[i] == NULL)
2597 continue;
2598 sdio_al_dev = sdio_al->devices[i];
2599
2600 if (sdio_al_dev->is_ready) {
2601 sdio_al_dev->is_ready = false; /* Flag worker to exit */
2602 sdio_al_dev->ask_mbox = false;
2603 ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
2604 /* allow gracefully exit of the worker thread */
2605 msleep(100);
2606
2607 flush_workqueue(sdio_al_dev->workqueue);
2608 destroy_workqueue(sdio_al_dev->workqueue);
2609
2610 sdio_al_vote_for_sleep(sdio_al_dev, 1);
2611
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002612 if (!sdio_al_claim_mutex_and_verify_dev(sdio_al_dev,
2613 __func__)) {
2614 if (!sdio_al_dev->card ||
2615 !sdio_al_dev->card->sdio_func[0]) {
2616 sdio_al_loge(sdio_al_dev->dev_log,
2617 MODULE_NAME
2618 ": %s: Invalid func1",
2619 __func__);
2620 return;
2621 }
2622 func1 = sdio_al_dev->card->sdio_func[0];
2623 sdio_release_irq(func1);
2624 sdio_disable_func(func1);
2625 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002626 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002627 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002628
2629 for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++)
2630 sdio_al_dev->channel[j].signature = 0x0;
2631 sdio_al_dev->signature = 0;
2632
2633 kfree(sdio_al_dev->sdioc_sw_header);
2634 kfree(sdio_al_dev->mailbox);
2635 kfree(sdio_al_dev->rx_flush_buf);
2636 kfree(sdio_al_dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002637 }
2638
2639 sdio_al->pdata->config_mdm2ap_status(0);
2640}
2641
2642/**
2643 * Find channel by name.
2644 *
2645 */
2646static struct sdio_channel *find_channel_by_name(const char *name)
2647{
2648 struct sdio_channel *ch = NULL;
2649 int i, j;
2650 struct sdio_al_device *sdio_al_dev = NULL;
2651
2652 for (j = 0; j < MAX_NUM_OF_SDIO_DEVICES; ++j) {
2653 if (sdio_al->devices[j] == NULL)
2654 continue;
2655 sdio_al_dev = sdio_al->devices[j];
2656 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002657 if (sdio_al_dev->channel[i].state ==
2658 SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002659 continue;
2660 if (strcmp(sdio_al_dev->channel[i].name, name) == 0) {
2661 ch = &sdio_al_dev->channel[i];
2662 break;
2663 }
2664 }
2665 if (ch != NULL)
2666 break;
2667 }
2668
2669 return ch;
2670}
2671
2672/**
2673 * Find the minimal poll time.
2674 *
2675 */
2676static int get_min_poll_time_msec(struct sdio_al_device *sdio_sl_dev)
2677{
2678 int i;
2679 int poll_delay_msec = 0x0FFFFFFF;
2680
2681 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++)
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002682 if ((sdio_sl_dev->channel[i].state ==
2683 SDIO_CHANNEL_STATE_OPEN) &&
2684 (sdio_sl_dev->channel[i].poll_delay_msec > 0) &&
2685 (sdio_sl_dev->channel[i].poll_delay_msec < poll_delay_msec))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002686 poll_delay_msec =
2687 sdio_sl_dev->channel[i].poll_delay_msec;
2688
2689 if (poll_delay_msec == 0x0FFFFFFF)
2690 poll_delay_msec = SDIO_AL_POLL_TIME_NO_STREAMING;
2691
2692 pr_debug(MODULE_NAME ":poll delay time is %d msec\n", poll_delay_msec);
2693
2694 return poll_delay_msec;
2695}
2696
2697/**
2698 * Open SDIO Channel.
2699 *
2700 * Enable the channel.
2701 * Set the channel context.
2702 * Trigger reading the mailbox to check available bytes.
2703 *
2704 */
2705int sdio_open(const char *name, struct sdio_channel **ret_ch, void *priv,
2706 void (*notify)(void *priv, unsigned ch_event))
2707{
2708 int ret = 0;
2709 struct sdio_channel *ch = NULL;
2710 struct sdio_al_device *sdio_al_dev = NULL;
2711
2712 *ret_ch = NULL; /* default */
2713
2714 ch = find_channel_by_name(name);
2715 if (ch == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002716 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":Can't find "
2717 "channel name %s\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002718 return -EINVAL;
2719 }
2720
2721 sdio_al_dev = ch->sdio_al_dev;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002722 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002723 return -ENODEV;
2724
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002725 if ((ch->state != SDIO_CHANNEL_STATE_IDLE) &&
2726 (ch->state != SDIO_CHANNEL_STATE_CLOSED)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002727 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Wrong ch %s "
2728 "state %d\n", name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002729 ret = -EPERM;
2730 goto exit_err;
2731 }
2732
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002733 if (sdio_al_dev->is_err) {
2734 SDIO_AL_ERR(__func__);
2735 ret = -ENODEV;
2736 goto exit_err;
2737 }
2738
Maya Erez7b1ebd22011-08-20 20:53:24 +03002739 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002740 if (ret)
2741 goto exit_err;
2742
2743 ch->notify = notify;
2744 ch->priv = priv;
2745
2746 /* Note: Set caller returned context before interrupts are enabled */
2747 *ret_ch = ch;
2748
2749 ret = open_channel(ch);
2750 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002751 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_open %s "
2752 "err=%d\n", name, -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002753 goto exit_err;
2754 }
2755
Maya Erez7ad06d82011-10-02 15:47:57 +02002756 CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":sdio_open %s "
2757 "completed OK\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002758 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
2759 if (sdio_al->sdioc_major == PEER_SDIOC_OLD_VERSION_MAJOR) {
2760 if (!ch->is_packet_mode) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002761 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME
2762 ":setting channel %s as "
2763 "lpm_chan\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002764 sdio_al_dev->lpm_chan = ch->num;
2765 }
2766 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002767 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": "
2768 "setting channel %s as lpm_chan\n",
2769 name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002770 sdio_al_dev->lpm_chan = ch->num;
2771 }
2772 }
2773
2774exit_err:
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002775 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002776 return ret;
2777}
2778EXPORT_SYMBOL(sdio_open);
2779
2780/**
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002781 * Request peer operation
2782 * note: sanity checks of parameters done by caller
2783 * called under bus locked
2784 */
2785static int peer_set_operation(u32 opcode,
2786 struct sdio_al_device *sdio_al_dev,
2787 struct sdio_channel *ch)
2788{
2789 int ret;
2790 int offset;
2791 struct sdio_func *wk_func;
2792 u32 peer_operation;
2793 int loop_count = 0;
2794
2795 wk_func = sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
2796 if (!wk_func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002797 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: NULL "
2798 "wakeup func:%d\n", __func__,
2799 SDIO_AL_WAKEUP_FUNC);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002800 ret = -ENODEV;
2801 goto exit;
2802 }
2803 /* calculate offset of peer_operation field in sw mailbox struct */
2804 offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config) +
2805 sizeof(struct peer_sdioc_channel_config) * ch->num +
2806 offsetof(struct peer_sdioc_channel_config, peer_operation);
2807
Maya Erez7b1ebd22011-08-20 20:53:24 +03002808 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002809 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002810 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
2811 "wake up\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002812 goto exit;
2813 }
2814 /* request operation from MDM peer */
2815 peer_operation = PEER_OPERATION(opcode, PEER_OP_STATE_INIT);
2816 ret = sdio_memcpy_toio(ch->func, SDIOC_SW_MAILBOX_ADDR+offset,
2817 &peer_operation, sizeof(u32));
2818 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002819 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
2820 "request close operation\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002821 goto exit;
2822 }
2823 ret = sdio_al_enable_func_retry(wk_func, "wk_func");
2824 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002825 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to enable"
2826 " Func#%d\n", wk_func->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002827 goto exit;
2828 }
2829 pr_debug(MODULE_NAME ":%s: wk_func enabled on ch %s\n",
2830 __func__, ch->name);
2831 /* send "start" operation to MDM */
2832 peer_operation = PEER_OPERATION(opcode, PEER_OP_STATE_START);
2833 ret = sdio_memcpy_toio(ch->func, SDIOC_SW_MAILBOX_ADDR+offset,
2834 &peer_operation, sizeof(u32));
2835 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002836 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
2837 "send start close operation\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002838 goto exit;
2839 }
2840 ret = sdio_disable_func(wk_func);
2841 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002842 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
2843 "disable Func#%d\n", wk_func->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002844 goto exit;
2845 }
2846 /* poll for peer operation ack */
2847 while (peer_operation != 0) {
2848 ret = sdio_memcpy_fromio(ch->func,
2849 &peer_operation,
2850 SDIOC_SW_MAILBOX_ADDR+offset,
2851 sizeof(u32));
2852 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002853 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2854 ":failed to request ack on close"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002855 " operation, loop_count = %d\n",
2856 loop_count);
2857 goto exit;
2858 }
2859 loop_count++;
2860 if (loop_count > 10) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002861 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2862 "peer_operation=0x%x wait loop"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002863 " %d on ch %s\n", __func__,
2864 peer_operation, loop_count, ch->name);
2865 }
2866 }
2867exit:
2868 return ret;
2869}
2870
Konstantin Dorfman52890522011-10-05 11:03:19 +02002871static int channel_close(struct sdio_channel *ch, int flush_flag)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002872{
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002873 int ret;
2874 struct sdio_al_device *sdio_al_dev = NULL;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002875 int flush_len;
2876 ulong flush_expires;
2877
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002878 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002879 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
2880 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002881 return -ENODEV;
2882 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002883
2884 if (!ch->func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002885 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: NULL func"
2886 " on channel:%d\n", __func__, ch->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002887 return -ENODEV;
2888 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002889
2890 sdio_al_dev = ch->sdio_al_dev;
2891 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
2892 return -ENODEV;
2893
2894 if (!sdio_al_dev->ch_close_supported) {
2895 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: Not "
2896 "supported by mdm, ch %s\n",
2897 __func__, ch->name);
2898 ret = -ENOTSUPP;
2899 goto error_exit;
2900 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002901
2902 if (sdio_al_dev->is_err) {
2903 SDIO_AL_ERR(__func__);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002904 ret = -ENODEV;
2905 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002906 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02002907 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
2908 sdio_al_loge(sdio_al_dev->dev_log,
2909 MODULE_NAME ":%s: ch %s is not in "
2910 "open state (%d)\n",
2911 __func__, ch->name, ch->state);
2912 ret = -ENODEV;
2913 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002914 }
2915 ch->state = SDIO_CHANNEL_STATE_CLOSING;
2916 ret = peer_set_operation(PEER_OP_CODE_CLOSE, sdio_al_dev, ch);
2917 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002918 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2919 "peer_set_operation() failed: %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002920 __func__, ret);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002921 ret = -ENODEV;
2922 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002923 }
2924 /* udate poll time for opened channels */
2925 if (ch->poll_delay_msec > 0) {
2926 sdio_al_dev->poll_delay_msec =
2927 get_min_poll_time_msec(sdio_al_dev);
2928 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002929 sdio_al_release_mutex(ch->sdio_al_dev, __func__);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002930
2931 flush_expires = jiffies +
2932 msecs_to_jiffies(SDIO_CLOSE_FLUSH_TIMEOUT_MSEC);
2933 /* flush rx packets of the channel */
Konstantin Dorfman52890522011-10-05 11:03:19 +02002934 if (flush_flag) {
2935 do {
2936 while (ch->read_avail > 0) {
2937 flush_len = ch->read_avail;
2938 ret = sdio_read_internal(ch,
2939 sdio_al_dev->rx_flush_buf,
2940 flush_len);
2941 if (ret) {
2942 sdio_al_loge(&sdio_al->gen_log,
2943 MODULE_NAME ":%s sdio_read"
2944 " failed: %d, ch %s\n",
2945 __func__, ret,
2946 ch->name);
2947 return ret;
2948 }
Yaniv Gardic4663632011-08-31 19:55:38 +03002949
Konstantin Dorfman52890522011-10-05 11:03:19 +02002950 if (time_after(jiffies, flush_expires) != 0) {
2951 sdio_al_loge(&sdio_al->gen_log,
2952 MODULE_NAME ":%s flush rx "
2953 "packets timeout: ch %s\n",
Krishna Kondaa7af6062011-09-01 18:34:38 -07002954 __func__, ch->name);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002955 sdio_al_get_into_err_state(sdio_al_dev);
2956 return -EBUSY;
2957 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002958 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02002959 msleep(100);
2960 if (ch->signature != SDIO_AL_SIGNATURE) {
2961 sdio_al_loge(&sdio_al->gen_log,
2962 MODULE_NAME ":%s: after sleep,"
2963 " invalid signature"
2964 " 0x%x\n", __func__,
2965 ch->signature);
2966 return -ENODEV;
2967 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002968 if (sdio_al_claim_mutex_and_verify_dev(ch->sdio_al_dev,
2969 __func__))
Konstantin Dorfman52890522011-10-05 11:03:19 +02002970 return -ENODEV;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002971
Konstantin Dorfman52890522011-10-05 11:03:19 +02002972 ret = read_mailbox(sdio_al_dev, false);
2973 if (ret) {
2974 sdio_al_loge(&sdio_al->gen_log,
2975 MODULE_NAME ":%s: failed to"
2976 " read mailbox", __func__);
2977 goto error_exit;
2978 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002979 sdio_al_release_mutex(ch->sdio_al_dev, __func__);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002980 } while (ch->read_avail > 0);
2981 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002982 if (sdio_al_claim_mutex_and_verify_dev(ch->sdio_al_dev,
2983 __func__))
2984 return -ENODEV;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002985 /* disable function to be able to open the channel again */
2986 ret = sdio_disable_func(ch->func);
2987 if (ret) {
Konstantin Dorfman52890522011-10-05 11:03:19 +02002988 sdio_al_loge(&sdio_al->gen_log,
2989 MODULE_NAME ":Fail to disable Func#%d\n",
2990 ch->func->num);
2991 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002992 }
2993 ch->state = SDIO_CHANNEL_STATE_CLOSED;
Maya Erez7ad06d82011-10-02 15:47:57 +02002994 CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":%s: Ch %s closed "
2995 "successfully\n", __func__, ch->name);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002996
2997error_exit:
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002998 sdio_al_release_mutex(ch->sdio_al_dev, __func__);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002999
3000 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003001}
Konstantin Dorfman52890522011-10-05 11:03:19 +02003002
3003/**
3004 * Close SDIO Channel.
3005 *
3006 */
3007int sdio_close(struct sdio_channel *ch)
3008{
3009 return channel_close(ch, true);
3010}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003011EXPORT_SYMBOL(sdio_close);
3012
3013/**
3014 * Get the number of available bytes to write.
3015 *
3016 */
3017int sdio_write_avail(struct sdio_channel *ch)
3018{
3019 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003020 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3021 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003022 return -ENODEV;
3023 }
3024 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003025 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
3026 "Invalid signature 0x%x\n", __func__,
3027 ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003028 return -ENODEV;
3029 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003030 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003031 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
3032 "channel %s state is not open (%d)\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003033 __func__, ch->name, ch->state);
3034 return -ENODEV;
3035 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003036 pr_debug(MODULE_NAME ":sdio_write_avail %s 0x%x\n",
3037 ch->name, ch->write_avail);
3038
3039 return ch->write_avail;
3040}
3041EXPORT_SYMBOL(sdio_write_avail);
3042
3043/**
3044 * Get the number of available bytes to read.
3045 *
3046 */
3047int sdio_read_avail(struct sdio_channel *ch)
3048{
3049 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003050 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3051 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003052 return -ENODEV;
3053 }
3054 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003055 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
3056 "Invalid signature 0x%x\n", __func__,
3057 ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003058 return -ENODEV;
3059 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003060 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003061 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
3062 "channel %s state is not open (%d)\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003063 __func__, ch->name, ch->state);
3064 return -ENODEV;
3065 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003066 pr_debug(MODULE_NAME ":sdio_read_avail %s 0x%x\n",
3067 ch->name, ch->read_avail);
3068
3069 return ch->read_avail;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003070}
3071EXPORT_SYMBOL(sdio_read_avail);
3072
Maya Erez5795e0d2011-09-12 20:20:06 +03003073static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len)
3074{
3075 int ret = 0;
3076 struct sdio_al_device *sdio_al_dev = NULL;
3077
3078 if (!ch) {
Konstantin Dorfman52890522011-10-05 11:03:19 +02003079 sdio_al_loge(ch->sdio_al_dev->dev_log,
3080 MODULE_NAME ":%s: NULL channel\n", __func__);
Maya Erez5795e0d2011-09-12 20:20:06 +03003081 return -ENODEV;
3082 }
3083
3084 sdio_al_dev = ch->sdio_al_dev;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003085 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
3086 return -ENODEV;
Maya Erez5795e0d2011-09-12 20:20:06 +03003087
3088 ret = sdio_memcpy_fromio(ch->func, sdio_al_dev->rx_flush_buf,
3089 PIPE_RX_FIFO_ADDR, len);
3090
3091 if (ret) {
Konstantin Dorfman52890522011-10-05 11:03:19 +02003092 sdio_al_loge(ch->sdio_al_dev->dev_log,
3093 MODULE_NAME ":ch %s: %s err=%d, len=%d\n",
Maya Erez5795e0d2011-09-12 20:20:06 +03003094 ch->name, __func__, -ret, len);
3095 sdio_al_dev->is_err = true;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003096 sdio_al_release_mutex(sdio_al_dev, __func__);
Maya Erez5795e0d2011-09-12 20:20:06 +03003097 return ret;
3098 }
3099
3100 restart_inactive_time(sdio_al_dev);
3101
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003102 sdio_al_release_mutex(sdio_al_dev, __func__);
Maya Erez5795e0d2011-09-12 20:20:06 +03003103
3104 return 0;
3105}
3106
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003107/**
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003108 * Internal read from SDIO Channel.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003109 *
3110 * Reading from the pipe will trigger interrupt if there are
3111 * other pending packets on the SDIO-Client.
3112 *
3113 */
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003114static int sdio_read_internal(struct sdio_channel *ch, void *data, int len)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003115{
3116 int ret = 0;
3117 struct sdio_al_device *sdio_al_dev = NULL;
3118
3119 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003120 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3121 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003122 return -ENODEV;
3123 }
3124 if (!data) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003125 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
3126 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003127 return -ENODEV;
3128 }
3129 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003130 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
3131 " to read 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003132 return -EINVAL;
3133 }
3134
3135 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003136 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
3137 "signature 0x%x\n", __func__, ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003138 return -ENODEV;
3139 }
3140
3141 sdio_al_dev = ch->sdio_al_dev;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003142 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003143 return -ENODEV;
3144
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003145 if (sdio_al_dev->is_err) {
3146 SDIO_AL_ERR(__func__);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003147 ret = -ENODEV;
3148 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003149 }
3150
3151 /* lpm policy says we can't go to sleep when we have pending rx data,
3152 so either we had rx interrupt and woken up, or we never went to
3153 sleep */
3154 if (sdio_al_dev->is_ok_to_sleep) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003155 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: called "
3156 "when is_ok_to_sleep is set for ch %s, len=%d,"
3157 " last_any_read_avail=%d, last_read_avail=%d, "
3158 "last_old_read_avail=%d", __func__, ch->name,
3159 len, ch->statistics.last_any_read_avail,
3160 ch->statistics.last_read_avail,
3161 ch->statistics.last_old_read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003162 }
3163 BUG_ON(sdio_al_dev->is_ok_to_sleep);
3164
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003165 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
3166 (ch->state != SDIO_CHANNEL_STATE_CLOSING)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003167 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s wrong "
3168 "channel %s state %d\n",
3169 __func__, ch->name, ch->state);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003170 ret = -EINVAL;
3171 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003172 }
3173
Krishna Kondaa7af6062011-09-01 18:34:38 -07003174 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s read %d "
3175 "avail %d.\n", ch->name, len, ch->read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003176
3177 restart_inactive_time(sdio_al_dev);
3178
3179 if ((ch->is_packet_mode) && (len != ch->read_avail)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003180 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_read ch "
3181 "%s len != read_avail\n", ch->name);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003182 ret = -EINVAL;
3183 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003184 }
3185
3186 if (len > ch->read_avail) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003187 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
3188 "reading more bytes (%d) than the avail(%d).\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003189 ch->name, len, ch->read_avail);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003190 ret = -ENOMEM;
3191 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003192 }
3193
3194 ret = sdio_memcpy_fromio(ch->func, data, PIPE_RX_FIFO_ADDR, len);
3195
3196 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003197 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ch %s: "
3198 "sdio_read err=%d, len=%d, read_avail=%d, "
3199 "last_read_avail=%d, last_old_read_avail=%d\n",
Maya Erezd9cc2292011-08-04 09:20:31 +03003200 ch->name, -ret, len, ch->read_avail,
3201 ch->statistics.last_read_avail,
3202 ch->statistics.last_old_read_avail);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003203 sdio_al_get_into_err_state(sdio_al_dev);
3204 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003205 }
3206
3207 ch->statistics.total_read_times++;
3208
3209 /* Remove handled packet from the list regardless if ret is ok */
3210 if (ch->is_packet_mode)
3211 remove_handled_rx_packet(ch);
3212 else
3213 ch->read_avail -= len;
3214
3215 ch->total_rx_bytes += len;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003216 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s read %d "
3217 "avail %d total %d.\n", ch->name, len,
3218 ch->read_avail, ch->total_rx_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003219
3220 if ((ch->read_avail == 0) && !(ch->is_packet_mode))
3221 ask_reading_mailbox(sdio_al_dev);
3222
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003223exit:
3224 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003225
3226 return ret;
3227}
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003228
3229/**
3230 * Read from SDIO Channel.
3231 *
3232 * Reading from the pipe will trigger interrupt if there are
3233 * other pending packets on the SDIO-Client.
3234 *
3235 */
3236int sdio_read(struct sdio_channel *ch, void *data, int len)
3237{
3238 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003239 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3240 "channel\n", __func__);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003241 return -ENODEV;
3242 }
3243 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003244 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
3245 "Invalid signature 0x%x\n", __func__, ch->signature);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003246 return -ENODEV;
3247 }
3248 if (ch->state == SDIO_CHANNEL_STATE_OPEN) {
3249 return sdio_read_internal(ch, data, len);
3250 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003251 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME
3252 ":%s: Invalid channel %s state %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003253 __func__, ch->name, ch->state);
3254 }
3255 return -ENODEV;
3256}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003257EXPORT_SYMBOL(sdio_read);
3258
3259/**
3260 * Write to SDIO Channel.
3261 *
3262 */
3263int sdio_write(struct sdio_channel *ch, const void *data, int len)
3264{
3265 int ret = 0;
3266 struct sdio_al_device *sdio_al_dev = NULL;
3267
3268 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003269 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3270 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003271 return -ENODEV;
3272 }
3273 if (!data) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003274 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
3275 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003276 return -ENODEV;
3277 }
3278 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003279 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
3280 " to write 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003281 return -EINVAL;
3282 }
3283
3284 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003285 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
3286 "signature 0x%x\n", __func__, ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003287 return -ENODEV;
3288 }
3289
3290 sdio_al_dev = ch->sdio_al_dev;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003291 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003292 return -ENODEV;
3293
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003294 WARN_ON(len > ch->write_avail);
3295
3296 if (sdio_al_dev->is_err) {
3297 SDIO_AL_ERR(__func__);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003298 ret = -ENODEV;
3299 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003300 }
3301
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003302 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003303 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":writing to "
3304 "closed channel %s\n", ch->name);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003305 ret = -EINVAL;
3306 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003307 }
3308
3309 if (sdio_al_dev->is_ok_to_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03003310 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003311 if (ret)
3312 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003313 } else {
3314 restart_inactive_time(sdio_al_dev);
3315 }
3316
Krishna Kondaa7af6062011-09-01 18:34:38 -07003317 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s write %d "
3318 "avail %d.\n", ch->name, len, ch->write_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003319
3320 if (len > ch->write_avail) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003321 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
3322 "write more bytes (%d) than available %d.\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003323 ch->name, len, ch->write_avail);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003324 ret = -ENOMEM;
3325 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003326 }
3327
3328 ret = sdio_ch_write(ch, data, len);
3329 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003330 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_write "
3331 "on channel %s err=%d\n", ch->name, -ret);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003332 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003333 }
3334
3335 ch->total_tx_bytes += len;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003336 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s write %d "
3337 "avail %d total %d.\n", ch->name, len,
3338 ch->write_avail, ch->total_tx_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003339
3340 /* Round up to whole buffer size */
3341 len = ROUND_UP(len, ch->peer_tx_buf_size);
3342 /* Protect from wraparound */
3343 len = min(len, (int) ch->write_avail);
3344 ch->write_avail -= len;
3345
3346 if (ch->write_avail < ch->min_write_avail)
3347 ask_reading_mailbox(sdio_al_dev);
3348
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003349exit:
3350 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003351
3352 return ret;
3353}
3354EXPORT_SYMBOL(sdio_write);
3355
3356static int __devinit msm_sdio_al_probe(struct platform_device *pdev)
3357{
3358 if (!sdio_al) {
3359 pr_err(MODULE_NAME ": %s: NULL sdio_al\n", __func__);
3360 return -ENODEV;
3361 }
3362
3363 sdio_al->pdata = pdev->dev.platform_data;
3364 return 0;
3365}
3366
3367static int __devexit msm_sdio_al_remove(struct platform_device *pdev)
3368{
3369 return 0;
3370}
3371
Konstantin Dorfman52890522011-10-05 11:03:19 +02003372static void sdio_al_close_all_channels(struct sdio_al_device *sdio_al_dev)
Maya Erez6862b142011-08-22 09:07:07 +03003373{
Konstantin Dorfman52890522011-10-05 11:03:19 +02003374 int j;
Maya Erez6862b142011-08-22 09:07:07 +03003375 int ret;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003376 struct sdio_channel *ch = NULL;
Maya Erez6862b142011-08-22 09:07:07 +03003377
Konstantin Dorfman52890522011-10-05 11:03:19 +02003378 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
Maya Erez6862b142011-08-22 09:07:07 +03003379
Konstantin Dorfman52890522011-10-05 11:03:19 +02003380 if (!sdio_al_dev) {
3381 sdio_al_loge(sdio_al_dev->dev_log,
3382 MODULE_NAME ": %s: NULL device", __func__);
3383 return;
3384 }
3385 for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++) {
3386 ch = &sdio_al_dev->channel[j];
3387
3388 if (ch->state == SDIO_CHANNEL_STATE_OPEN) {
3389 sdio_al_loge(sdio_al_dev->dev_log,
3390 MODULE_NAME ": %s: Call to sdio_close() for"
3391 " ch %s\n", __func__, ch->name);
3392 ret = channel_close(ch, false);
3393 if (ret) {
3394 sdio_al_loge(sdio_al_dev->dev_log,
3395 MODULE_NAME ": %s: failed sdio_close()"
3396 " for ch %s (%d)\n",
3397 __func__, ch->name, ret);
3398 }
3399 } else {
3400 pr_debug(MODULE_NAME ": %s: skip sdio_close() ch %s"
3401 " (state=%d)\n", __func__,
3402 ch->name, ch->state);
Maya Erez6862b142011-08-22 09:07:07 +03003403 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02003404 }
3405}
3406
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003407static void sdio_al_invalidate_sdio_clients(struct sdio_al_device *sdio_al_dev,
3408 struct platform_device **pdev_arr)
3409{
3410 int j;
3411
3412 pr_debug(MODULE_NAME ": %s: Notifying SDIO clients for card %d",
3413 __func__, sdio_al_dev->host->index);
3414 for (j = 0; j < SDIO_AL_MAX_CHANNELS; ++j) {
3415 if (sdio_al_dev->channel[j].state ==
3416 SDIO_CHANNEL_STATE_INVALID)
3417 continue;
3418 pdev_arr[j] = sdio_al_dev->channel[j].pdev;
3419 sdio_al_dev->channel[j].signature = 0x0;
3420 sdio_al_dev->channel[j].state =
3421 SDIO_CHANNEL_STATE_INVALID;
3422 }
3423}
3424
3425static void sdio_al_modem_reset_operations(struct sdio_al_device
Konstantin Dorfman52890522011-10-05 11:03:19 +02003426 *sdio_al_dev)
3427{
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003428 int ret = 0;
3429 struct sdio_func *func1 = NULL;
3430 struct platform_device *pdev_arr[SDIO_AL_MAX_CHANNELS];
3431 int j;
3432
Konstantin Dorfman52890522011-10-05 11:03:19 +02003433 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
3434
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003435 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Konstantin Dorfman52890522011-10-05 11:03:19 +02003436 return;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003437
3438 if (!sdio_al_dev->card || !sdio_al_dev->card->sdio_func[0]) {
3439 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: "
3440 "NULL func1 for card %d", __func__,
3441 sdio_al_dev->host->index);
3442 goto exit_err;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003443 }
Maya Erez6862b142011-08-22 09:07:07 +03003444
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003445 if (sdio_al_dev->state == CARD_REMOVED) {
3446 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: "
3447 "card %d is already removed", __func__,
3448 sdio_al_dev->host->index);
3449 goto exit_err;
3450 }
3451
3452 if (sdio_al_dev->state == MODEM_RESTART) {
3453 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: "
3454 "card %d was already notified for modem reset",
3455 __func__, sdio_al_dev->host->index);
3456 goto exit_err;
3457 }
3458
3459 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: Set the "
3460 "state to MODEM_RESTART for card %d",
3461 __func__, sdio_al_dev->host->index);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003462 sdio_al_dev->state = MODEM_RESTART;
3463 sdio_al_dev->is_ready = false;
Maya Erez6862b142011-08-22 09:07:07 +03003464
Konstantin Dorfman52890522011-10-05 11:03:19 +02003465 /* Stop mailbox timer */
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003466 stop_and_del_timer(sdio_al_dev);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003467
Konstantin Dorfman52890522011-10-05 11:03:19 +02003468 if ((sdio_al_dev->is_ok_to_sleep) &&
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003469 (!sdio_al_dev->is_err)) {
3470 pr_debug(MODULE_NAME ": %s: wakeup modem for "
3471 "card %d", __func__,
3472 sdio_al_dev->host->index);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003473 ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
Maya Erez6862b142011-08-22 09:07:07 +03003474 }
3475
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003476 if (!ret && (!sdio_al_dev->is_err)) {
3477 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME
3478 ": %s: sdio_release_irq for card %d",
3479 __func__,
3480 sdio_al_dev->host->index);
3481 func1 = sdio_al_dev->card->sdio_func[0];
3482 sdio_release_irq(sdio_al_dev->card->sdio_func[0]);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003483 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003484
3485 memset(pdev_arr, 0, sizeof(pdev_arr));
3486 sdio_al_invalidate_sdio_clients(sdio_al_dev, pdev_arr);
3487
3488 sdio_al_release_mutex(sdio_al_dev, __func__);
3489
3490 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Notifying SDIO "
3491 "clients for card %d",
3492 __func__, sdio_al_dev->host->index);
3493 for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++) {
3494 if (!pdev_arr[j])
3495 continue;
3496 platform_device_unregister(pdev_arr[j]);
3497 }
3498 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Finished Notifying "
3499 "SDIO clients for card %d",
3500 __func__, sdio_al_dev->host->index);
3501
3502 return;
3503
3504exit_err:
3505 sdio_al_release_mutex(sdio_al_dev, __func__);
3506 return;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003507}
3508
3509#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
3510static void sdio_al_reset(void)
3511{
3512 int i;
3513 struct sdio_al_device *sdio_al_dev;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003514
3515 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
3516
Maya Erez6862b142011-08-22 09:07:07 +03003517 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
Maya Erez6862b142011-08-22 09:07:07 +03003518 if (sdio_al->devices[i] == NULL) {
3519 pr_debug(MODULE_NAME ": %s: NULL device in index %d",
Konstantin Dorfman52890522011-10-05 11:03:19 +02003520 __func__, i);
Maya Erez6862b142011-08-22 09:07:07 +03003521 continue;
3522 }
3523 sdio_al_dev = sdio_al->devices[i];
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003524 sdio_al_modem_reset_operations(sdio_al->devices[i]);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003525 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003526
3527 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s completed", __func__);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003528}
3529#endif
Maya Erez6862b142011-08-22 09:07:07 +03003530
Konstantin Dorfman52890522011-10-05 11:03:19 +02003531static void msm_sdio_al_shutdown(struct platform_device *pdev)
3532{
3533 int i;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003534 struct sdio_al_device *sdio_al_dev;
3535
3536 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME
3537 "Initiating msm_sdio_al_shutdown...");
3538
3539 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
3540 if (sdio_al->devices[i] == NULL) {
3541 pr_debug(MODULE_NAME ": %s: NULL device in index %d",
3542 __func__, i);
3543 continue;
Maya Erez8afd5642011-08-24 15:57:06 +03003544 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02003545 sdio_al_dev = sdio_al->devices[i];
Maya Erez6862b142011-08-22 09:07:07 +03003546
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003547 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
3548 return;
Maya Erez6862b142011-08-22 09:07:07 +03003549
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003550 if (sdio_al_dev->ch_close_supported)
3551 sdio_al_close_all_channels(sdio_al_dev);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003552
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003553 sdio_al_release_mutex(sdio_al_dev, __func__);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003554
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003555 sdio_al_modem_reset_operations(sdio_al_dev);
Maya Erez6862b142011-08-22 09:07:07 +03003556 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07003557 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: "
3558 "msm_sdio_al_shutdown complete.", __func__);
Maya Erez6862b142011-08-22 09:07:07 +03003559}
3560
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003561static struct platform_driver msm_sdio_al_driver = {
3562 .probe = msm_sdio_al_probe,
3563 .remove = __exit_p(msm_sdio_al_remove),
Maya Erez6862b142011-08-22 09:07:07 +03003564 .shutdown = msm_sdio_al_shutdown,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003565 .driver = {
3566 .name = "msm_sdio_al",
3567 },
3568};
3569
3570/**
3571 * Initialize SDIO_AL channels.
3572 *
3573 */
3574static int init_channels(struct sdio_al_device *sdio_al_dev)
3575{
3576 int ret = 0;
3577 int i;
3578
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003579 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003580 return -ENODEV;
3581
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003582 ret = read_sdioc_software_header(sdio_al_dev,
3583 sdio_al_dev->sdioc_sw_header);
3584 if (ret)
3585 goto exit;
3586
3587 ret = sdio_al_setup(sdio_al_dev);
3588 if (ret)
3589 goto exit;
3590
3591 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
3592 int ch_name_size;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003593 if (sdio_al_dev->channel[i].state == SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003594 continue;
3595 if (sdio_al->unittest_mode) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003596 memset(sdio_al_dev->channel[i].ch_test_name, 0,
3597 sizeof(sdio_al_dev->channel[i].ch_test_name));
3598 ch_name_size = strnlen(sdio_al_dev->channel[i].name,
3599 CHANNEL_NAME_SIZE);
3600 strncpy(sdio_al_dev->channel[i].ch_test_name,
3601 sdio_al_dev->channel[i].name,
3602 ch_name_size);
3603 strncat(sdio_al_dev->channel[i].ch_test_name +
3604 ch_name_size,
3605 SDIO_TEST_POSTFIX,
3606 SDIO_TEST_POSTFIX_SIZE);
3607 pr_debug(MODULE_NAME ":pdev.name = %s\n",
3608 sdio_al_dev->channel[i].ch_test_name);
3609 sdio_al_dev->channel[i].pdev = platform_device_alloc(
3610 sdio_al_dev->channel[i].ch_test_name, -1);
3611 } else {
3612 pr_debug(MODULE_NAME ":pdev.name = %s\n",
3613 sdio_al_dev->channel[i].name);
3614 sdio_al_dev->channel[i].pdev = platform_device_alloc(
3615 sdio_al_dev->channel[i].name, -1);
3616 }
3617 if (!sdio_al_dev->channel[i].pdev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003618 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3619 ":NULL platform device for ch %s",
3620 sdio_al_dev->channel[i].name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003621 sdio_al_dev->channel[i].state =
3622 SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003623 continue;
3624 }
3625 ret = platform_device_add(sdio_al_dev->channel[i].pdev);
3626 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003627 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3628 ":platform_device_add failed, "
3629 "ret=%d\n", ret);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003630 sdio_al_dev->channel[i].state =
3631 SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003632 }
3633 }
3634
3635exit:
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003636 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003637 return ret;
3638}
3639
3640/**
3641 * Initialize SDIO_AL channels according to the client setup.
3642 * This function also check if the client is in boot mode and
3643 * flashless boot is required to be activated or the client is
3644 * up and running.
3645 *
3646 */
3647static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev)
3648{
3649 int ret = 0;
3650 struct sdio_func *func1;
3651 int signature = 0;
3652
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003653 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003654 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003655
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003656 if (!sdio_al_dev->card || !sdio_al_dev->card->sdio_func[0]) {
3657 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":NULL card or "
3658 "func1\n");
3659 sdio_al_release_mutex(sdio_al_dev, __func__);
3660 return -ENODEV;
3661 }
3662 func1 = sdio_al_dev->card->sdio_func[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003663
3664 /* Read the header signature to determine the status of the MDM
3665 * SDIO Client
3666 */
3667 signature = sdio_readl(func1, SDIOC_SW_HEADER_ADDR, &ret);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003668 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003669 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003670 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
3671 "signature from sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003672 return ret;
3673 }
3674
3675 switch (signature) {
3676 case PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE:
3677 if (sdio_al_dev == sdio_al->bootloader_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003678 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":setup "
3679 "bootloader on card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003680 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003681 return sdio_al_bootloader_setup();
3682 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003683 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":wait "
3684 "for bootloader completion "
3685 "on card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003686 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003687 return sdio_al_wait_for_bootloader_comp(sdio_al_dev);
3688 }
3689 case PEER_SDIOC_SW_MAILBOX_SIGNATURE:
3690 case PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE:
3691 return init_channels(sdio_al_dev);
3692 default:
Krishna Kondaa7af6062011-09-01 18:34:38 -07003693 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
3694 "signature 0x%x\n", signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003695 return -EINVAL;
3696 }
3697
3698 return 0;
3699}
3700
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003701static void clean_sdio_al_device_data(struct sdio_al_device *sdio_al_dev)
3702{
3703 sdio_al_dev->is_ready = 0;
3704 sdio_al_dev->bootloader_done = 0;
3705 sdio_al_dev->lpm_chan = 0;
3706 sdio_al_dev->is_ok_to_sleep = 0;
3707 sdio_al_dev->inactivity_time = 0;
3708 sdio_al_dev->poll_delay_msec = 0;
3709 sdio_al_dev->is_timer_initialized = 0;
3710 sdio_al_dev->is_err = 0;
3711 sdio_al_dev->is_suspended = 0;
3712 sdio_al_dev->flashless_boot_on = 0;
3713 sdio_al_dev->ch_close_supported = 0;
3714 sdio_al_dev->print_after_interrupt = 0;
3715 memset(sdio_al_dev->sdioc_sw_header, 0,
3716 sizeof(*sdio_al_dev->sdioc_sw_header));
3717 memset(sdio_al_dev->mailbox, 0, sizeof(*sdio_al_dev->mailbox));
3718 memset(sdio_al_dev->rx_flush_buf, 0,
3719 sizeof(*sdio_al_dev->rx_flush_buf));
3720}
3721
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003722/*
3723 * SDIO driver functions
3724 */
3725static int sdio_al_sdio_probe(struct sdio_func *func,
3726 const struct sdio_device_id *sdio_dev_id)
3727{
3728 int ret = 0;
3729 struct sdio_al_device *sdio_al_dev = NULL;
3730 int i;
3731 struct mmc_card *card = NULL;
3732
3733 if (!func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003734 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
3735 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003736 return -ENODEV;
3737 }
3738 card = func->card;
3739
3740 if (!card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003741 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
3742 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003743 return -ENODEV;
3744 }
3745
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003746 if (!card->sdio_func[0]) {
3747 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
3748 "func1\n",
3749 __func__);
3750 return -ENODEV;
3751 }
3752
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003753 if (card->sdio_funcs < SDIO_AL_MAX_FUNCS) {
3754 dev_info(&card->dev,
3755 "SDIO-functions# %d less than expected.\n",
3756 card->sdio_funcs);
3757 return -ENODEV;
3758 }
3759
3760 /* Check if there is already a device for this card */
3761 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
3762 if (sdio_al->devices[i] == NULL)
3763 continue;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003764 if (sdio_al->devices[i]->host == card->host) {
3765 sdio_al_dev = sdio_al->devices[i];
3766 if (sdio_al_dev->state == CARD_INSERTED)
3767 return 0;
3768 clean_sdio_al_device_data(sdio_al_dev);
3769 break;
3770 }
3771 }
3772
3773 if (!sdio_al_dev) {
3774 sdio_al_dev = kzalloc(sizeof(struct sdio_al_device),
3775 GFP_KERNEL);
3776 if (sdio_al_dev == NULL)
3777 return -ENOMEM;
3778
3779 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
3780 if (sdio_al->devices[i] == NULL) {
3781 sdio_al->devices[i] = sdio_al_dev;
3782 sdio_al_dev->dev_log = &sdio_al->device_log[i];
3783 spin_lock_init(&sdio_al_dev->dev_log->log_lock);
3784 #ifdef CONFIG_DEBUG_FS
3785 sdio_al_dbgfs_log[i].data =
3786 sdio_al_dev->dev_log->buffer;
3787 sdio_al_dbgfs_log[i].size =
3788 SDIO_AL_DEBUG_LOG_SIZE;
3789 #endif
3790 break;
3791 }
3792 if (i == MAX_NUM_OF_SDIO_DEVICES) {
3793 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":No space "
3794 "in devices array for the device\n");
3795 return -ENOMEM;
3796 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003797 }
3798
3799 dev_info(&card->dev, "SDIO Card claimed.\n");
3800
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003801 sdio_al_dev->state = CARD_INSERTED;
3802
3803 if (card->host->index == SDIO_BOOTLOADER_CARD_INDEX)
3804 sdio_al->bootloader_dev = sdio_al_dev;
3805
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003806 sdio_al_dev->is_ready = false;
3807
3808 sdio_al_dev->signature = SDIO_AL_SIGNATURE;
3809
3810 sdio_al_dev->is_suspended = 0;
3811 sdio_al_dev->is_timer_initialized = false;
3812
3813 sdio_al_dev->lpm_chan = INVALID_SDIO_CHAN;
3814
3815 sdio_al_dev->card = card;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003816 sdio_al_dev->host = card->host;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003817
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003818 if (!sdio_al_dev->mailbox) {
3819 sdio_al_dev->mailbox = kzalloc(sizeof(struct sdio_mailbox),
3820 GFP_KERNEL);
3821 if (sdio_al_dev->mailbox == NULL)
3822 return -ENOMEM;
3823 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003824
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003825 if (!sdio_al_dev->sdioc_sw_header) {
3826 sdio_al_dev->sdioc_sw_header
3827 = kzalloc(sizeof(*sdio_al_dev->sdioc_sw_header),
3828 GFP_KERNEL);
3829 if (sdio_al_dev->sdioc_sw_header == NULL)
3830 return -ENOMEM;
3831 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003832
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003833 if (!sdio_al_dev->rx_flush_buf) {
3834 sdio_al_dev->rx_flush_buf = kzalloc(RX_FLUSH_BUFFER_SIZE,
3835 GFP_KERNEL);
3836 if (sdio_al_dev->rx_flush_buf == NULL) {
3837 sdio_al_loge(&sdio_al->gen_log,
3838 MODULE_NAME ":Fail to allocate "
3839 "rx_flush_buf for card %d\n",
3840 card->host->index);
3841 return -ENOMEM;
3842 }
Maya Erez5795e0d2011-09-12 20:20:06 +03003843 }
3844
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003845 sdio_al_dev->timer.data = (unsigned long)sdio_al_dev;
3846
3847 wake_lock_init(&sdio_al_dev->wake_lock, WAKE_LOCK_SUSPEND, MODULE_NAME);
3848 /* Don't allow sleep until all required clients register */
3849 sdio_al_vote_for_sleep(sdio_al_dev, 0);
3850
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003851 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
3852 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003853
3854 /* Init Func#1 */
Yaniv Gardi9a952d92011-09-06 13:46:30 +03003855 ret = sdio_al_enable_func_retry(card->sdio_func[0], "Init Func#1");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003856 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003857 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
3858 "enable Func#%d\n", card->sdio_func[0]->num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003859 goto exit;
3860 }
3861
3862 /* Patch Func CIS tuple issue */
3863 ret = sdio_set_block_size(card->sdio_func[0], SDIO_AL_BLOCK_SIZE);
3864 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003865 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to set "
3866 "block size, Func#%d\n", card->sdio_func[0]->num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003867 goto exit;
3868 }
3869 sdio_al_dev->card->sdio_func[0]->max_blksize = SDIO_AL_BLOCK_SIZE;
3870
3871 sdio_al_dev->workqueue = create_singlethread_workqueue("sdio_al_wq");
3872 sdio_al_dev->sdio_al_work.sdio_al_dev = sdio_al_dev;
3873 init_waitqueue_head(&sdio_al_dev->wait_mbox);
3874
3875 ret = sdio_al_client_setup(sdio_al_dev);
3876
3877exit:
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003878 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003879 return ret;
3880}
3881
3882static void sdio_al_sdio_remove(struct sdio_func *func)
3883{
3884 struct sdio_al_device *sdio_al_dev = NULL;
3885 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003886 struct mmc_card *card = NULL;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003887 struct platform_device *pdev_arr[SDIO_AL_MAX_CHANNELS];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003888
3889 if (!func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003890 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
3891 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003892 return;
3893 }
3894 card = func->card;
3895
3896 if (!card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003897 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
3898 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003899 return;
3900 }
3901
3902 /* Find the sdio_al_device of this card */
3903 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
3904 if (sdio_al->devices[i] == NULL)
3905 continue;
3906 if (sdio_al->devices[i]->card == card) {
3907 sdio_al_dev = sdio_al->devices[i];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003908 break;
3909 }
3910 }
3911 if (sdio_al_dev == NULL) {
3912 pr_debug(MODULE_NAME ":%s :NULL sdio_al_dev for card %d\n",
3913 __func__, card->host->index);
3914 return;
3915 }
3916
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003917 if (sdio_al_claim_mutex(sdio_al_dev, __func__))
3918 return;
3919
3920 if (sdio_al_dev->state == CARD_REMOVED) {
3921 sdio_al_release_mutex(sdio_al_dev, __func__);
3922 return;
3923 }
3924
3925 if (!card->sdio_func[0]) {
3926 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
3927 "func1\n", __func__);
3928 sdio_al_release_mutex(sdio_al_dev, __func__);
3929 return;
3930 }
3931
Krishna Kondaa7af6062011-09-01 18:34:38 -07003932 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s for card %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003933 __func__, card->host->index);
3934
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003935 sdio_al_dev->state = CARD_REMOVED;
3936
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003937 memset(pdev_arr, 0, sizeof(pdev_arr));
3938 sdio_al_invalidate_sdio_clients(sdio_al_dev, pdev_arr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003939
Krishna Kondaa7af6062011-09-01 18:34:38 -07003940 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: ask_reading_mailbox "
3941 "for card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003942 sdio_al_dev->is_ready = false; /* Flag worker to exit */
3943 sdio_al_dev->ask_mbox = false;
3944 ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
3945
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003946 stop_and_del_timer(sdio_al_dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003947
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003948 sdio_al_release_mutex(sdio_al_dev, __func__);
3949
3950 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Notifying SDIO "
3951 "clients for card %d",
3952 __func__, sdio_al_dev->host->index);
3953 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
3954 if (!pdev_arr[i])
3955 continue;
3956 platform_device_unregister(pdev_arr[i]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003957 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003958 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Finished Notifying "
3959 "SDIO clients for card %d",
3960 __func__, sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003961
Krishna Kondaa7af6062011-09-01 18:34:38 -07003962 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: vote for sleep for "
3963 "card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003964 sdio_al_vote_for_sleep(sdio_al_dev, 1);
3965
Krishna Kondaa7af6062011-09-01 18:34:38 -07003966 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: flush_workqueue for "
3967 "card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003968 flush_workqueue(sdio_al_dev->workqueue);
3969 destroy_workqueue(sdio_al_dev->workqueue);
3970 wake_lock_destroy(&sdio_al_dev->wake_lock);
3971
Krishna Kondaa7af6062011-09-01 18:34:38 -07003972 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: sdio card %d removed."
3973 "\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003974}
3975
3976static void sdio_print_mailbox(char *prefix_str, struct sdio_mailbox *mailbox)
3977{
3978 int k = 0;
3979 char buf[256];
3980 char buf1[10];
3981
3982 if (!mailbox) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003983 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": mailbox is "
3984 "NULL\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003985 return;
3986 }
3987
Krishna Kondaa7af6062011-09-01 18:34:38 -07003988 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: pipes 0_7: eot=0x%x,"
3989 " thresh=0x%x, overflow=0x%x, "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003990 "underflow=0x%x, mask_thresh=0x%x\n",
3991 prefix_str, mailbox->eot_pipe_0_7,
3992 mailbox->thresh_above_limit_pipe_0_7,
3993 mailbox->overflow_pipe_0_7,
3994 mailbox->underflow_pipe_0_7,
3995 mailbox->mask_thresh_above_limit_pipe_0_7);
3996
3997 memset(buf, 0, sizeof(buf));
3998 strncat(buf, ": bytes_avail:", sizeof(buf));
3999
4000 for (k = 0 ; k < SDIO_AL_ACTIVE_PIPES ; ++k) {
4001 snprintf(buf1, sizeof(buf1), "%d, ",
4002 mailbox->pipe_bytes_avail[k]);
4003 strncat(buf, buf1, sizeof(buf));
4004 }
4005
Krishna Kondaa7af6062011-09-01 18:34:38 -07004006 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME "%s", buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004007}
4008
4009static void sdio_al_print_info(void)
4010{
4011 int i = 0;
4012 int j = 0;
4013 int ret = 0;
4014 struct sdio_mailbox *mailbox = NULL;
4015 struct sdio_mailbox *hw_mailbox = NULL;
4016 struct peer_sdioc_channel_config *ch_config = NULL;
4017 struct sdio_func *func1 = NULL;
4018 struct sdio_func *lpm_func = NULL;
4019 int offset = 0;
4020 int is_ok_to_sleep = 0;
4021 static atomic_t first_time;
4022 char buf[50];
4023
4024 if (atomic_read(&first_time) == 1)
4025 return;
4026
4027 atomic_set(&first_time, 1);
4028
Krishna Kondaa7af6062011-09-01 18:34:38 -07004029 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - SDIO DEBUG INFO\n",
4030 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004031
4032 if (!sdio_al) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004033 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - ERROR - "
4034 "sdio_al is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004035 return;
4036 }
4037
Krishna Kondaa7af6062011-09-01 18:34:38 -07004038 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": GPIO mdm2ap_status=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004039 sdio_al->pdata->get_mdm2ap_status());
4040
4041 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
4042 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
4043
4044 if (sdio_al_dev == NULL) {
4045 continue;
4046 }
4047
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004048 if (!sdio_al_dev->host) {
4049 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Host"
4050 " is NULL\n);");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004051 continue;
4052 }
4053
4054 snprintf(buf, sizeof(buf), "Card#%d: Shadow HW MB",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004055 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004056
4057 /* printing Shadowing HW Mailbox*/
4058 mailbox = sdio_al_dev->mailbox;
4059 sdio_print_mailbox(buf, mailbox);
4060
Krishna Kondaa7af6062011-09-01 18:34:38 -07004061 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004062 "is_ok_to_sleep=%d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004063 sdio_al_dev->host->index,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004064 sdio_al_dev->is_ok_to_sleep);
4065
4066
Krishna Kondaa7af6062011-09-01 18:34:38 -07004067 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004068 "Shadow channels SW MB:",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004069 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004070
4071 /* printing Shadowing SW Mailbox per channel*/
4072 for (i = 0 ; i < SDIO_AL_MAX_CHANNELS ; ++i) {
4073 struct sdio_channel *ch = &sdio_al_dev->channel[i];
4074
4075 if (ch == NULL) {
4076 continue;
4077 }
4078
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03004079 if (ch->state == SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004080 continue;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004081
4082 ch_config = &sdio_al_dev->channel[i].ch_config;
4083
Krishna Kondaa7af6062011-09-01 18:34:38 -07004084 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4085 ": Ch %s: max_rx_thres=0x%x, "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004086 "max_tx_thres=0x%x, tx_buf=0x%x, "
4087 "is_packet_mode=%d, "
4088 "max_packet=0x%x, min_write=0x%x",
4089 ch->name, ch_config->max_rx_threshold,
4090 ch_config->max_tx_threshold,
4091 ch_config->tx_buf_size,
4092 ch_config->is_packet_mode,
4093 ch_config->max_packet_size,
4094 ch->min_write_avail);
4095
Krishna Kondaa7af6062011-09-01 18:34:38 -07004096 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4097 ": total_rx=0x%x, total_tx=0x%x, "
4098 "read_avail=0x%x, write_avail=0x%x, "
4099 "rx_pending=0x%x, num_reads=0x%x, "
4100 "num_notifs=0x%x", ch->total_rx_bytes,
4101 ch->total_tx_bytes, ch->read_avail,
4102 ch->write_avail, ch->rx_pending_bytes,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004103 ch->statistics.total_read_times,
4104 ch->statistics.total_notifs);
4105 } /* end loop over all channels */
4106
4107 } /* end loop over all devices */
4108
4109 /* reading from client and printing is_host_ok_to_sleep per device */
4110 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
4111 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
4112
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004113 if (sdio_al_verify_func1(sdio_al_dev, __func__))
4114 continue;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004115
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004116 if (!sdio_al_dev->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004117 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4118 ": Host is NULL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004119 continue;
4120 }
4121
4122 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004123 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4124 ": %s - for Card#%d, is lpm_chan=="
4125 "INVALID_SDIO_CHAN. continuing...",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004126 __func__, sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004127 continue;
4128 }
4129
4130 offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
4131 sizeof(struct peer_sdioc_channel_config) *
4132 sdio_al_dev->lpm_chan+
4133 offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
4134
4135 lpm_func = sdio_al_dev->card->sdio_func[sdio_al_dev->
4136 lpm_chan+1];
4137 if (!lpm_func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004138 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4139 ": %s - lpm_func is NULL for card#%d"
4140 " continuing...\n", __func__,
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004141 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004142 continue;
4143 }
4144
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004145 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
4146 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004147 ret = sdio_memcpy_fromio(lpm_func,
4148 &is_ok_to_sleep,
4149 SDIOC_SW_MAILBOX_ADDR+offset,
4150 sizeof(int));
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004151 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004152
4153 if (ret)
Krishna Kondaa7af6062011-09-01 18:34:38 -07004154 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4155 ": %s - fail to read "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004156 "is_HOST_ok_to_sleep from mailbox for card %d",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004157 __func__, sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004158 else
Krishna Kondaa7af6062011-09-01 18:34:38 -07004159 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4160 ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004161 "is_HOST_ok_to_sleep=%d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004162 sdio_al_dev->host->index,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004163 is_ok_to_sleep);
4164 }
4165
4166 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
4167 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
4168
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004169 if (!sdio_al_dev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004170 continue;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004171
4172 /* Reading HW Mailbox */
4173 hw_mailbox = sdio_al_dev->mailbox;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004174
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004175 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
4176 return;
4177
4178 if (!sdio_al_dev->card || !sdio_al_dev->card->sdio_func[0]) {
4179 sdio_al_release_mutex(sdio_al_dev, __func__);
4180 return;
4181 }
4182 func1 = sdio_al_dev->card->sdio_func[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004183 ret = sdio_memcpy_fromio(func1, hw_mailbox,
4184 HW_MAILBOX_ADDR, sizeof(*hw_mailbox));
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004185 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004186
4187 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004188 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4189 ": fail to read "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004190 "mailbox for card#%d. "
4191 "continuing...\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004192 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004193 continue;
4194 }
4195
4196 snprintf(buf, sizeof(buf), "Card#%d: Current HW MB",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004197 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004198
4199 /* Printing HW Mailbox */
4200 sdio_print_mailbox(buf, hw_mailbox);
4201 }
4202}
4203
4204static struct sdio_device_id sdio_al_sdioid[] = {
4205 {.class = 0, .vendor = 0x70, .device = 0x2460},
4206 {.class = 0, .vendor = 0x70, .device = 0x0460},
4207 {.class = 0, .vendor = 0x70, .device = 0x23F1},
4208 {.class = 0, .vendor = 0x70, .device = 0x23F0},
4209 {}
4210};
4211
4212static struct sdio_driver sdio_al_sdiofn_driver = {
4213 .name = "sdio_al_sdiofn",
4214 .id_table = sdio_al_sdioid,
4215 .probe = sdio_al_sdio_probe,
4216 .remove = sdio_al_sdio_remove,
4217};
4218
4219#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4220/*
4221 * Callback for notifications from restart mudule.
4222 * This function handles only the BEFORE_RESTART notification.
4223 * Stop all the activity on the card and notify our clients.
4224 */
4225static int sdio_al_subsys_notifier_cb(struct notifier_block *this,
4226 unsigned long notif_type,
4227 void *data)
4228{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004229 if (notif_type != SUBSYS_BEFORE_SHUTDOWN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004230 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: got "
4231 "notification %ld", __func__, notif_type);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004232 return NOTIFY_DONE;
4233 }
4234
Konstantin Dorfman52890522011-10-05 11:03:19 +02004235 sdio_al_reset();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004236 return NOTIFY_OK;
4237}
4238
4239static struct notifier_block sdio_al_nb = {
4240 .notifier_call = sdio_al_subsys_notifier_cb,
4241};
4242#endif
4243
4244/**
4245 * Module Init.
4246 *
4247 * @warn: allocate sdio_al context before registering driver.
4248 *
4249 */
4250static int __init sdio_al_init(void)
4251{
4252 int ret = 0;
4253 int i;
4254
4255 pr_debug(MODULE_NAME ":sdio_al_init\n");
4256
4257 pr_info(MODULE_NAME ":SDIO-AL SW version %s\n",
4258 DRV_VERSION);
4259
4260 sdio_al = kzalloc(sizeof(struct sdio_al), GFP_KERNEL);
4261 if (sdio_al == NULL)
4262 return -ENOMEM;
4263
4264 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
4265 sdio_al->devices[i] = NULL;
4266
4267 sdio_al->unittest_mode = false;
4268
4269 sdio_al->debug.debug_lpm_on = debug_lpm_on;
4270 sdio_al->debug.debug_data_on = debug_data_on;
Maya Erez7ad06d82011-10-02 15:47:57 +02004271 sdio_al->debug.debug_close_on = debug_close_on;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004272
4273#ifdef CONFIG_DEBUG_FS
4274 sdio_al_debugfs_init();
4275#endif
4276
4277
4278#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4279 sdio_al->subsys_notif_handle = subsys_notif_register_notifier(
4280 "external_modem", &sdio_al_nb);
4281#endif
4282
4283 ret = platform_driver_register(&msm_sdio_al_driver);
4284 if (ret) {
4285 pr_err(MODULE_NAME ": platform_driver_register failed: %d\n",
4286 ret);
4287 goto exit;
4288 }
4289
4290 sdio_register_driver(&sdio_al_sdiofn_driver);
Krishna Kondaa7af6062011-09-01 18:34:38 -07004291
4292 spin_lock_init(&sdio_al->gen_log.log_lock);
4293
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004294exit:
4295 if (ret)
4296 kfree(sdio_al);
4297 return ret;
4298}
4299
4300/**
4301 * Module Exit.
4302 *
4303 * Free allocated memory.
4304 * Disable SDIO-Card.
4305 * Unregister driver.
4306 *
4307 */
4308static void __exit sdio_al_exit(void)
4309{
4310 if (sdio_al == NULL)
4311 return;
4312
4313 pr_debug(MODULE_NAME ":sdio_al_exit\n");
4314
4315#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4316 subsys_notif_unregister_notifier(
4317 sdio_al->subsys_notif_handle, &sdio_al_nb);
4318#endif
4319
4320 sdio_al_tear_down();
4321
4322 sdio_unregister_driver(&sdio_al_sdiofn_driver);
4323
4324 kfree(sdio_al);
4325
4326#ifdef CONFIG_DEBUG_FS
4327 sdio_al_debugfs_cleanup();
4328#endif
4329
4330 platform_driver_unregister(&msm_sdio_al_driver);
4331
4332 pr_debug(MODULE_NAME ":sdio_al_exit complete\n");
4333}
4334
4335module_init(sdio_al_init);
4336module_exit(sdio_al_exit);
4337
4338MODULE_LICENSE("GPL v2");
4339MODULE_DESCRIPTION("SDIO Abstraction Layer");
4340MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
4341MODULE_VERSION(DRV_VERSION);
4342