blob: 1a05449ee7bcb3516cdf394e721f64bc54dba2bd [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;
408 struct sdio_mailbox *mailbox;
409 struct sdio_channel channel[SDIO_AL_MAX_CHANNELS];
410
411 struct peer_sdioc_sw_header *sdioc_sw_header;
412 struct peer_sdioc_boot_sw_header *sdioc_boot_sw_header;
413
414 struct workqueue_struct *workqueue;
415 struct sdio_al_work sdio_al_work;
416 struct sdio_al_work boot_work;
417
418 int is_ready;
419
420 wait_queue_head_t wait_mbox;
421 int ask_mbox;
422 int bootloader_done;
423
424 struct wake_lock wake_lock;
425 int lpm_chan;
426 int is_ok_to_sleep;
427 unsigned long inactivity_time;
428
429 struct timer_list timer;
430 u32 poll_delay_msec;
431 int is_timer_initialized;
432
433 int is_err;
434
435 u32 signature;
436
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700437 unsigned int is_suspended;
438
439 int flashless_boot_on;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300440 int ch_close_supported;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700441 int state;
442 int (*lpm_callback)(void *, int);
Maya Erez7b1ebd22011-08-20 20:53:24 +0300443
444 int print_after_interrupt;
Maya Erez5795e0d2011-09-12 20:20:06 +0300445
446 u8 *rx_flush_buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700447};
448
449/*
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300450 * Host operation:
451 * lower 16bits are operation code
452 * upper 16bits are operation state
453 */
454#define PEER_OPERATION(op_code , op_state) ((op_code) | ((op_state) << 16))
455#define GET_PEER_OPERATION_CODE(op) ((op) & 0xffff)
456#define GET_PEER_OPERATION_STATE(op) ((op) >> 16)
457
458enum peer_op_code {
459 PEER_OP_CODE_CLOSE = 1
460};
461
462enum peer_op_state {
463 PEER_OP_STATE_INIT = 0,
464 PEER_OP_STATE_START = 1
465};
466
467
468/*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700469 * On the kernel command line specify
470 * sdio_al.debug_lpm_on=1 to enable the LPM debug messages
471 * By default the LPM debug messages are turned off
472 */
473static int debug_lpm_on;
474module_param(debug_lpm_on, int, 0);
475
476/*
477 * On the kernel command line specify
478 * sdio_al.debug_data_on=1 to enable the DATA debug messages
479 * By default the DATA debug messages are turned off
480 */
481static int debug_data_on;
482module_param(debug_data_on, int, 0);
483
Maya Erez7ad06d82011-10-02 15:47:57 +0200484/*
485 * Enables / disables open close debug messages
486 */
487static int debug_close_on = 1;
488module_param(debug_close_on, int, 0);
489
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700490/** The driver context */
491static struct sdio_al *sdio_al;
492
493/* Static functions declaration */
494static int enable_eot_interrupt(struct sdio_al_device *sdio_al_dev,
495 int pipe_index, int enable);
496static int enable_threshold_interrupt(struct sdio_al_device *sdio_al_dev,
497 int pipe_index, int enable);
498static void sdio_func_irq(struct sdio_func *func);
499static void sdio_al_timer_handler(unsigned long data);
500static int get_min_poll_time_msec(struct sdio_al_device *sdio_al_dev);
501static u32 check_pending_rx_packet(struct sdio_channel *ch, u32 eot);
502static u32 remove_handled_rx_packet(struct sdio_channel *ch);
503static int set_pipe_threshold(struct sdio_al_device *sdio_al_dev,
504 int pipe_index, int threshold);
505static int sdio_al_wake_up(struct sdio_al_device *sdio_al_dev,
Maya Erez7b1ebd22011-08-20 20:53:24 +0300506 u32 not_from_int, struct sdio_channel *ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700507static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev);
508static int enable_mask_irq(struct sdio_al_device *sdio_al_dev,
509 int func_num, int enable, u8 bit_offset);
510static int sdio_al_enable_func_retry(struct sdio_func *func, const char *name);
511static void sdio_al_print_info(void);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300512static int sdio_read_internal(struct sdio_channel *ch, void *data, int len);
Maya Erez5795e0d2011-09-12 20:20:06 +0300513static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700514
515#define SDIO_AL_ERR(func) \
516 do { \
517 printk_once(KERN_ERR MODULE_NAME \
518 ":In Error state, ignore %s\n", \
519 func); \
520 sdio_al_print_info(); \
521 } while (0)
522
523#ifdef CONFIG_DEBUG_FS
524static int debug_info_open(struct inode *inode, struct file *file)
525{
526 file->private_data = inode->i_private;
527 return 0;
528}
529
530static ssize_t debug_info_write(struct file *file,
531 const char __user *buf, size_t count, loff_t *ppos)
532{
533 sdio_al_print_info();
534 return 1;
535}
536
537const struct file_operations debug_info_ops = {
538 .open = debug_info_open,
539 .write = debug_info_write,
540};
541
Krishna Kondaa7af6062011-09-01 18:34:38 -0700542struct debugfs_blob_wrapper sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES + 1];
543
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700544/*
545*
546* Trigger on/off for debug messages
547* for trigger off the data messages debug level use:
548* echo 0 > /sys/kernel/debugfs/sdio_al/debug_data_on
549* for trigger on the data messages debug level use:
550* echo 1 > /sys/kernel/debugfs/sdio_al/debug_data_on
551* for trigger off the lpm messages debug level use:
552* echo 0 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
553* for trigger on the lpm messages debug level use:
554* echo 1 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
555*/
556static int sdio_al_debugfs_init(void)
557{
Krishna Kondaa7af6062011-09-01 18:34:38 -0700558 int i, blob_errs = 0;
559
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700560 sdio_al->debug.sdio_al_debug_root = debugfs_create_dir("sdio_al", NULL);
561 if (!sdio_al->debug.sdio_al_debug_root)
562 return -ENOENT;
563
564 sdio_al->debug.sdio_al_debug_lpm_on = debugfs_create_u8("debug_lpm_on",
565 S_IRUGO | S_IWUGO,
566 sdio_al->debug.sdio_al_debug_root,
567 &sdio_al->debug.debug_lpm_on);
568
569 sdio_al->debug.sdio_al_debug_data_on = debugfs_create_u8(
570 "debug_data_on",
571 S_IRUGO | S_IWUGO,
572 sdio_al->debug.sdio_al_debug_root,
573 &sdio_al->debug.debug_data_on);
574
Maya Erez7ad06d82011-10-02 15:47:57 +0200575 sdio_al->debug.sdio_al_debug_close_on = debugfs_create_u8(
576 "debug_close_on",
577 S_IRUGO | S_IWUGO,
578 sdio_al->debug.sdio_al_debug_root,
579 &sdio_al->debug.debug_close_on);
580
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700581 sdio_al->debug.sdio_al_debug_info = debugfs_create_file(
582 "sdio_debug_info",
583 S_IRUGO | S_IWUGO,
584 sdio_al->debug.sdio_al_debug_root,
585 NULL,
586 &debug_info_ops);
587
Krishna Kondaa7af6062011-09-01 18:34:38 -0700588 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
589 char temp[18];
590
591 scnprintf(temp, 18, "sdio_al_log_dev_%d", i + 1);
592 sdio_al->debug.sdio_al_debug_log_buffers[i] =
593 debugfs_create_blob(temp,
594 S_IRUGO | S_IWUGO,
595 sdio_al->debug.sdio_al_debug_root,
596 &sdio_al_dbgfs_log[i]);
597 }
598
599 sdio_al->debug.sdio_al_debug_log_buffers[MAX_NUM_OF_SDIO_DEVICES] =
600 debugfs_create_blob("sdio_al_gen_log",
601 S_IRUGO | S_IWUGO,
602 sdio_al->debug.sdio_al_debug_root,
603 &sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES]);
604
605 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i) {
606 if (!sdio_al->debug.sdio_al_debug_log_buffers[i]) {
607 pr_err(MODULE_NAME ": Failed to create debugfs buffer"
608 " entry for "
609 "sdio_al->debug.sdio_al_debug_log_buffers[%d]",
610 i);
611 blob_errs = 1;
612 }
613 }
614
615 if (blob_errs) {
616 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i)
617 if (sdio_al->debug.sdio_al_debug_log_buffers[i])
618 debugfs_remove(
619 sdio_al->
620 debug.sdio_al_debug_log_buffers[i]);
621 }
622
623
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700624 if ((!sdio_al->debug.sdio_al_debug_data_on) &&
625 (!sdio_al->debug.sdio_al_debug_lpm_on) &&
Maya Erez7ad06d82011-10-02 15:47:57 +0200626 (!sdio_al->debug.sdio_al_debug_close_on) &&
Krishna Kondaa7af6062011-09-01 18:34:38 -0700627 (!sdio_al->debug.sdio_al_debug_info) &&
628 blob_errs) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700629 debugfs_remove(sdio_al->debug.sdio_al_debug_root);
630 sdio_al->debug.sdio_al_debug_root = NULL;
631 return -ENOENT;
632 }
Krishna Kondaa7af6062011-09-01 18:34:38 -0700633
634 sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES].data =
635 sdio_al->gen_log.buffer;
636 sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES].size =
637 SDIO_AL_DEBUG_LOG_SIZE;
638
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700639 return 0;
640}
641
642static void sdio_al_debugfs_cleanup(void)
643{
Krishna Kondaa7af6062011-09-01 18:34:38 -0700644 int i;
645
646 debugfs_remove(sdio_al->debug.sdio_al_debug_lpm_on);
647 debugfs_remove(sdio_al->debug.sdio_al_debug_data_on);
Maya Erez7ad06d82011-10-02 15:47:57 +0200648 debugfs_remove(sdio_al->debug.sdio_al_debug_close_on);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700649 debugfs_remove(sdio_al->debug.sdio_al_debug_info);
Krishna Kondaa7af6062011-09-01 18:34:38 -0700650
651 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i)
652 debugfs_remove(sdio_al->debug.sdio_al_debug_log_buffers[i]);
653
654 debugfs_remove(sdio_al->debug.sdio_al_debug_root);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700655}
656#endif
657
Krishna Kondaa7af6062011-09-01 18:34:38 -0700658static int sdio_al_log(struct sdio_al_local_log *log, const char *fmt, ...)
659{
660 va_list args;
661 int r;
662 char *tp, *log_buf;
663 unsigned int *log_cur_pos;
664 struct timeval kt;
665 unsigned long flags;
666 static char sdio_al_log_tmp[SDIO_AL_DEBUG_TMP_LOG_SIZE];
667
668 spin_lock_irqsave(&log->log_lock, flags);
669
670 kt = ktime_to_timeval(ktime_get());
671 r = scnprintf(sdio_al_log_tmp, SDIO_AL_DEBUG_TMP_LOG_SIZE,
672 "[%8ld.%6ld] ", kt.tv_sec, kt.tv_usec);
673
674 va_start(args, fmt);
675 r += vscnprintf(&sdio_al_log_tmp[r], (SDIO_AL_DEBUG_TMP_LOG_SIZE - r),
676 fmt, args);
677 va_end(args);
678
679 log_buf = log->buffer;
680 log_cur_pos = &(log->buf_cur_pos);
681
682 for (tp = sdio_al_log_tmp; tp < (sdio_al_log_tmp + r); tp++) {
683 log_buf[(*log_cur_pos)++] = *tp;
684 if ((*log_cur_pos) == SDIO_AL_DEBUG_LOG_SIZE)
685 *log_cur_pos = 0;
686 }
687
688 spin_unlock_irqrestore(&log->log_lock, flags);
689
690 return r;
691}
692
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700693static int sdio_al_verify_func1(struct sdio_al_device *sdio_al_dev,
694 char const *func)
695{
696 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700697 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
698 "sdio_al_dev\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700699 return -ENODEV;
700 }
701 if (!sdio_al_dev->card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700702 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
703 "card\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700704 return -ENODEV;
705 }
706 if (!sdio_al_dev->card->sdio_func[0]) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700707 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
708 "func1\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700709 return -ENODEV;
710 }
711 return 0;
712}
713
714
715static int sdio_al_verify_dev(struct sdio_al_device *sdio_al_dev,
716 char const *func)
717{
718 int ret;
719
720 ret = sdio_al_verify_func1(sdio_al_dev, func);
721 if (ret)
722 return ret;
723
724 if ((sdio_al_dev->state == MODEM_RESTART) ||
725 (sdio_al_dev->state == CARD_REMOVED)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700726 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: device "
727 "state %d\n", func, sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700728 return -ENODEV;
729 }
730 return 0;
731}
732
733static void sdio_al_get_into_err_state(struct sdio_al_device *sdio_al_dev)
734{
735 if ((!sdio_al) || (!sdio_al_dev))
736 return;
737
738 sdio_al_dev->is_err = true;
739 sdio_al->debug.debug_data_on = 0;
740 sdio_al->debug.debug_lpm_on = 0;
741 sdio_al_print_info();
742}
743
744void sdio_al_register_lpm_cb(void *device_handle,
745 int(*lpm_callback)(void *, int))
746{
747 struct sdio_al_device *sdio_al_dev =
748 (struct sdio_al_device *) device_handle;
749
750 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700751 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - "
752 "device_handle is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700753 return;
754 }
755
756 if (lpm_callback) {
757 sdio_al_dev->lpm_callback = lpm_callback;
758 lpm_callback((void *)sdio_al_dev,
759 sdio_al_dev->is_ok_to_sleep);
760 }
Krishna Kondaa7af6062011-09-01 18:34:38 -0700761
762 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - device %d "
763 "registered for wakeup callback\n", __func__,
764 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700765}
766
767void sdio_al_unregister_lpm_cb(void *device_handle)
768{
769 struct sdio_al_device *sdio_al_dev =
770 (struct sdio_al_device *) device_handle;
771
772 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700773 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - "
774 "device_handle is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700775 return;
776 }
777
778 sdio_al_dev->lpm_callback = NULL;
Krishna Kondaa7af6062011-09-01 18:34:38 -0700779 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - device %d "
780 "unregister for wakeup callback\n", __func__,
781 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700782}
783
784static void sdio_al_vote_for_sleep(struct sdio_al_device *sdio_al_dev,
785 int is_vote_for_sleep)
786{
787 pr_debug(MODULE_NAME ": %s()", __func__);
788
Yaniv Gardi3e327762011-07-27 11:11:04 +0300789 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700790 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - sdio_al_dev"
791 " is NULL\n", __func__);
Yaniv Gardi3e327762011-07-27 11:11:04 +0300792 return;
793 }
794
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700795 if (is_vote_for_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +0300796 pr_debug(MODULE_NAME ": %s - sdio vote for Sleep", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700797 wake_unlock(&sdio_al_dev->wake_lock);
798 } else {
Maya Erez7b1ebd22011-08-20 20:53:24 +0300799 pr_debug(MODULE_NAME ": %s - sdio vote against sleep",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800 __func__);
801 wake_lock(&sdio_al_dev->wake_lock);
802 }
803
804 if (sdio_al_dev->lpm_callback != NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700805 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - "
806 "is_vote_for_sleep=%d for card#%d, "
807 "calling callback...", __func__,
808 is_vote_for_sleep,
809 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700810 sdio_al_dev->lpm_callback((void *)sdio_al_dev,
811 is_vote_for_sleep);
812 }
813}
814
815/**
816 * Write SDIO-Client lpm information
817 * Should only be called with host claimed.
818 */
819static int write_lpm_info(struct sdio_al_device *sdio_al_dev)
820{
821 struct sdio_func *lpm_func =
822 sdio_al_dev->card->sdio_func[sdio_al_dev->lpm_chan+1];
823 int offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
824 sizeof(struct peer_sdioc_channel_config) *
825 sdio_al_dev->lpm_chan+
826 offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
827 int ret;
828
829 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700830 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
831 "lpm_chan for card %d\n",
832 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700833 return -EINVAL;
834 }
835
836 pr_debug(MODULE_NAME ":write_lpm_info is_ok_to_sleep=%d, device %d\n",
837 sdio_al_dev->is_ok_to_sleep,
838 sdio_al_dev->card->host->index);
839
840 ret = sdio_memcpy_toio(lpm_func, SDIOC_SW_MAILBOX_ADDR+offset,
841 &sdio_al_dev->is_ok_to_sleep, sizeof(u32));
842 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700843 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
844 "write lpm info for card %d\n",
845 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700846 return ret;
847 }
848
849 return 0;
850}
851
852/* Set inactivity counter to intial value to allow clients come up */
853static inline void start_inactive_time(struct sdio_al_device *sdio_al_dev)
854{
855 sdio_al_dev->inactivity_time = jiffies +
856 msecs_to_jiffies(INITIAL_INACTIVITY_TIME_MSEC);
857}
858
859static inline void restart_inactive_time(struct sdio_al_device *sdio_al_dev)
860{
861 sdio_al_dev->inactivity_time = jiffies +
862 msecs_to_jiffies(INACTIVITY_TIME_MSEC);
863}
864
865static inline int is_inactive_time_expired(struct sdio_al_device *sdio_al_dev)
866{
867 return time_after(jiffies, sdio_al_dev->inactivity_time);
868}
869
870
871static int is_user_irq_enabled(struct sdio_al_device *sdio_al_dev,
872 int func_num)
873{
874 int ret = 0;
875 struct sdio_func *func1;
876 u32 user_irq = 0;
877 u32 addr = 0;
878 u32 offset = 0;
879 u32 masked_user_irq = 0;
880
881 if (sdio_al_verify_dev(sdio_al_dev, __func__))
882 return 0;
883 func1 = sdio_al_dev->card->sdio_func[0];
884
885 if (func_num < 4) {
886 addr = FUNC_1_4_USER_IRQ_ADDR;
887 offset = func_num * 8;
888 } else {
889 addr = FUNC_5_7_USER_IRQ_ADDR;
890 offset = (func_num - 4) * 8;
891 }
892
893 user_irq = sdio_readl(func1, addr, &ret);
894 if (ret) {
895 pr_debug(MODULE_NAME ":read_user_irq fail\n");
896 return 0;
897 }
898
899 masked_user_irq = (user_irq >> offset) && 0xFF;
900 if (masked_user_irq == 0x1) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700901 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":user_irq "
902 "enabled\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700903 return 1;
904 }
905
906 return 0;
907}
908
909static void sdio_al_sleep(struct sdio_al_device *sdio_al_dev,
910 struct mmc_host *host)
911{
912 int i;
913
914 /* Go to sleep */
Maya Erez7b1ebd22011-08-20 20:53:24 +0300915 pr_debug(MODULE_NAME ":Inactivity timer expired."
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700916 " Going to sleep\n");
917 /* Stop mailbox timer */
918 sdio_al_dev->poll_delay_msec = 0;
919 del_timer_sync(&sdio_al_dev->timer);
920 /* Make sure we get interrupt for non-packet-mode right away */
921 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
922 struct sdio_channel *ch = &sdio_al_dev->channel[i];
Maya Erez5795e0d2011-09-12 20:20:06 +0300923 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
924 (ch->state != SDIO_CHANNEL_STATE_CLOSED)) {
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300925 pr_debug(MODULE_NAME ":continue for channel %s in"
926 " state %d\n", ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700927 continue;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300928 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700929 if (ch->is_packet_mode == false) {
930 ch->read_threshold = 1;
931 set_pipe_threshold(sdio_al_dev,
932 ch->rx_pipe_index,
933 ch->read_threshold);
934 }
935 }
Maya Erezfd915312011-07-14 13:45:34 +0300936 /* Prevent modem to go to sleep until we get the PROG_DONE on
937 the dummy CMD52 */
938 msmsdcc_set_pwrsave(sdio_al_dev->card->host, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700939 /* Mark HOST_OK_TOSLEEP */
940 sdio_al_dev->is_ok_to_sleep = 1;
941 write_lpm_info(sdio_al_dev);
942
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700943 msmsdcc_lpm_enable(host);
Krishna Kondaa7af6062011-09-01 18:34:38 -0700944 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Finished sleep sequence"
945 " for card %d. Sleep now.\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700946 sdio_al_dev->card->host->index);
947 /* Release wakelock */
948 sdio_al_vote_for_sleep(sdio_al_dev, 1);
949}
950
951
952/**
953 * Read SDIO-Client Mailbox from Function#1.thresh_pipe
954 *
955 * The mailbox contain the bytes available per pipe,
956 * and the End-Of-Transfer indication per pipe (if available).
957 *
958 * WARNING: Each time the Mailbox is read from the client, the
959 * read_bytes_avail is incremented with another pending
960 * transfer. Therefore, a pending rx-packet should be added to a
961 * list before the next read of the mailbox.
962 *
963 * This function should run from a workqueue context since it
964 * notifies the clients.
965 *
966 * This function assumes that sdio_claim_host was called before
967 * calling it.
968 *
969 */
970static int read_mailbox(struct sdio_al_device *sdio_al_dev, int from_isr)
971{
972 int ret;
973 struct sdio_func *func1 = sdio_al_dev->card->sdio_func[0];
974 struct sdio_mailbox *mailbox = sdio_al_dev->mailbox;
975 struct mmc_host *host = func1->card->host;
976 u32 new_write_avail = 0;
977 u32 old_write_avail = 0;
978 u32 any_read_avail = 0;
979 u32 any_write_pending = 0;
980 int i;
981 u32 rx_notify_bitmask = 0;
982 u32 tx_notify_bitmask = 0;
983 u32 eot_pipe = 0;
984 u32 thresh_pipe = 0;
985 u32 overflow_pipe = 0;
986 u32 underflow_pipe = 0;
987 u32 thresh_intr_mask = 0;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300988 int is_closing = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700989
990 if (sdio_al_dev->is_err) {
991 SDIO_AL_ERR(__func__);
992 return 0;
993 }
994
995 pr_debug(MODULE_NAME ":start %s from_isr = %d for card %d.\n"
996 , __func__, from_isr, sdio_al_dev->card->host->index);
997
998 pr_debug(MODULE_NAME ":before sdio_memcpy_fromio.\n");
Maya Erez320a7ca2011-08-03 09:41:27 +0300999 memset(mailbox, 0, sizeof(struct sdio_mailbox));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001000 ret = sdio_memcpy_fromio(func1, mailbox,
1001 HW_MAILBOX_ADDR, sizeof(*mailbox));
1002 pr_debug(MODULE_NAME ":after sdio_memcpy_fromio.\n");
Maya Erez320a7ca2011-08-03 09:41:27 +03001003 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001004 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to read "
1005 "Mailbox for card %d, goto error state\n",
1006 sdio_al_dev->card->host->index);
Maya Erez320a7ca2011-08-03 09:41:27 +03001007 sdio_al_get_into_err_state(sdio_al_dev);
1008 /* Stop the timer to stop reading the mailbox */
1009 sdio_al_dev->poll_delay_msec = 0;
1010 goto exit_err;
1011 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001012
1013 eot_pipe = (mailbox->eot_pipe_0_7) |
1014 (mailbox->eot_pipe_8_15<<8);
1015 thresh_pipe = (mailbox->thresh_above_limit_pipe_0_7) |
1016 (mailbox->thresh_above_limit_pipe_8_15<<8);
1017
1018 overflow_pipe = (mailbox->overflow_pipe_0_7) |
1019 (mailbox->overflow_pipe_8_15<<8);
1020 underflow_pipe = mailbox->underflow_pipe_0_7 |
1021 (mailbox->underflow_pipe_8_15<<8);
1022 thresh_intr_mask =
1023 (mailbox->mask_thresh_above_limit_pipe_0_7) |
1024 (mailbox->mask_thresh_above_limit_pipe_8_15<<8);
1025
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001026 if (overflow_pipe || underflow_pipe)
Krishna Kondaa7af6062011-09-01 18:34:38 -07001027 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Mailbox ERROR "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001028 "overflow=0x%x, underflow=0x%x\n",
1029 overflow_pipe, underflow_pipe);
1030
1031 /* In case of modem reset we would like to read the daya from the modem
1032 to clear the interrupts but do not process it */
1033 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001034 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_device"
1035 " (card %d) is in invalid state %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001036 sdio_al_dev->card->host->index,
1037 sdio_al_dev->state);
1038 return -ENODEV;
1039 }
1040
1041 pr_debug(MODULE_NAME ":card %d: eot=0x%x, thresh=0x%x\n",
1042 sdio_al_dev->card->host->index,
1043 eot_pipe, thresh_pipe);
1044
1045 /* Scan for Rx Packets available and update read available bytes */
1046 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1047 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1048 u32 old_read_avail;
1049 u32 read_avail;
1050 u32 new_packet_size = 0;
1051
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001052 if (ch->state == SDIO_CHANNEL_STATE_CLOSING)
1053 is_closing = true; /* used to prevent sleep */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001054
1055 old_read_avail = ch->read_avail;
1056 read_avail = mailbox->pipe_bytes_avail[ch->rx_pipe_index];
1057
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001058 if ((ch->state == SDIO_CHANNEL_STATE_CLOSED) &&
1059 (read_avail > 0)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001060 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1061 ":%s: Invalid read_avail 0x%x, for CLOSED ch %s\n",
Maya Erez5795e0d2011-09-12 20:20:06 +03001062 __func__, read_avail, ch->name);
1063 sdio_read_from_closed_ch(ch, read_avail);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001064 }
1065 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
1066 (ch->state != SDIO_CHANNEL_STATE_CLOSING))
1067 continue;
1068
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001069 if (read_avail > INVALID_DATA_AVAILABLE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001070 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001071 ":Invalid read_avail 0x%x for pipe %d\n",
1072 read_avail, ch->rx_pipe_index);
1073 continue;
1074 }
1075 any_read_avail |= read_avail | old_read_avail;
1076 ch->statistics.last_any_read_avail = any_read_avail;
1077 ch->statistics.last_read_avail = read_avail;
1078 ch->statistics.last_old_read_avail = old_read_avail;
1079
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001080 if (ch->is_packet_mode) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001081 if ((eot_pipe & (1<<ch->rx_pipe_index)) &&
1082 sdio_al_dev->print_after_interrupt) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001083 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME
1084 ":Interrupt on ch %s, "
1085 "card %d", ch->name,
1086 sdio_al_dev->card->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03001087 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001088 new_packet_size = check_pending_rx_packet(ch, eot_pipe);
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001089 } else {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001090 if ((thresh_pipe & (1<<ch->rx_pipe_index)) &&
1091 sdio_al_dev->print_after_interrupt) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001092 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME
1093 ":Interrupt on ch %s, "
1094 "card %d", ch->name,
1095 sdio_al_dev->card->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03001096 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001097 ch->read_avail = read_avail;
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001098 /* Restore default thresh for non packet channels */
1099 if ((ch->read_threshold != ch->def_read_threshold) &&
1100 (read_avail >= ch->threshold_change_cnt)) {
1101 ch->read_threshold = ch->def_read_threshold;
1102 set_pipe_threshold(sdio_al_dev,
1103 ch->rx_pipe_index,
1104 ch->read_threshold);
1105 }
1106 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001107
1108 if ((ch->is_packet_mode) && (new_packet_size > 0)) {
1109 rx_notify_bitmask |= (1<<ch->num);
1110 ch->statistics.total_notifs++;
1111 }
1112
1113 if ((!ch->is_packet_mode) && (ch->read_avail > 0) &&
1114 (old_read_avail == 0)) {
1115 rx_notify_bitmask |= (1<<ch->num);
1116 ch->statistics.total_notifs++;
1117 }
1118 }
Maya Erez7b1ebd22011-08-20 20:53:24 +03001119 sdio_al_dev->print_after_interrupt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001120
1121 /* Update Write available */
1122 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1123 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1124
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001125 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
1126 (ch->state != SDIO_CHANNEL_STATE_CLOSING))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001127 continue;
1128
1129 new_write_avail = mailbox->pipe_bytes_avail[ch->tx_pipe_index];
1130
1131 if (new_write_avail > INVALID_DATA_AVAILABLE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001132 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001133 ":Invalid write_avail 0x%x for pipe %d\n",
1134 new_write_avail, ch->tx_pipe_index);
1135 continue;
1136 }
1137
1138 old_write_avail = ch->write_avail;
1139 ch->write_avail = new_write_avail;
1140
1141 if ((old_write_avail <= ch->min_write_avail) &&
1142 (new_write_avail >= ch->min_write_avail))
1143 tx_notify_bitmask |= (1<<ch->num);
1144
1145 /* There is not enough write avail for this channel.
1146 We need to keep reading mailbox to wait for the appropriate
1147 write avail and cannot sleep. Ignore SMEM channel that has
1148 only one direction. */
1149 if (strcmp(ch->name, "SDIO_SMEM"))
1150 any_write_pending |=
1151 (new_write_avail < ch->ch_config.max_tx_threshold);
1152 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001153 /* notify clients */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001154 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1155 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1156
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001157 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) ||
1158 (ch->notify == NULL))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001159 continue;
1160
1161 if (rx_notify_bitmask & (1<<ch->num))
1162 ch->notify(ch->priv,
1163 SDIO_EVENT_DATA_READ_AVAIL);
1164
1165 if (tx_notify_bitmask & (1<<ch->num))
1166 ch->notify(ch->priv,
1167 SDIO_EVENT_DATA_WRITE_AVAIL);
1168 }
1169
1170
1171 if ((rx_notify_bitmask == 0) && (tx_notify_bitmask == 0) &&
1172 !any_read_avail && !any_write_pending) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001173 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Nothing to "
1174 "Notify for card %d, is_closing=%d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001175 sdio_al_dev->card->host->index, is_closing);
1176 if (is_closing)
1177 restart_inactive_time(sdio_al_dev);
1178 else if (is_inactive_time_expired(sdio_al_dev))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001179 sdio_al_sleep(sdio_al_dev, host);
1180 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001181 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Notify bitmask"
1182 " for card %d rx=0x%x, tx=0x%x.\n",
1183 sdio_al_dev->card->host->index,
1184 rx_notify_bitmask, tx_notify_bitmask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001185 /* Restart inactivity timer if any activity on the channel */
1186 restart_inactive_time(sdio_al_dev);
1187 }
1188
1189 pr_debug(MODULE_NAME ":end %s.\n", __func__);
1190
1191exit_err:
1192 return ret;
1193}
1194
1195/**
1196 * Check pending rx packet when reading the mailbox.
1197 */
1198static u32 check_pending_rx_packet(struct sdio_channel *ch, u32 eot)
1199{
1200 u32 rx_pending;
1201 u32 rx_avail;
1202 u32 new_packet_size = 0;
1203 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
1204
1205
1206 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001207 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
1208 " for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001209 return -EINVAL;
1210 }
1211
1212 mutex_lock(&ch->ch_lock);
1213
1214 rx_pending = ch->rx_pending_bytes;
1215 rx_avail = sdio_al_dev->mailbox->pipe_bytes_avail[ch->rx_pipe_index];
1216
1217 pr_debug(MODULE_NAME ":pipe %d of card %d rx_avail=0x%x, "
1218 "rx_pending=0x%x\n",
1219 ch->rx_pipe_index, sdio_al_dev->card->host->index, rx_avail,
1220 rx_pending);
1221
1222
1223 /* new packet detected */
1224 if (eot & (1<<ch->rx_pipe_index)) {
1225 struct rx_packet_size *p = NULL;
1226 new_packet_size = rx_avail - rx_pending;
1227
1228 if ((rx_avail <= rx_pending)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001229 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1230 ": Invalid new packet size."
1231 " rx_avail=%d.\n", rx_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001232 new_packet_size = 0;
1233 goto exit_err;
1234 }
1235
1236 p = kzalloc(sizeof(*p), GFP_KERNEL);
Maya Erezd9cc2292011-08-04 09:20:31 +03001237 if (p == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001238 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1239 ": failed to allocate item for "
1240 "rx_pending list. rx_avail=%d, "
1241 "rx_pending=%d.\n",
1242 rx_avail, rx_pending);
Maya Erezd9cc2292011-08-04 09:20:31 +03001243 new_packet_size = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001244 goto exit_err;
Maya Erezd9cc2292011-08-04 09:20:31 +03001245 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001246 p->size = new_packet_size;
1247 /* Add new packet as last */
1248 list_add_tail(&p->list, &ch->rx_size_list_head);
1249 ch->rx_pending_bytes += new_packet_size;
1250
1251 if (ch->read_avail == 0)
1252 ch->read_avail = new_packet_size;
1253 }
1254
1255exit_err:
1256 mutex_unlock(&ch->ch_lock);
1257
1258 return new_packet_size;
1259}
1260
1261
1262
1263/**
1264 * Remove first pending packet from the list.
1265 */
1266static u32 remove_handled_rx_packet(struct sdio_channel *ch)
1267{
1268 struct rx_packet_size *p = NULL;
1269
1270 mutex_lock(&ch->ch_lock);
1271
1272 ch->rx_pending_bytes -= ch->read_avail;
1273
1274 if (!list_empty(&ch->rx_size_list_head)) {
1275 p = list_first_entry(&ch->rx_size_list_head,
1276 struct rx_packet_size, list);
1277 list_del(&p->list);
1278 kfree(p);
Maya Erezd9cc2292011-08-04 09:20:31 +03001279 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001280 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: ch "
1281 "%s: unexpected empty list!!\n",
1282 __func__, ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001283 }
1284
1285 if (list_empty(&ch->rx_size_list_head)) {
1286 ch->read_avail = 0;
1287 } else {
1288 p = list_first_entry(&ch->rx_size_list_head,
1289 struct rx_packet_size, list);
1290 ch->read_avail = p->size;
1291 }
1292
1293 mutex_unlock(&ch->ch_lock);
1294
1295 return ch->read_avail;
1296}
1297
1298
1299/**
1300 * Bootloader worker function.
1301 *
1302 * @note: clear the bootloader_done flag only after reading the
1303 * mailbox, to ignore more requests while reading the mailbox.
1304 */
1305static void boot_worker(struct work_struct *work)
1306{
1307 int ret = 0;
1308 int func_num = 0;
1309 int i;
1310 struct sdio_al_device *sdio_al_dev = NULL;
1311 struct sdio_al_work *sdio_al_work = container_of(work,
1312 struct sdio_al_work,
1313 work);
1314
1315 if (sdio_al_work == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001316 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1317 "sdio_al_work\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001318 return;
1319 }
1320
1321 sdio_al_dev = sdio_al_work->sdio_al_dev;
1322 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001323 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1324 "sdio_al_dev\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001325 return;
1326 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07001327 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":Bootloader Worker Started"
1328 ", wait for bootloader_done event..\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001329 wait_event(sdio_al_dev->wait_mbox,
1330 sdio_al_dev->bootloader_done);
Krishna Kondaa7af6062011-09-01 18:34:38 -07001331 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":Got bootloader_done "
1332 "event..\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001333 /* Do polling until MDM is up */
1334 for (i = 0; i < 5000; ++i) {
1335 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1336 return;
1337 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
1338 if (is_user_irq_enabled(sdio_al_dev, func_num)) {
1339 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
1340 sdio_al_dev->bootloader_done = 0;
1341 ret = sdio_al_client_setup(sdio_al_dev);
1342 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001343 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1344 ": sdio_al_client_setup failed, "
1345 "for card %d ret=%d\n",
1346 sdio_al_dev->card->host->index, ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001347 sdio_al_get_into_err_state(sdio_al_dev);
1348 }
1349 goto done;
1350 }
1351 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
1352 msleep(100);
1353 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07001354 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Timeout waiting for "
1355 "user_irq for card %d\n",
1356 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001357 sdio_al_get_into_err_state(sdio_al_dev);
1358
1359done:
1360 pr_debug(MODULE_NAME ":Boot Worker for card %d Exit!\n",
1361 sdio_al_dev->card->host->index);
1362}
1363
1364/**
1365 * Worker function.
1366 *
1367 * @note: clear the ask_mbox flag only after
1368 * reading the mailbox, to ignore more requests while
1369 * reading the mailbox.
1370 */
1371static void worker(struct work_struct *work)
1372{
1373 int ret = 0;
1374 struct sdio_al_device *sdio_al_dev = NULL;
1375 struct sdio_al_work *sdio_al_work = container_of(work,
1376 struct sdio_al_work,
1377 work);
1378 if (sdio_al_work == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001379 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": worker: NULL "
1380 "sdio_al_work\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001381 return;
1382 }
1383
1384 sdio_al_dev = sdio_al_work->sdio_al_dev;
1385 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001386 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": worker: NULL "
1387 "sdio_al_dev\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001388 return;
1389 }
1390 pr_debug(MODULE_NAME ":Worker Started..\n");
1391 while ((sdio_al_dev->is_ready) && (ret == 0)) {
1392 pr_debug(MODULE_NAME ":Wait for read mailbox request..\n");
1393 wait_event(sdio_al_dev->wait_mbox, sdio_al_dev->ask_mbox);
1394 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1395 break;
1396 if (!sdio_al_dev->is_ready)
1397 break;
1398 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
1399 if (sdio_al_dev->is_ok_to_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001400 ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001401 if (ret) {
1402 sdio_release_host(
1403 sdio_al_dev->card->sdio_func[0]);
1404 return;
1405 }
1406 }
1407 ret = read_mailbox(sdio_al_dev, false);
1408 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
1409 sdio_al_dev->ask_mbox = false;
1410 }
1411 pr_debug(MODULE_NAME ":Worker Exit!\n");
1412}
1413
1414/**
1415 * Write command using CMD54 rather than CMD53.
1416 * Writing with CMD54 generate EOT interrupt at the
1417 * SDIO-Client.
1418 * Based on mmc_io_rw_extended()
1419 */
1420static int sdio_write_cmd54(struct mmc_card *card, unsigned fn,
1421 unsigned addr, const u8 *buf,
1422 unsigned blocks, unsigned blksz)
1423{
1424 struct mmc_request mrq;
1425 struct mmc_command cmd;
1426 struct mmc_data data;
1427 struct scatterlist sg;
1428 int incr_addr = 1; /* MUST */
1429 int write = 1;
1430
1431 BUG_ON(!card);
1432 BUG_ON(fn > 7);
1433 BUG_ON(blocks == 1 && blksz > 512);
1434 WARN_ON(blocks == 0);
1435 WARN_ON(blksz == 0);
1436
1437 write = true;
1438 pr_debug(MODULE_NAME ":sdio_write_cmd54()"
1439 "fn=%d,buf=0x%x,blocks=%d,blksz=%d\n",
1440 fn, (u32) buf, blocks, blksz);
1441
1442 memset(&mrq, 0, sizeof(struct mmc_request));
1443 memset(&cmd, 0, sizeof(struct mmc_command));
1444 memset(&data, 0, sizeof(struct mmc_data));
1445
1446 mrq.cmd = &cmd;
1447 mrq.data = &data;
1448
1449 cmd.opcode = SD_IO_RW_EXTENDED_QCOM;
1450
1451 cmd.arg = write ? 0x80000000 : 0x00000000;
1452 cmd.arg |= fn << 28;
1453 cmd.arg |= incr_addr ? 0x04000000 : 0x00000000;
1454 cmd.arg |= addr << 9;
1455 if (blocks == 1 && blksz <= 512)
1456 cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */
1457 else
1458 cmd.arg |= 0x08000000 | blocks; /* block mode */
1459 cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
1460
1461 data.blksz = blksz;
1462 data.blocks = blocks;
1463 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
1464 data.sg = &sg;
1465 data.sg_len = 1;
1466
1467 sg_init_one(&sg, buf, blksz * blocks);
1468
1469 mmc_set_data_timeout(&data, card);
1470
1471 mmc_wait_for_req(card->host, &mrq);
1472
1473 if (cmd.error)
1474 return cmd.error;
1475 if (data.error)
1476 return data.error;
1477
1478 if (mmc_host_is_spi(card->host)) {
1479 /* host driver already reported errors */
1480 } else {
1481 if (cmd.resp[0] & R5_ERROR) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001482 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1483 ":%s: R5_ERROR for card %d",
1484 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001485 return -EIO;
1486 }
1487 if (cmd.resp[0] & R5_FUNCTION_NUMBER) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001488 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1489 ":%s: R5_FUNCTION_NUMBER for card %d",
1490 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001491 return -EINVAL;
1492 }
1493 if (cmd.resp[0] & R5_OUT_OF_RANGE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001494 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1495 ":%s: R5_OUT_OF_RANGE for card %d",
1496 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001497 return -ERANGE;
1498 }
1499 }
1500
1501 return 0;
1502}
1503
1504
1505/**
1506 * Write data to channel.
1507 * Handle different data size types.
1508 *
1509 */
1510static int sdio_ch_write(struct sdio_channel *ch, const u8 *buf, u32 len)
1511{
1512 int ret = 0;
1513 unsigned blksz = ch->func->cur_blksize;
1514 int blocks = len / blksz;
1515 int remain_bytes = len % blksz;
1516 struct mmc_card *card = NULL;
1517 u32 fn = ch->func->num;
1518
Krishna Kondaa7af6062011-09-01 18:34:38 -07001519 if (!ch) {
1520 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1521 "channel\n", __func__);
1522 return -ENODEV;
1523 }
1524
1525 if (!ch->sdio_al_dev) {
1526 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1527 "sdio_al_dev\n", __func__);
1528 return -ENODEV;
1529 }
1530
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001531 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001532 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":channel "
1533 "%s trying to write 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001534 return -EINVAL;
1535 }
1536
1537 card = ch->func->card;
1538
1539 if (remain_bytes) {
1540 /* CMD53 */
1541 if (blocks) {
1542 ret = sdio_memcpy_toio(ch->func, PIPE_TX_FIFO_ADDR,
1543 (void *) buf, blocks*blksz);
1544 if (ret != 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001545 sdio_al_loge(ch->sdio_al_dev->dev_log,
1546 MODULE_NAME ":%s: sdio_memcpy_toio "
1547 "failed for channel %s\n",
1548 __func__, ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001549 ch->sdio_al_dev->is_err = true;
1550 return ret;
1551 }
1552 }
1553
1554 buf += (blocks*blksz);
1555
1556 ret = sdio_write_cmd54(card, fn, PIPE_TX_FIFO_ADDR,
1557 buf, 1, remain_bytes);
1558 } else {
1559 ret = sdio_write_cmd54(card, fn, PIPE_TX_FIFO_ADDR,
1560 buf, blocks, blksz);
1561 }
1562
1563 if (ret != 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001564 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
1565 "sdio_write_cmd54 failed for channel %s\n",
1566 __func__, ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001567 ch->sdio_al_dev->is_err = true;
1568 return ret;
1569 }
1570
1571 return ret;
1572}
1573
1574static int sdio_al_bootloader_completed(void)
1575{
1576 int i;
1577
1578 pr_debug(MODULE_NAME ":sdio_al_bootloader_completed was called\n");
1579
1580 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
1581 struct sdio_al_device *dev = NULL;
1582 if (sdio_al->devices[i] == NULL)
1583 continue;
1584 dev = sdio_al->devices[i];
1585 dev->bootloader_done = 1;
1586 wake_up(&dev->wait_mbox);
1587 }
1588
1589 return 0;
1590}
1591
1592static int sdio_al_wait_for_bootloader_comp(struct sdio_al_device *sdio_al_dev)
1593{
1594 int ret = 0;
1595
1596 struct sdio_func *func1;
1597
1598 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1599 return -ENODEV;
1600 func1 = sdio_al_dev->card->sdio_func[0];
1601
1602 sdio_claim_host(func1);
1603 /*
1604 * Enable function 0 interrupt mask to allow 9k to raise this interrupt
1605 * in power-up. When sdio_downloader will notify its completion
1606 * we will poll on this interrupt to wait for 9k power-up
1607 */
1608 ret = enable_mask_irq(sdio_al_dev, 0, 1, 0);
1609 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001610 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1611 ": Enable_mask_irq for card %d failed, "
1612 "ret=%d\n",
1613 sdio_al_dev->card->host->index, ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001614 sdio_release_host(func1);
1615 return ret;
1616 }
1617
1618 sdio_release_host(func1);
1619
1620 /*
1621 * Start bootloader worker that will wait for the bootloader
1622 * completion
1623 */
1624 sdio_al_dev->boot_work.sdio_al_dev = sdio_al_dev;
1625 INIT_WORK(&sdio_al_dev->boot_work.work, boot_worker);
1626 sdio_al_dev->bootloader_done = 0;
1627 queue_work(sdio_al_dev->workqueue, &sdio_al_dev->boot_work.work);
1628
1629 return 0;
1630}
1631
1632static int sdio_al_bootloader_setup(void)
1633{
1634 int ret = 0;
1635 struct sdio_func *func1;
1636 struct sdio_al_device *bootloader_dev = sdio_al->bootloader_dev;
1637
1638 if (bootloader_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001639 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1640 ": No bootloader_dev\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001641 return -ENODEV;
1642 }
1643
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001644 if (bootloader_dev->flashless_boot_on) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001645 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":Already "
1646 "in boot process.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001647 return 0;
1648 }
1649
1650 func1 = bootloader_dev->card->sdio_func[0];
1651 if (!func1) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001652 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
1653 ": %s: NULL func1\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001654 return -ENODEV;
1655 }
1656
1657 bootloader_dev->sdioc_boot_sw_header
1658 = kzalloc(sizeof(*bootloader_dev->sdioc_boot_sw_header),
1659 GFP_KERNEL);
1660 if (bootloader_dev->sdioc_boot_sw_header == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001661 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":fail to "
1662 "allocate sdioc boot sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001663 return -ENOMEM;
1664 }
1665
1666 sdio_claim_host(func1);
1667
1668 ret = sdio_memcpy_fromio(func1,
1669 bootloader_dev->sdioc_boot_sw_header,
1670 SDIOC_SW_HEADER_ADDR,
1671 sizeof(struct peer_sdioc_boot_sw_header));
1672 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001673 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":fail to "
1674 "read sdioc boot sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001675 sdio_release_host(func1);
1676 goto exit_err;
1677 }
1678
1679 if (bootloader_dev->sdioc_boot_sw_header->signature !=
1680 (u32) PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001681 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":invalid "
1682 "mailbox signature 0x%x.\n",
1683 bootloader_dev->sdioc_boot_sw_header->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001684 sdio_release_host(func1);
1685 ret = -EINVAL;
1686 goto exit_err;
1687 }
1688
1689 /* Upper byte has to be equal - no backward compatibility for unequal */
1690 if ((bootloader_dev->sdioc_boot_sw_header->version >> 16) !=
1691 (sdio_al->pdata->peer_sdioc_boot_version_major)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001692 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ": HOST(0x%x)"
1693 " and CLIENT(0x%x) SDIO_AL BOOT VERSION don't match\n",
1694 ((sdio_al->pdata->peer_sdioc_boot_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001695 sdio_al->pdata->peer_sdioc_boot_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001696 bootloader_dev->sdioc_boot_sw_header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001697 sdio_release_host(func1);
1698 ret = -EIO;
1699 goto exit_err;
1700 }
1701
Krishna Kondaa7af6062011-09-01 18:34:38 -07001702 sdio_al_logi(bootloader_dev->dev_log, MODULE_NAME ": SDIOC BOOT SW "
1703 "version 0x%x\n",
1704 bootloader_dev->sdioc_boot_sw_header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001705
1706 bootloader_dev->flashless_boot_on = true;
1707
1708 sdio_release_host(func1);
1709
1710 ret = sdio_al_wait_for_bootloader_comp(bootloader_dev);
1711 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001712 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
1713 ": sdio_al_wait_for_bootloader_comp failed, "
1714 "err=%d\n", ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001715 goto exit_err;
1716 }
1717
1718 ret = sdio_downloader_setup(bootloader_dev->card, 1,
1719 bootloader_dev->sdioc_boot_sw_header->boot_ch_num,
1720 sdio_al_bootloader_completed);
1721
1722 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001723 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
1724 ": sdio_downloader_setup failed, err=%d\n", ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001725 goto exit_err;
1726 }
1727
Krishna Kondaa7af6062011-09-01 18:34:38 -07001728 sdio_al_logi(bootloader_dev->dev_log, MODULE_NAME ":In Flashless boot,"
1729 " waiting for its completion\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001730
1731
1732exit_err:
Krishna Kondaa7af6062011-09-01 18:34:38 -07001733 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":free "
1734 "sdioc_boot_sw_header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001735 kfree(bootloader_dev->sdioc_boot_sw_header);
1736 bootloader_dev->sdioc_boot_sw_header = NULL;
1737 bootloader_dev = NULL;
1738
1739 return ret;
1740}
1741
1742
1743/**
1744 * Read SDIO-Client software header
1745 *
1746 */
1747static int read_sdioc_software_header(struct sdio_al_device *sdio_al_dev,
1748 struct peer_sdioc_sw_header *header)
1749{
1750 int ret;
1751 int i;
1752 int test_version = 0;
1753 int sdioc_test_version = 0;
1754
1755 pr_debug(MODULE_NAME ":reading sdioc sw header.\n");
1756
1757 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1758 return -ENODEV;
1759
1760 ret = sdio_memcpy_fromio(sdio_al_dev->card->sdio_func[0], header,
1761 SDIOC_SW_HEADER_ADDR, sizeof(*header));
1762 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001763 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
1764 "sdioc sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001765 goto exit_err;
1766 }
1767
1768 if (header->signature == (u32)PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001769 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW "
1770 "unittest signature. 0x%x\n",
1771 header->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001772 sdio_al->unittest_mode = true;
1773 /* Verify test code compatibility with the modem */
1774 sdioc_test_version = (header->version & 0xFF00) >> 8;
1775 test_version = sdio_al->pdata->peer_sdioc_version_minor >> 8;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001776 if (test_version != sdioc_test_version) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001777 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1778 ": HOST(0x%x) and CLIENT(0x%x) "
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001779 "testing VERSION don't match\n",
Krishna Kondaa7af6062011-09-01 18:34:38 -07001780 test_version,
1781 sdioc_test_version);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001782 msleep(500);
1783 BUG();
1784 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785 }
1786
1787 if ((header->signature != (u32) PEER_SDIOC_SW_MAILBOX_SIGNATURE) &&
1788 (header->signature != (u32) PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001789 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW "
1790 "invalid signature. 0x%x\n", header->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001791 goto exit_err;
1792 }
1793 /* Upper byte has to be equal - no backward compatibility for unequal */
1794 sdio_al->sdioc_major = header->version >> 16;
1795 if (sdio_al->pdata->allow_sdioc_version_major_2) {
1796 if ((sdio_al->sdioc_major !=
1797 sdio_al->pdata->peer_sdioc_version_major) &&
1798 (sdio_al->sdioc_major != PEER_SDIOC_OLD_VERSION_MAJOR)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001799 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1800 ": HOST(0x%x) and CLIENT(0x%x) "
1801 "SDIO_AL VERSION don't match\n",
1802 ((sdio_al->pdata->peer_sdioc_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001803 sdio_al->pdata->peer_sdioc_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001804 header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001805 goto exit_err;
1806 }
1807 } else {
1808 if (sdio_al->sdioc_major !=
1809 sdio_al->pdata->peer_sdioc_version_major) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001810 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1811 ": HOST(0x%x) and CLIENT(0x%x) "
1812 "SDIO_AL VERSION don't match\n",
1813 ((sdio_al->pdata->peer_sdioc_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001814 sdio_al->pdata->peer_sdioc_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001815 header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001816 goto exit_err;
1817 }
1818 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001819 sdio_al_dev->ch_close_supported = (header->version & 0x000F) >=
1820 (sdio_al->pdata->peer_sdioc_version_minor & 0xF);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001821
Krishna Kondaa7af6062011-09-01 18:34:38 -07001822 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW version 0x%x,"
1823 " sdio_al major 0x%x minor 0x%x\n", header->version,
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001824 sdio_al->sdioc_major,
1825 sdio_al->pdata->peer_sdioc_version_minor);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001826
1827 sdio_al_dev->flashless_boot_on = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001828 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1829 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1830
1831 /* Set default values */
1832 ch->read_threshold = DEFAULT_READ_THRESHOLD;
1833 ch->write_threshold = DEFAULT_WRITE_THRESHOLD;
1834 ch->min_write_avail = DEFAULT_MIN_WRITE_THRESHOLD;
1835 ch->is_packet_mode = true;
1836 ch->peer_tx_buf_size = DEFAULT_PEER_TX_BUF_SIZE;
1837 ch->poll_delay_msec = 0;
1838
1839 ch->num = i;
1840
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001841 ch->func = sdio_al_dev->card->sdio_func[ch->num+1];
1842 ch->rx_pipe_index = ch->num*2;
1843 ch->tx_pipe_index = ch->num*2+1;
1844
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001845 memset(ch->name, 0, sizeof(ch->name));
1846
1847 if (header->channel_names[i][0]) {
1848 memcpy(ch->name, SDIO_PREFIX,
1849 strlen(SDIO_PREFIX));
1850 memcpy(ch->name + strlen(SDIO_PREFIX),
1851 header->channel_names[i],
1852 PEER_CHANNEL_NAME_SIZE);
1853
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001854 ch->state = SDIO_CHANNEL_STATE_IDLE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001855 ch->sdio_al_dev = sdio_al_dev;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001856 } else {
1857 ch->state = SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001858 }
1859
Krishna Kondaa7af6062011-09-01 18:34:38 -07001860 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":Channel=%s, "
1861 "state=%d\n", ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001862 }
1863
1864 return 0;
1865
1866exit_err:
1867 sdio_al_get_into_err_state(sdio_al_dev);
1868 memset(header, 0, sizeof(*header));
1869
1870 return -EIO;
1871}
1872
1873/**
1874 * Read SDIO-Client channel configuration
1875 *
1876 */
1877static int read_sdioc_channel_config(struct sdio_channel *ch)
1878{
1879 int ret;
1880 struct peer_sdioc_sw_mailbox *sw_mailbox = NULL;
1881 struct peer_sdioc_channel_config *ch_config = NULL;
1882 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
1883
1884 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001885 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
1886 " for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001887 return -EINVAL;
1888 }
1889
1890 if (sdio_al_dev->sdioc_sw_header->version == 0)
1891 return -1;
1892
1893 pr_debug(MODULE_NAME ":reading sw mailbox %s channel.\n", ch->name);
1894
1895 sw_mailbox = kzalloc(sizeof(*sw_mailbox), GFP_KERNEL);
1896 if (sw_mailbox == NULL)
1897 return -ENOMEM;
1898
1899 ret = sdio_memcpy_fromio(ch->func, sw_mailbox,
1900 SDIOC_SW_MAILBOX_ADDR, sizeof(*sw_mailbox));
1901 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001902 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
1903 "sw mailbox.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001904 goto exit_err;
1905 }
1906
1907 ch_config = &sw_mailbox->ch_config[ch->num];
1908 memcpy(&ch->ch_config, ch_config,
1909 sizeof(struct peer_sdioc_channel_config));
1910
1911 if (!ch_config->is_ready) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001912 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sw mailbox "
1913 "channel not ready.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001914 goto exit_err;
1915 }
1916
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001917 /* Aggregation up to 90% of the maximum size */
1918 ch->read_threshold = (ch_config->max_rx_threshold * 9) / 10;
1919 /* Threshold on 50% of the maximum size , sdioc uses double-buffer */
1920 ch->write_threshold = (ch_config->max_tx_threshold * 5) / 10;
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001921 ch->threshold_change_cnt = ch->ch_config.max_rx_threshold -
1922 ch->read_threshold + THRESHOLD_CHANGE_EXTRA_BYTES;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001923
1924 ch->def_read_threshold = ch->read_threshold;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001925 ch->is_packet_mode = ch_config->is_packet_mode;
1926 if (!ch->is_packet_mode) {
1927 ch->poll_delay_msec = DEFAULT_POLL_DELAY_NOPACKET_MSEC;
1928 ch->min_write_avail = DEFAULT_MIN_WRITE_THRESHOLD_STREAMING;
1929 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001930 /* The max_packet_size is set by the modem in version 3 and on */
1931 if (sdio_al->sdioc_major > PEER_SDIOC_OLD_VERSION_MAJOR)
1932 ch->min_write_avail = ch_config->max_packet_size;
1933
1934 if (ch->min_write_avail > ch->write_threshold)
1935 ch->min_write_avail = ch->write_threshold;
1936
Maya Erez7ad06d82011-10-02 15:47:57 +02001937 CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":ch %s "
Krishna Kondaa7af6062011-09-01 18:34:38 -07001938 "read_threshold=%d, write_threshold=%d,"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001939 " min_write_avail=%d, max_rx_threshold=%d,"
1940 " max_tx_threshold=%d\n", ch->name, ch->read_threshold,
1941 ch->write_threshold, ch->min_write_avail,
1942 ch_config->max_rx_threshold,
1943 ch_config->max_tx_threshold);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001944
1945 ch->peer_tx_buf_size = ch_config->tx_buf_size;
1946
1947 kfree(sw_mailbox);
1948
1949 return 0;
1950
1951exit_err:
Krishna Kondaa7af6062011-09-01 18:34:38 -07001952 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":Reading SW Mailbox "
1953 "error.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001954 kfree(sw_mailbox);
1955
1956 return -1;
1957}
1958
1959
1960/**
1961 * Enable/Disable EOT interrupt of a pipe.
1962 *
1963 */
1964static int enable_eot_interrupt(struct sdio_al_device *sdio_al_dev,
1965 int pipe_index, int enable)
1966{
1967 int ret = 0;
1968 struct sdio_func *func1;
1969 u32 mask;
1970 u32 pipe_mask;
1971 u32 addr;
1972
1973 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1974 return -ENODEV;
1975 func1 = sdio_al_dev->card->sdio_func[0];
1976
1977 if (pipe_index < 8) {
1978 addr = PIPES_0_7_IRQ_MASK_ADDR;
1979 pipe_mask = (1<<pipe_index);
1980 } else {
1981 addr = PIPES_8_15_IRQ_MASK_ADDR;
1982 pipe_mask = (1<<(pipe_index-8));
1983 }
1984
1985 mask = sdio_readl(func1, addr, &ret);
1986 if (ret) {
1987 pr_debug(MODULE_NAME ":enable_eot_interrupt fail\n");
1988 goto exit_err;
1989 }
1990
1991 if (enable)
1992 mask &= (~pipe_mask); /* 0 = enable */
1993 else
1994 mask |= (pipe_mask); /* 1 = disable */
1995
1996 sdio_writel(func1, mask, addr, &ret);
1997
1998exit_err:
1999 return ret;
2000}
2001
2002
2003/**
2004 * Enable/Disable mask interrupt of a function.
2005 *
2006 */
2007static int enable_mask_irq(struct sdio_al_device *sdio_al_dev,
2008 int func_num, int enable, u8 bit_offset)
2009{
2010 int ret = 0;
2011 struct sdio_func *func1 = NULL;
2012 u32 mask = 0;
2013 u32 func_mask = 0;
2014 u32 addr = 0;
2015 u32 offset = 0;
2016
2017 if (sdio_al_verify_dev(sdio_al_dev, __func__))
2018 return -ENODEV;
2019 func1 = sdio_al_dev->card->sdio_func[0];
2020
2021 if (func_num < 4) {
2022 addr = FUNC_1_4_MASK_IRQ_ADDR;
2023 offset = func_num * 8 + bit_offset;
2024 } else {
2025 addr = FUNC_5_7_MASK_IRQ_ADDR;
2026 offset = (func_num - 4) * 8 + bit_offset;
2027 }
2028
2029 func_mask = 1<<offset;
2030
2031 mask = sdio_readl(func1, addr, &ret);
2032 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002033 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2034 "enable_mask_irq fail\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002035 goto exit_err;
2036 }
2037
2038 if (enable)
2039 mask &= (~func_mask); /* 0 = enable */
2040 else
2041 mask |= (func_mask); /* 1 = disable */
2042
2043 pr_debug(MODULE_NAME ":enable_mask_irq, writing mask = 0x%x\n", mask);
2044
2045 sdio_writel(func1, mask, addr, &ret);
2046
2047exit_err:
2048 return ret;
2049}
2050
2051/**
2052 * Enable/Disable Threshold interrupt of a pipe.
2053 *
2054 */
2055static int enable_threshold_interrupt(struct sdio_al_device *sdio_al_dev,
2056 int pipe_index, int enable)
2057{
2058 int ret = 0;
2059 struct sdio_func *func1;
2060 u32 mask;
2061 u32 pipe_mask;
2062 u32 addr;
2063
2064 if (sdio_al_verify_dev(sdio_al_dev, __func__))
2065 return -ENODEV;
2066 func1 = sdio_al_dev->card->sdio_func[0];
2067
2068 if (pipe_index < 8) {
2069 addr = PIPES_0_7_IRQ_MASK_ADDR;
2070 pipe_mask = (1<<pipe_index);
2071 } else {
2072 addr = PIPES_8_15_IRQ_MASK_ADDR;
2073 pipe_mask = (1<<(pipe_index-8));
2074 }
2075
2076 mask = sdio_readl(func1, addr, &ret);
2077 if (ret) {
2078 pr_debug(MODULE_NAME ":enable_threshold_interrupt fail\n");
2079 goto exit_err;
2080 }
2081
2082 pipe_mask = pipe_mask<<8; /* Threshold bits 8..15 */
2083 if (enable)
2084 mask &= (~pipe_mask); /* 0 = enable */
2085 else
2086 mask |= (pipe_mask); /* 1 = disable */
2087
2088 sdio_writel(func1, mask, addr, &ret);
2089
2090exit_err:
2091 return ret;
2092}
2093
2094/**
2095 * Set the threshold to trigger interrupt from SDIO-Card on
2096 * pipe available bytes.
2097 *
2098 */
2099static int set_pipe_threshold(struct sdio_al_device *sdio_al_dev,
2100 int pipe_index, int threshold)
2101{
2102 int ret = 0;
2103 struct sdio_func *func1;
2104
2105 if (sdio_al_verify_dev(sdio_al_dev, __func__))
2106 return -ENODEV;
2107 func1 = sdio_al_dev->card->sdio_func[0];
2108
2109 sdio_writel(func1, threshold,
2110 PIPES_THRESHOLD_ADDR+pipe_index*4, &ret);
2111 if (ret)
Krishna Kondaa7af6062011-09-01 18:34:38 -07002112 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2113 "set_pipe_threshold err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002114
2115 return ret;
2116}
2117
2118/**
2119 * Enable func w/ retries
2120 *
2121 */
2122static int sdio_al_enable_func_retry(struct sdio_func *func, const char *name)
2123{
2124 int ret, i;
2125 for (i = 0; i < 200; i++) {
2126 ret = sdio_enable_func(func);
2127 if (ret) {
2128 pr_debug(MODULE_NAME ":retry enable %s func#%d "
2129 "ret=%d\n",
2130 name, func->num, ret);
2131 msleep(10);
2132 } else
2133 break;
2134 }
2135
2136 return ret;
2137}
2138
2139/**
2140 * Open Channel
2141 *
2142 * 1. Init Channel Context.
2143 * 2. Init the Channel SDIO-Function.
2144 * 3. Init the Channel Pipes on Mailbox.
2145 */
2146static int open_channel(struct sdio_channel *ch)
2147{
2148 int ret = 0;
2149 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
2150
2151 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002152 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL "
2153 "sdio_al_dev for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002154 return -EINVAL;
2155 }
2156
2157 /* Init channel Context */
2158 /** Func#1 is reserved for mailbox */
2159 ch->func = sdio_al_dev->card->sdio_func[ch->num+1];
2160 ch->rx_pipe_index = ch->num*2;
2161 ch->tx_pipe_index = ch->num*2+1;
2162 ch->signature = SDIO_AL_SIGNATURE;
2163
2164 ch->total_rx_bytes = 0;
2165 ch->total_tx_bytes = 0;
2166
2167 ch->write_avail = 0;
2168 ch->read_avail = 0;
2169 ch->rx_pending_bytes = 0;
2170
2171 mutex_init(&ch->ch_lock);
2172
2173 pr_debug(MODULE_NAME ":open_channel %s func#%d\n",
2174 ch->name, ch->func->num);
2175
2176 INIT_LIST_HEAD(&(ch->rx_size_list_head));
2177
2178 /* Init SDIO Function */
2179 ret = sdio_al_enable_func_retry(ch->func, ch->name);
2180 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002181 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2182 "sdio_enable_func() err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002183 goto exit_err;
2184 }
2185
2186 /* Note: Patch Func CIS tuple issue */
2187 ret = sdio_set_block_size(ch->func, SDIO_AL_BLOCK_SIZE);
2188 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002189 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2190 "sdio_set_block_size()failed, err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002191 goto exit_err;
2192 }
2193
2194 ch->func->max_blksize = SDIO_AL_BLOCK_SIZE;
2195
2196 sdio_set_drvdata(ch->func, ch);
2197
2198 /* Get channel parameters from the peer SDIO-Client */
2199 read_sdioc_channel_config(ch);
2200
2201 /* Set Pipes Threshold on Mailbox */
2202 ret = set_pipe_threshold(sdio_al_dev,
2203 ch->rx_pipe_index, ch->read_threshold);
2204 if (ret)
2205 goto exit_err;
2206 ret = set_pipe_threshold(sdio_al_dev,
2207 ch->tx_pipe_index, ch->write_threshold);
2208 if (ret)
2209 goto exit_err;
2210
2211 /* Set flag before interrupts are enabled to allow notify */
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002212 ch->state = SDIO_CHANNEL_STATE_OPEN;
2213 pr_debug(MODULE_NAME ":channel %s is in OPEN state now\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002214
2215 sdio_al_dev->poll_delay_msec = get_min_poll_time_msec(sdio_al_dev);
2216
2217 /* lpm mechanism lives under the assumption there is always a timer */
2218 /* Check if need to start the timer */
2219 if ((sdio_al_dev->poll_delay_msec) &&
2220 (sdio_al_dev->is_timer_initialized == false)) {
2221
2222 init_timer(&sdio_al_dev->timer);
2223 sdio_al_dev->timer.data = (unsigned long) sdio_al_dev;
2224 sdio_al_dev->timer.function = sdio_al_timer_handler;
2225 sdio_al_dev->timer.expires = jiffies +
2226 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2227 add_timer(&sdio_al_dev->timer);
2228 sdio_al_dev->is_timer_initialized = true;
2229 }
2230
2231 /* Enable Pipes Interrupts */
2232 enable_eot_interrupt(sdio_al_dev, ch->rx_pipe_index, true);
2233 enable_eot_interrupt(sdio_al_dev, ch->tx_pipe_index, true);
2234
2235 enable_threshold_interrupt(sdio_al_dev, ch->rx_pipe_index, true);
2236 enable_threshold_interrupt(sdio_al_dev, ch->tx_pipe_index, true);
2237
2238exit_err:
2239
2240 return ret;
2241}
2242
2243/**
2244 * Ask the worker to read the mailbox.
2245 */
2246static void ask_reading_mailbox(struct sdio_al_device *sdio_al_dev)
2247{
2248 if (!sdio_al_dev->ask_mbox) {
2249 pr_debug(MODULE_NAME ":ask_reading_mailbox for card %d\n",
2250 sdio_al_dev->card->host->index);
2251 sdio_al_dev->ask_mbox = true;
2252 wake_up(&sdio_al_dev->wait_mbox);
2253 }
2254}
2255
2256/**
2257 * Start the timer
2258 */
2259static void start_timer(struct sdio_al_device *sdio_al_dev)
2260{
2261 if ((sdio_al_dev->poll_delay_msec) &&
2262 (sdio_al_dev->state == CARD_INSERTED)) {
2263 sdio_al_dev->timer.expires = jiffies +
2264 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2265 add_timer(&sdio_al_dev->timer);
2266 }
2267}
2268
2269/**
2270 * Restart(postpone) the already working timer
2271 */
2272static void restart_timer(struct sdio_al_device *sdio_al_dev)
2273{
2274 if ((sdio_al_dev->poll_delay_msec) &&
2275 (sdio_al_dev->state == CARD_INSERTED)) {
2276 ulong expires = jiffies +
2277 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2278 mod_timer(&sdio_al_dev->timer, expires);
2279 }
2280}
2281
2282/**
2283 * Do the wakup sequence.
2284 * This function should be called after claiming the host!
2285 * The caller is responsible for releasing the host.
2286 *
2287 * Wake up sequence
2288 * 1. Get lock
2289 * 2. Enable wake up function if needed
2290 * 3. Mark NOT OK to sleep and write it
2291 * 4. Restore default thresholds
2292 * 5. Start the mailbox and inactivity timer again
2293 */
2294static int sdio_al_wake_up(struct sdio_al_device *sdio_al_dev,
Maya Erez7b1ebd22011-08-20 20:53:24 +03002295 u32 not_from_int, struct sdio_channel *ch)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002296{
Maya Erez8ed0a9a2011-07-19 14:46:53 +03002297 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002298 struct sdio_func *wk_func =
2299 sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
2300 unsigned long time_to_wait;
2301 struct mmc_host *host = wk_func->card->host;
2302
2303 if (sdio_al_dev->is_err) {
2304 SDIO_AL_ERR(__func__);
2305 return -ENODEV;
2306 }
2307
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002308 if (!sdio_al_dev->is_ok_to_sleep) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002309 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":card %d already"
2310 " awake, no need to wake up\n",
2311 sdio_al_dev->card->host->index);
2312 return 0;
2313 }
2314
2315 if (!sdio_al_dev->is_ok_to_sleep) {
2316 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":card %d "
2317 "already awake, no need to wake up\n",
2318 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002319 return 0;
2320 }
Maya Erez7b1ebd22011-08-20 20:53:24 +03002321
2322 /* Wake up sequence */
2323 if (not_from_int) {
2324 if (ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002325 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up"
2326 " card %d (not by interrupt), ch %s",
2327 sdio_al_dev->card->host->index,
2328 ch->name);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002329 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002330 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up"
2331 " card %d (not by interrupt)",
2332 sdio_al_dev->card->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002333 }
2334 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002335 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up card "
2336 "%d by interrupt",
2337 sdio_al_dev->card->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002338 sdio_al_dev->print_after_interrupt = 1;
2339 }
2340
Yaniv Gardi3e327762011-07-27 11:11:04 +03002341 sdio_al_vote_for_sleep(sdio_al_dev, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002342
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002343 msmsdcc_lpm_disable(host);
2344 msmsdcc_set_pwrsave(sdio_al_dev->card->host, 0);
2345 /* Poll the GPIO */
2346 time_to_wait = jiffies + msecs_to_jiffies(1000);
2347 while (time_before(jiffies, time_to_wait)) {
2348 if (sdio_al->pdata->get_mdm2ap_status())
2349 break;
2350 udelay(TIME_TO_WAIT_US);
2351 }
Yaniv Gardi3e327762011-07-27 11:11:04 +03002352
Maya Erez7b1ebd22011-08-20 20:53:24 +03002353 pr_debug(MODULE_NAME ":GPIO mdm2ap_status=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002354 sdio_al->pdata->get_mdm2ap_status());
2355
2356 /* Here get_mdm2ap_status() returning 0 is not an error condition */
2357 if (sdio_al->pdata->get_mdm2ap_status() == 0)
Krishna Kondaa7af6062011-09-01 18:34:38 -07002358 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": "
2359 "get_mdm2ap_status() is 0\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002360
2361 /* Enable Wake up Function */
2362 ret = sdio_al_enable_func_retry(wk_func, "wakeup func");
2363 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002364 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2365 "sdio_enable_func() err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002366 goto error_exit;
2367 }
2368 /* Mark NOT OK_TOSLEEP */
2369 sdio_al_dev->is_ok_to_sleep = 0;
2370 ret = write_lpm_info(sdio_al_dev);
2371 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002372 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2373 "write_lpm_info() failed, err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002374 sdio_al_dev->is_ok_to_sleep = 1;
2375 sdio_disable_func(wk_func);
2376 goto error_exit;
2377 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002378 sdio_disable_func(wk_func);
2379
2380 /* Start the timer again*/
2381 restart_inactive_time(sdio_al_dev);
2382 sdio_al_dev->poll_delay_msec = get_min_poll_time_msec(sdio_al_dev);
2383 start_timer(sdio_al_dev);
2384
Krishna Kondaa7af6062011-09-01 18:34:38 -07002385 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME "Finished Wake up sequence"
2386 " for card %d", sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002387
2388 msmsdcc_set_pwrsave(sdio_al_dev->card->host, 1);
2389 pr_debug(MODULE_NAME ":Turn clock off\n");
2390
2391 return ret;
2392error_exit:
2393 sdio_al_vote_for_sleep(sdio_al_dev, 1);
2394 msmsdcc_set_pwrsave(sdio_al_dev->card->host, 1);
2395 WARN_ON(ret);
2396 sdio_al_get_into_err_state(sdio_al_dev);
2397 return ret;
2398}
2399
2400
2401/**
2402 * SDIO Function Interrupt handler.
2403 *
2404 * Interrupt shall be triggered by SDIO-Client when:
2405 * 1. End-Of-Transfer (EOT) detected in packet mode.
2406 * 2. Bytes-available reached the threshold.
2407 *
2408 * Reading the mailbox clears the EOT/Threshold interrupt
2409 * source.
2410 * The interrupt source should be cleared before this ISR
2411 * returns. This ISR is called from IRQ Thread and not
2412 * interrupt, so it may sleep.
2413 *
2414 */
2415static void sdio_func_irq(struct sdio_func *func)
2416{
2417 struct sdio_al_device *sdio_al_dev = sdio_get_drvdata(func);
2418
2419 pr_debug(MODULE_NAME ":start %s.\n", __func__);
2420
2421 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002422 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
2423 " for card %d\n", func->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002424 return;
2425 }
2426
2427 if (sdio_al_dev->is_ok_to_sleep)
Maya Erez7b1ebd22011-08-20 20:53:24 +03002428 sdio_al_wake_up(sdio_al_dev, 0, NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002429 else
2430 restart_timer(sdio_al_dev);
2431
2432 read_mailbox(sdio_al_dev, true);
2433
2434 pr_debug(MODULE_NAME ":end %s.\n", __func__);
2435}
2436
2437/**
2438 * Timer Expire Handler
2439 *
2440 */
2441static void sdio_al_timer_handler(unsigned long data)
2442{
2443 struct sdio_al_device *sdio_al_dev = (struct sdio_al_device *)data;
2444 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002445 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": NULL "
2446 "sdio_al_dev for data %lu\n", data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002447 return;
2448 }
2449 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002450 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": sdio_al_dev "
2451 "is in invalid state %d\n", sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002452 return;
2453 }
2454 pr_debug(MODULE_NAME " Timer Expired\n");
2455
2456 ask_reading_mailbox(sdio_al_dev);
2457
2458 restart_timer(sdio_al_dev);
2459}
2460
2461/**
2462 * Driver Setup.
2463 *
2464 */
2465static int sdio_al_setup(struct sdio_al_device *sdio_al_dev)
2466{
2467 int ret = 0;
2468 struct mmc_card *card = sdio_al_dev->card;
2469 struct sdio_func *func1 = NULL;
2470 int i = 0;
2471 int fn = 0;
2472
2473 if (card == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002474 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2475 "sdio_al_setup: No Card detected\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002476 return -ENODEV;
2477 }
2478
2479
Krishna Kondaa7af6062011-09-01 18:34:38 -07002480 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_setup for "
2481 "card %d\n", sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002482
2483 func1 = card->sdio_func[0];
2484
2485 ret = sdio_al->pdata->config_mdm2ap_status(1);
2486 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002487 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME "Could not "
2488 "request GPIO\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002489 return ret;
2490 }
2491
2492 INIT_WORK(&sdio_al_dev->sdio_al_work.work, worker);
2493 /* disable all pipes interrupts before claim irq.
2494 since all are enabled by default. */
2495 for (i = 0 ; i < SDIO_AL_MAX_PIPES; i++) {
2496 enable_eot_interrupt(sdio_al_dev, i, false);
2497 enable_threshold_interrupt(sdio_al_dev, i, false);
2498 }
2499
2500 /* Disable all SDIO Functions before claim irq. */
2501 for (fn = 1 ; fn <= card->sdio_funcs; fn++)
2502 sdio_disable_func(card->sdio_func[fn-1]);
2503
2504 sdio_set_drvdata(func1, sdio_al_dev);
Krishna Kondaa7af6062011-09-01 18:34:38 -07002505 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":claim IRQ for card "
2506 "%d\n", card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002507
2508 ret = sdio_claim_irq(func1, sdio_func_irq);
2509 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002510 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to claim"
2511 " IRQ for card %d\n",
2512 card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002513 goto exit_err;
2514 }
2515
2516 sdio_al_dev->is_ready = true;
2517
2518 /* Start worker before interrupt might happen */
2519 queue_work(sdio_al_dev->workqueue, &sdio_al_dev->sdio_al_work.work);
2520
2521 start_inactive_time(sdio_al_dev);
2522
2523 pr_debug(MODULE_NAME ":Ready.\n");
2524
2525 return 0;
2526
2527exit_err:
2528 sdio_release_host(func1);
Krishna Kondaa7af6062011-09-01 18:34:38 -07002529 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Setup Failure.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002530
2531 return ret;
2532}
2533
2534/**
2535 * Driver Tear-Down.
2536 *
2537 */
2538static void sdio_al_tear_down(void)
2539{
2540 int i;
2541 struct sdio_al_device *sdio_al_dev = NULL;
2542 struct sdio_func *func1;
2543
2544 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
2545 if (sdio_al->devices[i] == NULL)
2546 continue;
2547 sdio_al_dev = sdio_al->devices[i];
2548
2549 if (sdio_al_dev->is_ready) {
2550 sdio_al_dev->is_ready = false; /* Flag worker to exit */
2551 sdio_al_dev->ask_mbox = false;
2552 ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
2553 /* allow gracefully exit of the worker thread */
2554 msleep(100);
2555
2556 flush_workqueue(sdio_al_dev->workqueue);
2557 destroy_workqueue(sdio_al_dev->workqueue);
2558
2559 sdio_al_vote_for_sleep(sdio_al_dev, 1);
2560
2561 if (sdio_al_verify_func1(sdio_al_dev, __func__)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002562 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2563 ": %s: Invalid func1",
2564 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002565 return;
2566 }
2567 func1 = sdio_al_dev->card->sdio_func[0];
2568
2569 sdio_claim_host(func1);
2570 sdio_release_irq(func1);
2571 sdio_disable_func(func1);
2572 sdio_release_host(func1);
2573 }
2574 }
2575
2576 sdio_al->pdata->config_mdm2ap_status(0);
2577}
2578
2579/**
2580 * Find channel by name.
2581 *
2582 */
2583static struct sdio_channel *find_channel_by_name(const char *name)
2584{
2585 struct sdio_channel *ch = NULL;
2586 int i, j;
2587 struct sdio_al_device *sdio_al_dev = NULL;
2588
2589 for (j = 0; j < MAX_NUM_OF_SDIO_DEVICES; ++j) {
2590 if (sdio_al->devices[j] == NULL)
2591 continue;
2592 sdio_al_dev = sdio_al->devices[j];
2593 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002594 if (sdio_al_dev->channel[i].state ==
2595 SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002596 continue;
2597 if (strcmp(sdio_al_dev->channel[i].name, name) == 0) {
2598 ch = &sdio_al_dev->channel[i];
2599 break;
2600 }
2601 }
2602 if (ch != NULL)
2603 break;
2604 }
2605
2606 return ch;
2607}
2608
2609/**
2610 * Find the minimal poll time.
2611 *
2612 */
2613static int get_min_poll_time_msec(struct sdio_al_device *sdio_sl_dev)
2614{
2615 int i;
2616 int poll_delay_msec = 0x0FFFFFFF;
2617
2618 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++)
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002619 if ((sdio_sl_dev->channel[i].state ==
2620 SDIO_CHANNEL_STATE_OPEN) &&
2621 (sdio_sl_dev->channel[i].poll_delay_msec > 0) &&
2622 (sdio_sl_dev->channel[i].poll_delay_msec < poll_delay_msec))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002623 poll_delay_msec =
2624 sdio_sl_dev->channel[i].poll_delay_msec;
2625
2626 if (poll_delay_msec == 0x0FFFFFFF)
2627 poll_delay_msec = SDIO_AL_POLL_TIME_NO_STREAMING;
2628
2629 pr_debug(MODULE_NAME ":poll delay time is %d msec\n", poll_delay_msec);
2630
2631 return poll_delay_msec;
2632}
2633
2634/**
2635 * Open SDIO Channel.
2636 *
2637 * Enable the channel.
2638 * Set the channel context.
2639 * Trigger reading the mailbox to check available bytes.
2640 *
2641 */
2642int sdio_open(const char *name, struct sdio_channel **ret_ch, void *priv,
2643 void (*notify)(void *priv, unsigned ch_event))
2644{
2645 int ret = 0;
2646 struct sdio_channel *ch = NULL;
2647 struct sdio_al_device *sdio_al_dev = NULL;
2648
2649 *ret_ch = NULL; /* default */
2650
2651 ch = find_channel_by_name(name);
2652 if (ch == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002653 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":Can't find "
2654 "channel name %s\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002655 return -EINVAL;
2656 }
2657
2658 sdio_al_dev = ch->sdio_al_dev;
2659 if (sdio_al_verify_dev(sdio_al_dev, __func__))
2660 return -ENODEV;
2661
2662 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
2663
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002664 if ((ch->state != SDIO_CHANNEL_STATE_IDLE) &&
2665 (ch->state != SDIO_CHANNEL_STATE_CLOSED)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002666 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Wrong ch %s "
2667 "state %d\n", name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002668 ret = -EPERM;
2669 goto exit_err;
2670 }
2671
2672 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002673 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2674 "sdio_al_dev is in invalid state %d\n",
2675 __func__, sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002676 ret = -ENODEV;
2677 goto exit_err;
2678 }
2679
2680 if (sdio_al_dev->is_err) {
2681 SDIO_AL_ERR(__func__);
2682 ret = -ENODEV;
2683 goto exit_err;
2684 }
2685
Maya Erez7b1ebd22011-08-20 20:53:24 +03002686 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002687 if (ret)
2688 goto exit_err;
2689
2690 ch->notify = notify;
2691 ch->priv = priv;
2692
2693 /* Note: Set caller returned context before interrupts are enabled */
2694 *ret_ch = ch;
2695
2696 ret = open_channel(ch);
2697 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002698 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_open %s "
2699 "err=%d\n", name, -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002700 goto exit_err;
2701 }
2702
Maya Erez7ad06d82011-10-02 15:47:57 +02002703 CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":sdio_open %s "
2704 "completed OK\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002705 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
2706 if (sdio_al->sdioc_major == PEER_SDIOC_OLD_VERSION_MAJOR) {
2707 if (!ch->is_packet_mode) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002708 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME
2709 ":setting channel %s as "
2710 "lpm_chan\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002711 sdio_al_dev->lpm_chan = ch->num;
2712 }
2713 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002714 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": "
2715 "setting channel %s as lpm_chan\n",
2716 name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002717 sdio_al_dev->lpm_chan = ch->num;
2718 }
2719 }
2720
2721exit_err:
2722 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2723 return ret;
2724}
2725EXPORT_SYMBOL(sdio_open);
2726
2727/**
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002728 * Request peer operation
2729 * note: sanity checks of parameters done by caller
2730 * called under bus locked
2731 */
2732static int peer_set_operation(u32 opcode,
2733 struct sdio_al_device *sdio_al_dev,
2734 struct sdio_channel *ch)
2735{
2736 int ret;
2737 int offset;
2738 struct sdio_func *wk_func;
2739 u32 peer_operation;
2740 int loop_count = 0;
2741
2742 wk_func = sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
2743 if (!wk_func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002744 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: NULL "
2745 "wakeup func:%d\n", __func__,
2746 SDIO_AL_WAKEUP_FUNC);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002747 ret = -ENODEV;
2748 goto exit;
2749 }
2750 /* calculate offset of peer_operation field in sw mailbox struct */
2751 offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config) +
2752 sizeof(struct peer_sdioc_channel_config) * ch->num +
2753 offsetof(struct peer_sdioc_channel_config, peer_operation);
2754
Maya Erez7b1ebd22011-08-20 20:53:24 +03002755 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002756 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002757 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
2758 "wake up\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002759 goto exit;
2760 }
2761 /* request operation from MDM peer */
2762 peer_operation = PEER_OPERATION(opcode, PEER_OP_STATE_INIT);
2763 ret = sdio_memcpy_toio(ch->func, SDIOC_SW_MAILBOX_ADDR+offset,
2764 &peer_operation, sizeof(u32));
2765 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002766 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
2767 "request close operation\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002768 goto exit;
2769 }
2770 ret = sdio_al_enable_func_retry(wk_func, "wk_func");
2771 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002772 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to enable"
2773 " Func#%d\n", wk_func->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002774 goto exit;
2775 }
2776 pr_debug(MODULE_NAME ":%s: wk_func enabled on ch %s\n",
2777 __func__, ch->name);
2778 /* send "start" operation to MDM */
2779 peer_operation = PEER_OPERATION(opcode, PEER_OP_STATE_START);
2780 ret = sdio_memcpy_toio(ch->func, SDIOC_SW_MAILBOX_ADDR+offset,
2781 &peer_operation, sizeof(u32));
2782 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002783 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
2784 "send start close operation\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002785 goto exit;
2786 }
2787 ret = sdio_disable_func(wk_func);
2788 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002789 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
2790 "disable Func#%d\n", wk_func->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002791 goto exit;
2792 }
2793 /* poll for peer operation ack */
2794 while (peer_operation != 0) {
2795 ret = sdio_memcpy_fromio(ch->func,
2796 &peer_operation,
2797 SDIOC_SW_MAILBOX_ADDR+offset,
2798 sizeof(u32));
2799 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002800 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2801 ":failed to request ack on close"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002802 " operation, loop_count = %d\n",
2803 loop_count);
2804 goto exit;
2805 }
2806 loop_count++;
2807 if (loop_count > 10) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002808 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2809 "peer_operation=0x%x wait loop"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002810 " %d on ch %s\n", __func__,
2811 peer_operation, loop_count, ch->name);
2812 }
2813 }
2814exit:
2815 return ret;
2816}
2817
Konstantin Dorfman52890522011-10-05 11:03:19 +02002818static int channel_close(struct sdio_channel *ch, int flush_flag)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002819{
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002820 int ret;
2821 struct sdio_al_device *sdio_al_dev = NULL;
Konstantin Dorfman52890522011-10-05 11:03:19 +02002822 struct sdio_func *func1 = NULL;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002823 int flush_len;
2824 ulong flush_expires;
2825
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002826 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002827 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
2828 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002829 return -ENODEV;
2830 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002831 sdio_al_dev = ch->sdio_al_dev;
2832 if (sdio_al_verify_dev(sdio_al_dev, __func__))
2833 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002834
Maya Erezc29f2912011-08-22 14:32:13 +03002835 if (!sdio_al_dev->ch_close_supported) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002836 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: Not "
2837 "supported by mdm, ch %s\n",
2838 __func__, ch->name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002839 return -ENOTSUPP;
2840 }
2841
2842 if (!ch->func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002843 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: NULL func"
2844 " on channel:%d\n", __func__, ch->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002845 return -ENODEV;
2846 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02002847 func1 = sdio_al_dev->card->sdio_func[0];
2848 sdio_claim_host(func1);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002849
2850 if (sdio_al_dev->is_err) {
2851 SDIO_AL_ERR(__func__);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002852 ret = -ENODEV;
2853 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002854 }
2855 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002856 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2857 "sdio_al_dev is in invalid state %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002858 __func__, sdio_al_dev->state);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002859 ret = -ENODEV;
2860 goto error_exit;
2861 }
2862 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
2863 sdio_al_loge(sdio_al_dev->dev_log,
2864 MODULE_NAME ":%s: ch %s is not in "
2865 "open state (%d)\n",
2866 __func__, ch->name, ch->state);
2867 ret = -ENODEV;
2868 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002869 }
2870 ch->state = SDIO_CHANNEL_STATE_CLOSING;
2871 ret = peer_set_operation(PEER_OP_CODE_CLOSE, sdio_al_dev, ch);
2872 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002873 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2874 "peer_set_operation() failed: %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002875 __func__, ret);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002876 ret = -ENODEV;
2877 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002878 }
2879 /* udate poll time for opened channels */
2880 if (ch->poll_delay_msec > 0) {
2881 sdio_al_dev->poll_delay_msec =
2882 get_min_poll_time_msec(sdio_al_dev);
2883 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02002884 sdio_release_host(func1);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002885
2886 flush_expires = jiffies +
2887 msecs_to_jiffies(SDIO_CLOSE_FLUSH_TIMEOUT_MSEC);
2888 /* flush rx packets of the channel */
Konstantin Dorfman52890522011-10-05 11:03:19 +02002889 if (flush_flag) {
2890 do {
2891 while (ch->read_avail > 0) {
2892 flush_len = ch->read_avail;
2893 ret = sdio_read_internal(ch,
2894 sdio_al_dev->rx_flush_buf,
2895 flush_len);
2896 if (ret) {
2897 sdio_al_loge(&sdio_al->gen_log,
2898 MODULE_NAME ":%s sdio_read"
2899 " failed: %d, ch %s\n",
2900 __func__, ret,
2901 ch->name);
2902 return ret;
2903 }
Yaniv Gardic4663632011-08-31 19:55:38 +03002904
Konstantin Dorfman52890522011-10-05 11:03:19 +02002905 if (time_after(jiffies, flush_expires) != 0) {
2906 sdio_al_loge(&sdio_al->gen_log,
2907 MODULE_NAME ":%s flush rx "
2908 "packets timeout: ch %s\n",
Krishna Kondaa7af6062011-09-01 18:34:38 -07002909 __func__, ch->name);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002910 sdio_al_get_into_err_state(sdio_al_dev);
2911 return -EBUSY;
2912 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002913 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02002914 msleep(100);
2915 if (ch->signature != SDIO_AL_SIGNATURE) {
2916 sdio_al_loge(&sdio_al->gen_log,
2917 MODULE_NAME ":%s: after sleep,"
2918 " invalid signature"
2919 " 0x%x\n", __func__,
2920 ch->signature);
2921 return -ENODEV;
2922 }
2923 if (sdio_al_verify_dev(ch->sdio_al_dev, __func__))
2924 return -ENODEV;
2925 sdio_claim_host(func1);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002926
Konstantin Dorfman52890522011-10-05 11:03:19 +02002927 ret = read_mailbox(sdio_al_dev, false);
2928 if (ret) {
2929 sdio_al_loge(&sdio_al->gen_log,
2930 MODULE_NAME ":%s: failed to"
2931 " read mailbox", __func__);
2932 goto error_exit;
2933 }
2934 sdio_release_host(func1);
2935 } while (ch->read_avail > 0);
2936 }
2937 sdio_claim_host(func1);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002938 /* disable function to be able to open the channel again */
2939 ret = sdio_disable_func(ch->func);
2940 if (ret) {
Konstantin Dorfman52890522011-10-05 11:03:19 +02002941 sdio_al_loge(&sdio_al->gen_log,
2942 MODULE_NAME ":Fail to disable Func#%d\n",
2943 ch->func->num);
2944 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002945 }
2946 ch->state = SDIO_CHANNEL_STATE_CLOSED;
Maya Erez7ad06d82011-10-02 15:47:57 +02002947 CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":%s: Ch %s closed "
2948 "successfully\n", __func__, ch->name);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002949
2950error_exit:
2951 sdio_release_host(func1);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002952
2953 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002954}
Konstantin Dorfman52890522011-10-05 11:03:19 +02002955
2956/**
2957 * Close SDIO Channel.
2958 *
2959 */
2960int sdio_close(struct sdio_channel *ch)
2961{
2962 return channel_close(ch, true);
2963}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002964EXPORT_SYMBOL(sdio_close);
2965
2966/**
2967 * Get the number of available bytes to write.
2968 *
2969 */
2970int sdio_write_avail(struct sdio_channel *ch)
2971{
2972 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002973 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
2974 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002975 return -ENODEV;
2976 }
2977 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002978 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
2979 "Invalid signature 0x%x\n", __func__,
2980 ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002981 return -ENODEV;
2982 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002983 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002984 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2985 "channel %s state is not open (%d)\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002986 __func__, ch->name, ch->state);
2987 return -ENODEV;
2988 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002989 pr_debug(MODULE_NAME ":sdio_write_avail %s 0x%x\n",
2990 ch->name, ch->write_avail);
2991
2992 return ch->write_avail;
2993}
2994EXPORT_SYMBOL(sdio_write_avail);
2995
2996/**
2997 * Get the number of available bytes to read.
2998 *
2999 */
3000int sdio_read_avail(struct sdio_channel *ch)
3001{
3002 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003003 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3004 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003005 return -ENODEV;
3006 }
3007 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003008 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
3009 "Invalid signature 0x%x\n", __func__,
3010 ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003011 return -ENODEV;
3012 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003013 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003014 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
3015 "channel %s state is not open (%d)\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003016 __func__, ch->name, ch->state);
3017 return -ENODEV;
3018 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003019 pr_debug(MODULE_NAME ":sdio_read_avail %s 0x%x\n",
3020 ch->name, ch->read_avail);
3021
3022 return ch->read_avail;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003023}
3024EXPORT_SYMBOL(sdio_read_avail);
3025
Maya Erez5795e0d2011-09-12 20:20:06 +03003026static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len)
3027{
3028 int ret = 0;
3029 struct sdio_al_device *sdio_al_dev = NULL;
3030
3031 if (!ch) {
Konstantin Dorfman52890522011-10-05 11:03:19 +02003032 sdio_al_loge(ch->sdio_al_dev->dev_log,
3033 MODULE_NAME ":%s: NULL channel\n", __func__);
Maya Erez5795e0d2011-09-12 20:20:06 +03003034 return -ENODEV;
3035 }
3036
3037 sdio_al_dev = ch->sdio_al_dev;
3038
3039 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3040
3041 ret = sdio_memcpy_fromio(ch->func, sdio_al_dev->rx_flush_buf,
3042 PIPE_RX_FIFO_ADDR, len);
3043
3044 if (ret) {
Konstantin Dorfman52890522011-10-05 11:03:19 +02003045 sdio_al_loge(ch->sdio_al_dev->dev_log,
3046 MODULE_NAME ":ch %s: %s err=%d, len=%d\n",
Maya Erez5795e0d2011-09-12 20:20:06 +03003047 ch->name, __func__, -ret, len);
3048 sdio_al_dev->is_err = true;
3049 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3050 return ret;
3051 }
3052
3053 restart_inactive_time(sdio_al_dev);
3054
3055 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3056
3057 return 0;
3058}
3059
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003060/**
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003061 * Internal read from SDIO Channel.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003062 *
3063 * Reading from the pipe will trigger interrupt if there are
3064 * other pending packets on the SDIO-Client.
3065 *
3066 */
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003067static int sdio_read_internal(struct sdio_channel *ch, void *data, int len)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003068{
3069 int ret = 0;
3070 struct sdio_al_device *sdio_al_dev = NULL;
3071
3072 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003073 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3074 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003075 return -ENODEV;
3076 }
3077 if (!data) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003078 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
3079 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003080 return -ENODEV;
3081 }
3082 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003083 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
3084 " to read 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003085 return -EINVAL;
3086 }
3087
3088 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003089 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
3090 "signature 0x%x\n", __func__, ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003091 return -ENODEV;
3092 }
3093
3094 sdio_al_dev = ch->sdio_al_dev;
3095 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3096 return -ENODEV;
3097
3098 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3099
3100 if (sdio_al_dev->is_err) {
3101 SDIO_AL_ERR(__func__);
3102 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3103 return -ENODEV;
3104 }
3105
3106 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003107 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
3108 "sdio_al_dev is in invalid state %d\n",
3109 __func__, sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003110 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3111 return -ENODEV;
3112 }
3113
3114 /* lpm policy says we can't go to sleep when we have pending rx data,
3115 so either we had rx interrupt and woken up, or we never went to
3116 sleep */
3117 if (sdio_al_dev->is_ok_to_sleep) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003118 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: called "
3119 "when is_ok_to_sleep is set for ch %s, len=%d,"
3120 " last_any_read_avail=%d, last_read_avail=%d, "
3121 "last_old_read_avail=%d", __func__, ch->name,
3122 len, ch->statistics.last_any_read_avail,
3123 ch->statistics.last_read_avail,
3124 ch->statistics.last_old_read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003125 }
3126 BUG_ON(sdio_al_dev->is_ok_to_sleep);
3127
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003128 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
3129 (ch->state != SDIO_CHANNEL_STATE_CLOSING)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003130 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s wrong "
3131 "channel %s state %d\n",
3132 __func__, ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003133 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3134 return -EINVAL;
3135 }
3136
Krishna Kondaa7af6062011-09-01 18:34:38 -07003137 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s read %d "
3138 "avail %d.\n", ch->name, len, ch->read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003139
3140 restart_inactive_time(sdio_al_dev);
3141
3142 if ((ch->is_packet_mode) && (len != ch->read_avail)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003143 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_read ch "
3144 "%s len != read_avail\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003145 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3146 return -EINVAL;
3147 }
3148
3149 if (len > ch->read_avail) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003150 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
3151 "reading more bytes (%d) than the avail(%d).\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003152 ch->name, len, ch->read_avail);
3153 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3154 return -ENOMEM;
3155 }
3156
3157 ret = sdio_memcpy_fromio(ch->func, data, PIPE_RX_FIFO_ADDR, len);
3158
3159 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003160 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ch %s: "
3161 "sdio_read err=%d, len=%d, read_avail=%d, "
3162 "last_read_avail=%d, last_old_read_avail=%d\n",
Maya Erezd9cc2292011-08-04 09:20:31 +03003163 ch->name, -ret, len, ch->read_avail,
3164 ch->statistics.last_read_avail,
3165 ch->statistics.last_old_read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003166 sdio_al_dev->is_err = true;
3167 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3168 return ret;
3169 }
3170
3171 ch->statistics.total_read_times++;
3172
3173 /* Remove handled packet from the list regardless if ret is ok */
3174 if (ch->is_packet_mode)
3175 remove_handled_rx_packet(ch);
3176 else
3177 ch->read_avail -= len;
3178
3179 ch->total_rx_bytes += len;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003180 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s read %d "
3181 "avail %d total %d.\n", ch->name, len,
3182 ch->read_avail, ch->total_rx_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003183
3184 if ((ch->read_avail == 0) && !(ch->is_packet_mode))
3185 ask_reading_mailbox(sdio_al_dev);
3186
3187 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3188
3189 return ret;
3190}
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003191
3192/**
3193 * Read from SDIO Channel.
3194 *
3195 * Reading from the pipe will trigger interrupt if there are
3196 * other pending packets on the SDIO-Client.
3197 *
3198 */
3199int sdio_read(struct sdio_channel *ch, void *data, int len)
3200{
3201 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003202 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3203 "channel\n", __func__);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003204 return -ENODEV;
3205 }
3206 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003207 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
3208 "Invalid signature 0x%x\n", __func__, ch->signature);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003209 return -ENODEV;
3210 }
3211 if (ch->state == SDIO_CHANNEL_STATE_OPEN) {
3212 return sdio_read_internal(ch, data, len);
3213 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003214 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME
3215 ":%s: Invalid channel %s state %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003216 __func__, ch->name, ch->state);
3217 }
3218 return -ENODEV;
3219}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003220EXPORT_SYMBOL(sdio_read);
3221
3222/**
3223 * Write to SDIO Channel.
3224 *
3225 */
3226int sdio_write(struct sdio_channel *ch, const void *data, int len)
3227{
3228 int ret = 0;
3229 struct sdio_al_device *sdio_al_dev = NULL;
3230
3231 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003232 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3233 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003234 return -ENODEV;
3235 }
3236 if (!data) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003237 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
3238 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003239 return -ENODEV;
3240 }
3241 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003242 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
3243 " to write 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003244 return -EINVAL;
3245 }
3246
3247 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003248 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
3249 "signature 0x%x\n", __func__, ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003250 return -ENODEV;
3251 }
3252
3253 sdio_al_dev = ch->sdio_al_dev;
3254 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3255 return -ENODEV;
3256
3257 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3258
3259
3260 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003261 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3262 ":%s: sdio_al_dev is in invalid state %d\n",
3263 __func__, sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003264 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3265 return -ENODEV;
3266 }
3267 WARN_ON(len > ch->write_avail);
3268
3269 if (sdio_al_dev->is_err) {
3270 SDIO_AL_ERR(__func__);
3271 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3272 return -ENODEV;
3273 }
3274
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003275 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003276 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":writing to "
3277 "closed channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003278 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3279 return -EINVAL;
3280 }
3281
3282 if (sdio_al_dev->is_ok_to_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03003283 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003284 if (ret) {
3285 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3286 return ret;
3287 }
3288 } else {
3289 restart_inactive_time(sdio_al_dev);
3290 }
3291
Krishna Kondaa7af6062011-09-01 18:34:38 -07003292 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s write %d "
3293 "avail %d.\n", ch->name, len, ch->write_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003294
3295 if (len > ch->write_avail) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003296 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
3297 "write more bytes (%d) than available %d.\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003298 ch->name, len, ch->write_avail);
3299 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3300 return -ENOMEM;
3301 }
3302
3303 ret = sdio_ch_write(ch, data, len);
3304 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003305 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_write "
3306 "on channel %s err=%d\n", ch->name, -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003307 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3308 return ret;
3309 }
3310
3311 ch->total_tx_bytes += len;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003312 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s write %d "
3313 "avail %d total %d.\n", ch->name, len,
3314 ch->write_avail, ch->total_tx_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003315
3316 /* Round up to whole buffer size */
3317 len = ROUND_UP(len, ch->peer_tx_buf_size);
3318 /* Protect from wraparound */
3319 len = min(len, (int) ch->write_avail);
3320 ch->write_avail -= len;
3321
3322 if (ch->write_avail < ch->min_write_avail)
3323 ask_reading_mailbox(sdio_al_dev);
3324
3325 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3326
3327 return ret;
3328}
3329EXPORT_SYMBOL(sdio_write);
3330
3331static int __devinit msm_sdio_al_probe(struct platform_device *pdev)
3332{
3333 if (!sdio_al) {
3334 pr_err(MODULE_NAME ": %s: NULL sdio_al\n", __func__);
3335 return -ENODEV;
3336 }
3337
3338 sdio_al->pdata = pdev->dev.platform_data;
3339 return 0;
3340}
3341
3342static int __devexit msm_sdio_al_remove(struct platform_device *pdev)
3343{
3344 return 0;
3345}
3346
Konstantin Dorfman52890522011-10-05 11:03:19 +02003347static void sdio_al_close_all_channels(struct sdio_al_device *sdio_al_dev)
Maya Erez6862b142011-08-22 09:07:07 +03003348{
Konstantin Dorfman52890522011-10-05 11:03:19 +02003349 int j;
Maya Erez6862b142011-08-22 09:07:07 +03003350 int ret;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003351 struct sdio_channel *ch = NULL;
Maya Erez6862b142011-08-22 09:07:07 +03003352
Konstantin Dorfman52890522011-10-05 11:03:19 +02003353 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
Maya Erez6862b142011-08-22 09:07:07 +03003354
Konstantin Dorfman52890522011-10-05 11:03:19 +02003355 if (!sdio_al_dev) {
3356 sdio_al_loge(sdio_al_dev->dev_log,
3357 MODULE_NAME ": %s: NULL device", __func__);
3358 return;
3359 }
3360 for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++) {
3361 ch = &sdio_al_dev->channel[j];
3362
3363 if (ch->state == SDIO_CHANNEL_STATE_OPEN) {
3364 sdio_al_loge(sdio_al_dev->dev_log,
3365 MODULE_NAME ": %s: Call to sdio_close() for"
3366 " ch %s\n", __func__, ch->name);
3367 ret = channel_close(ch, false);
3368 if (ret) {
3369 sdio_al_loge(sdio_al_dev->dev_log,
3370 MODULE_NAME ": %s: failed sdio_close()"
3371 " for ch %s (%d)\n",
3372 __func__, ch->name, ret);
3373 }
3374 } else {
3375 pr_debug(MODULE_NAME ": %s: skip sdio_close() ch %s"
3376 " (state=%d)\n", __func__,
3377 ch->name, ch->state);
Maya Erez6862b142011-08-22 09:07:07 +03003378 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02003379 }
3380}
3381
3382static void sdio_al_modem_reset_dev_operations(struct sdio_al_device
3383 *sdio_al_dev)
3384{
3385 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
3386
3387 if (!sdio_al_dev) {
3388 sdio_al_loge(sdio_al_dev->dev_log,
3389 MODULE_NAME ": %s: NULL device", __func__);
3390 return;
3391 }
3392 if (sdio_al_dev->state == CARD_REMOVED) {
3393 sdio_al_logi(sdio_al_dev->dev_log,
3394 MODULE_NAME ": %s: card %d is already removed",
Maya Erez6862b142011-08-22 09:07:07 +03003395 __func__, sdio_al_dev->card->host->index);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003396 return;
3397 }
3398 if (sdio_al_dev->state == MODEM_RESTART) {
3399 sdio_al_logi(sdio_al_dev->dev_log,
3400 MODULE_NAME ": %s: card %d was already "
3401 "notified for modem reset",
3402 __func__, sdio_al_dev->card->host->index);
3403 return;
3404 }
Maya Erez6862b142011-08-22 09:07:07 +03003405
Krishna Kondaa7af6062011-09-01 18:34:38 -07003406 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: Set the "
3407 "state to MODEM_RESTART for card %d",
Maya Erez6862b142011-08-22 09:07:07 +03003408 __func__, sdio_al_dev->card->host->index);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003409 sdio_al_dev->state = MODEM_RESTART;
3410 sdio_al_dev->is_ready = false;
Maya Erez6862b142011-08-22 09:07:07 +03003411
Konstantin Dorfman52890522011-10-05 11:03:19 +02003412 /* Stop mailbox timer */
3413 if (sdio_al_dev->is_timer_initialized) {
3414 sdio_al_logi(sdio_al_dev->dev_log,
3415 MODULE_NAME ": %s: Stop timer for card %d",
Maya Erez6862b142011-08-22 09:07:07 +03003416 __func__, sdio_al_dev->card->host->index);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003417 sdio_al_dev->poll_delay_msec = 0;
3418 del_timer_sync(&sdio_al_dev->timer);
3419 sdio_al_dev->is_timer_initialized = false;
3420 } else {
3421 sdio_al_logi(sdio_al_dev->dev_log,
3422 MODULE_NAME ": %s: No timer. Nothing to do for card %d",
3423 __func__, sdio_al_dev->card->host->index);
3424 }
3425 return;
3426}
3427
3428static int sdio_al_modem_reset_bus_operations(struct sdio_al_device
3429 *sdio_al_dev)
3430{
3431 int j;
3432 int ret;
3433 struct sdio_func *func1 = NULL;
3434
3435 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
3436
3437 func1 = sdio_al_dev->card->sdio_func[0];
3438 if ((sdio_al_dev->is_ok_to_sleep) &&
3439 (!sdio_al_dev->is_err)) {
3440 sdio_al_logi(&sdio_al->gen_log,
3441 MODULE_NAME ": %s: wakeup modem for "
3442 "card %d", __func__,
3443 sdio_al_dev->card->host->index);
3444 ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
3445 if (ret == 0) {
3446 sdio_al_logi(&sdio_al->gen_log,
3447 MODULE_NAME ": %s: "
3448 "sdio_release_irq"
3449 " for card %d",
3450 __func__,
3451 sdio_al_dev->card->host->index);
3452 sdio_release_irq(func1);
Maya Erez6862b142011-08-22 09:07:07 +03003453 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02003454 } else {
3455 sdio_al_logi(&sdio_al->gen_log,
3456 MODULE_NAME ": %s: sdio_release_irq"
3457 " for card %d",
3458 __func__,
3459 sdio_al_dev->card->host->index);
3460 sdio_release_irq(func1);
Maya Erez6862b142011-08-22 09:07:07 +03003461 }
3462
Konstantin Dorfman52890522011-10-05 11:03:19 +02003463 sdio_al_logi(&sdio_al->gen_log,
3464 MODULE_NAME ": %s: Notifying SDIO clients for card %d",
3465 __func__, sdio_al_dev->card->host->index);
3466 for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++) {
3467 if (sdio_al_dev->channel[j].state ==
3468 SDIO_CHANNEL_STATE_INVALID)
3469 continue;
3470 platform_device_unregister(
3471 sdio_al_dev->channel[j].pdev);
3472 sdio_al_dev->channel[j].signature = 0x0;
3473 }
3474 return 0;
3475}
3476
3477#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
3478static void sdio_al_reset(void)
3479{
3480 int i;
3481 struct sdio_al_device *sdio_al_dev;
3482 struct sdio_func *func1 = NULL;
3483
3484 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
3485
3486 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++)
3487 sdio_al_modem_reset_dev_operations(sdio_al->devices[i]);
3488
Maya Erez6862b142011-08-22 09:07:07 +03003489 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
Maya Erez6862b142011-08-22 09:07:07 +03003490 if (sdio_al->devices[i] == NULL) {
3491 pr_debug(MODULE_NAME ": %s: NULL device in index %d",
Konstantin Dorfman52890522011-10-05 11:03:19 +02003492 __func__, i);
Maya Erez6862b142011-08-22 09:07:07 +03003493 continue;
3494 }
3495 sdio_al_dev = sdio_al->devices[i];
3496
3497 if (!sdio_al_verify_func1(sdio_al_dev, __func__)) {
3498 func1 = sdio_al_dev->card->sdio_func[0];
3499 sdio_claim_host(func1);
3500
Konstantin Dorfman52890522011-10-05 11:03:19 +02003501 sdio_al_modem_reset_bus_operations(sdio_al_dev);
3502
3503 if (!sdio_al_verify_func1(sdio_al_dev, __func__))
3504 sdio_release_host(func1);
3505
3506
3507 pr_debug(MODULE_NAME ": %s: Allows sleep for card %d",
Maya Erez6862b142011-08-22 09:07:07 +03003508 __func__,
3509 sdio_al_dev->card->host->index);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003510 sdio_al_vote_for_sleep(sdio_al_dev, 1);
3511 } else {
3512 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME
3513 ":%s bad function i=%d\n", __func__, i);
Maya Erez6862b142011-08-22 09:07:07 +03003514 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02003515 }
3516 return;
3517}
3518#endif
Maya Erez6862b142011-08-22 09:07:07 +03003519
Konstantin Dorfman52890522011-10-05 11:03:19 +02003520static void msm_sdio_al_shutdown(struct platform_device *pdev)
3521{
3522 int i;
3523 struct sdio_func *func1 = NULL;
3524 struct sdio_al_device *sdio_al_dev;
3525
3526 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME
3527 "Initiating msm_sdio_al_shutdown...");
3528
3529 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
3530 if (sdio_al->devices[i] == NULL) {
3531 pr_debug(MODULE_NAME ": %s: NULL device in index %d",
3532 __func__, i);
3533 continue;
Maya Erez8afd564f2011-08-24 15:57:06 +03003534 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02003535 sdio_al_dev = sdio_al->devices[i];
Maya Erez6862b142011-08-22 09:07:07 +03003536
Maya Erez6862b142011-08-22 09:07:07 +03003537
Konstantin Dorfman52890522011-10-05 11:03:19 +02003538 if (!sdio_al_verify_func1(sdio_al_dev, __func__)) {
3539 func1 = sdio_al_dev->card->sdio_func[0];
3540 sdio_claim_host(func1);
3541
3542 if (sdio_al_dev->ch_close_supported)
3543 sdio_al_close_all_channels(sdio_al_dev);
3544
3545 sdio_al_modem_reset_dev_operations(sdio_al_dev);
3546
3547 sdio_al_modem_reset_bus_operations(sdio_al_dev);
3548
3549 if (!sdio_al_verify_func1(sdio_al_dev, __func__))
3550 sdio_release_host(func1);
3551
3552 pr_debug(MODULE_NAME ": %s: Allows sleep for card %d",
3553 __func__,
3554 sdio_al_dev->card->host->index);
3555 sdio_al_vote_for_sleep(sdio_al_dev, 1);
3556 }
Maya Erez6862b142011-08-22 09:07:07 +03003557 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07003558 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: "
3559 "msm_sdio_al_shutdown complete.", __func__);
Maya Erez6862b142011-08-22 09:07:07 +03003560}
3561
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003562static struct platform_driver msm_sdio_al_driver = {
3563 .probe = msm_sdio_al_probe,
3564 .remove = __exit_p(msm_sdio_al_remove),
Maya Erez6862b142011-08-22 09:07:07 +03003565 .shutdown = msm_sdio_al_shutdown,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003566 .driver = {
3567 .name = "msm_sdio_al",
3568 },
3569};
3570
3571/**
3572 * Initialize SDIO_AL channels.
3573 *
3574 */
3575static int init_channels(struct sdio_al_device *sdio_al_dev)
3576{
3577 int ret = 0;
3578 int i;
3579
3580 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3581 return -ENODEV;
3582
3583 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3584
3585 ret = read_sdioc_software_header(sdio_al_dev,
3586 sdio_al_dev->sdioc_sw_header);
3587 if (ret)
3588 goto exit;
3589
3590 ret = sdio_al_setup(sdio_al_dev);
3591 if (ret)
3592 goto exit;
3593
3594 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
3595 int ch_name_size;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003596 if (sdio_al_dev->channel[i].state == SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003597 continue;
3598 if (sdio_al->unittest_mode) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003599 memset(sdio_al_dev->channel[i].ch_test_name, 0,
3600 sizeof(sdio_al_dev->channel[i].ch_test_name));
3601 ch_name_size = strnlen(sdio_al_dev->channel[i].name,
3602 CHANNEL_NAME_SIZE);
3603 strncpy(sdio_al_dev->channel[i].ch_test_name,
3604 sdio_al_dev->channel[i].name,
3605 ch_name_size);
3606 strncat(sdio_al_dev->channel[i].ch_test_name +
3607 ch_name_size,
3608 SDIO_TEST_POSTFIX,
3609 SDIO_TEST_POSTFIX_SIZE);
3610 pr_debug(MODULE_NAME ":pdev.name = %s\n",
3611 sdio_al_dev->channel[i].ch_test_name);
3612 sdio_al_dev->channel[i].pdev = platform_device_alloc(
3613 sdio_al_dev->channel[i].ch_test_name, -1);
3614 } else {
3615 pr_debug(MODULE_NAME ":pdev.name = %s\n",
3616 sdio_al_dev->channel[i].name);
3617 sdio_al_dev->channel[i].pdev = platform_device_alloc(
3618 sdio_al_dev->channel[i].name, -1);
3619 }
3620 if (!sdio_al_dev->channel[i].pdev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003621 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3622 ":NULL platform device for ch %s",
3623 sdio_al_dev->channel[i].name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003624 sdio_al_dev->channel[i].state =
3625 SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003626 continue;
3627 }
3628 ret = platform_device_add(sdio_al_dev->channel[i].pdev);
3629 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003630 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3631 ":platform_device_add failed, "
3632 "ret=%d\n", ret);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003633 sdio_al_dev->channel[i].state =
3634 SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003635 }
3636 }
3637
3638exit:
3639 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3640 return ret;
3641}
3642
3643/**
3644 * Initialize SDIO_AL channels according to the client setup.
3645 * This function also check if the client is in boot mode and
3646 * flashless boot is required to be activated or the client is
3647 * up and running.
3648 *
3649 */
3650static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev)
3651{
3652 int ret = 0;
3653 struct sdio_func *func1;
3654 int signature = 0;
3655
3656 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3657 return -ENODEV;
3658 func1 = sdio_al_dev->card->sdio_func[0];
3659
3660 sdio_claim_host(func1);
3661
3662 /* Read the header signature to determine the status of the MDM
3663 * SDIO Client
3664 */
3665 signature = sdio_readl(func1, SDIOC_SW_HEADER_ADDR, &ret);
3666 sdio_release_host(func1);
3667 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003668 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
3669 "signature from sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003670 return ret;
3671 }
3672
3673 switch (signature) {
3674 case PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE:
3675 if (sdio_al_dev == sdio_al->bootloader_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003676 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":setup "
3677 "bootloader on card %d\n",
3678 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003679 return sdio_al_bootloader_setup();
3680 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003681 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":wait "
3682 "for bootloader completion "
3683 "on card %d\n",
3684 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003685 return sdio_al_wait_for_bootloader_comp(sdio_al_dev);
3686 }
3687 case PEER_SDIOC_SW_MAILBOX_SIGNATURE:
3688 case PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE:
3689 return init_channels(sdio_al_dev);
3690 default:
Krishna Kondaa7af6062011-09-01 18:34:38 -07003691 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
3692 "signature 0x%x\n", signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003693 return -EINVAL;
3694 }
3695
3696 return 0;
3697}
3698
3699/*
3700 * SDIO driver functions
3701 */
3702static int sdio_al_sdio_probe(struct sdio_func *func,
3703 const struct sdio_device_id *sdio_dev_id)
3704{
3705 int ret = 0;
3706 struct sdio_al_device *sdio_al_dev = NULL;
3707 int i;
3708 struct mmc_card *card = NULL;
3709
3710 if (!func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003711 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
3712 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003713 return -ENODEV;
3714 }
3715 card = func->card;
3716
3717 if (!card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003718 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
3719 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003720 return -ENODEV;
3721 }
3722
3723 if (card->sdio_funcs < SDIO_AL_MAX_FUNCS) {
3724 dev_info(&card->dev,
3725 "SDIO-functions# %d less than expected.\n",
3726 card->sdio_funcs);
3727 return -ENODEV;
3728 }
3729
3730 /* Check if there is already a device for this card */
3731 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
3732 if (sdio_al->devices[i] == NULL)
3733 continue;
3734 if (sdio_al->devices[i]->card == card)
3735 return 0;
3736 }
3737
3738 dev_info(&card->dev, "SDIO Card claimed.\n");
3739
3740 sdio_al_dev = kzalloc(sizeof(struct sdio_al_device), GFP_KERNEL);
3741 if (sdio_al_dev == NULL)
3742 return -ENOMEM;
3743
3744 sdio_al_dev->state = CARD_INSERTED;
3745
3746 if (card->host->index == SDIO_BOOTLOADER_CARD_INDEX)
3747 sdio_al->bootloader_dev = sdio_al_dev;
3748
3749 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
3750 if (sdio_al->devices[i] == NULL) {
3751 sdio_al->devices[i] = sdio_al_dev;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003752 sdio_al_dev->dev_log = &sdio_al->device_log[i];
3753 spin_lock_init(&sdio_al_dev->dev_log->log_lock);
3754#ifdef CONFIG_DEBUG_FS
3755 sdio_al_dbgfs_log[i].data =
3756 sdio_al_dev->dev_log->buffer;
3757 sdio_al_dbgfs_log[i].size = SDIO_AL_DEBUG_LOG_SIZE;
3758#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003759 break;
3760 }
3761 if (i == MAX_NUM_OF_SDIO_DEVICES) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003762 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":No space in "
3763 "devices array for the device\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003764 return -ENOMEM;
3765 }
3766
3767 sdio_al_dev->is_ready = false;
3768
3769 sdio_al_dev->signature = SDIO_AL_SIGNATURE;
3770
3771 sdio_al_dev->is_suspended = 0;
3772 sdio_al_dev->is_timer_initialized = false;
3773
3774 sdio_al_dev->lpm_chan = INVALID_SDIO_CHAN;
3775
3776 sdio_al_dev->card = card;
3777
3778 sdio_al_dev->mailbox = kzalloc(sizeof(struct sdio_mailbox), GFP_KERNEL);
3779 if (sdio_al_dev->mailbox == NULL)
3780 return -ENOMEM;
3781
3782 sdio_al_dev->sdioc_sw_header
3783 = kzalloc(sizeof(*sdio_al_dev->sdioc_sw_header), GFP_KERNEL);
3784 if (sdio_al_dev->sdioc_sw_header == NULL)
3785 return -ENOMEM;
3786
Maya Erez5795e0d2011-09-12 20:20:06 +03003787
3788 sdio_al_dev->rx_flush_buf = kzalloc(RX_FLUSH_BUFFER_SIZE, GFP_KERNEL);
3789 if (sdio_al_dev->rx_flush_buf == NULL) {
Konstantin Dorfman52890522011-10-05 11:03:19 +02003790 sdio_al_loge(&sdio_al->gen_log,
3791 MODULE_NAME ":Fail to allocate rx_flush_buf "
Maya Erez5795e0d2011-09-12 20:20:06 +03003792 "for card %d\n",
3793 card->host->index);
3794 return -ENOMEM;
3795 }
3796
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003797 sdio_al_dev->timer.data = (unsigned long)sdio_al_dev;
3798
3799 wake_lock_init(&sdio_al_dev->wake_lock, WAKE_LOCK_SUSPEND, MODULE_NAME);
3800 /* Don't allow sleep until all required clients register */
3801 sdio_al_vote_for_sleep(sdio_al_dev, 0);
3802
3803 sdio_claim_host(card->sdio_func[0]);
3804
3805 /* Init Func#1 */
Yaniv Gardi9a952d92011-09-06 13:46:30 +03003806 ret = sdio_al_enable_func_retry(card->sdio_func[0], "Init Func#1");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003807 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003808 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
3809 "enable Func#%d\n", card->sdio_func[0]->num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003810 goto exit;
3811 }
3812
3813 /* Patch Func CIS tuple issue */
3814 ret = sdio_set_block_size(card->sdio_func[0], SDIO_AL_BLOCK_SIZE);
3815 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003816 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to set "
3817 "block size, Func#%d\n", card->sdio_func[0]->num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003818 goto exit;
3819 }
3820 sdio_al_dev->card->sdio_func[0]->max_blksize = SDIO_AL_BLOCK_SIZE;
3821
3822 sdio_al_dev->workqueue = create_singlethread_workqueue("sdio_al_wq");
3823 sdio_al_dev->sdio_al_work.sdio_al_dev = sdio_al_dev;
3824 init_waitqueue_head(&sdio_al_dev->wait_mbox);
3825
3826 ret = sdio_al_client_setup(sdio_al_dev);
3827
3828exit:
3829 sdio_release_host(card->sdio_func[0]);
3830 return ret;
3831}
3832
3833static void sdio_al_sdio_remove(struct sdio_func *func)
3834{
3835 struct sdio_al_device *sdio_al_dev = NULL;
3836 int i;
3837 int state;
3838 struct mmc_card *card = NULL;
3839
3840 if (!func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003841 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
3842 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003843 return;
3844 }
3845 card = func->card;
3846
3847 if (!card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003848 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
3849 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003850 return;
3851 }
3852
3853 /* Find the sdio_al_device of this card */
3854 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
3855 if (sdio_al->devices[i] == NULL)
3856 continue;
3857 if (sdio_al->devices[i]->card == card) {
3858 sdio_al_dev = sdio_al->devices[i];
3859 sdio_al->devices[i] = NULL;
3860 break;
3861 }
3862 }
3863 if (sdio_al_dev == NULL) {
3864 pr_debug(MODULE_NAME ":%s :NULL sdio_al_dev for card %d\n",
3865 __func__, card->host->index);
3866 return;
3867 }
3868
Krishna Kondaa7af6062011-09-01 18:34:38 -07003869 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s for card %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003870 __func__, card->host->index);
3871
3872 if (card->sdio_func[0])
3873 sdio_claim_host(card->sdio_func[0]);
3874 else
Krishna Kondaa7af6062011-09-01 18:34:38 -07003875 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL func1 "
3876 "for card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003877
3878 if (sdio_al_dev->state == CARD_REMOVED)
3879 return;
3880
3881 state = sdio_al_dev->state;
3882 sdio_al_dev->state = CARD_REMOVED;
3883
3884 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++)
3885 sdio_al_dev->channel[i].signature = 0x0;
3886
Krishna Kondaa7af6062011-09-01 18:34:38 -07003887 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: ask_reading_mailbox "
3888 "for card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003889 sdio_al_dev->is_ready = false; /* Flag worker to exit */
3890 sdio_al_dev->ask_mbox = false;
3891 ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
3892
3893 if (state != MODEM_RESTART) {
3894 if (sdio_al_dev->is_timer_initialized) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003895 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Stop"
3896 " timer for card %d", __func__,
3897 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003898 sdio_al_dev->poll_delay_msec = 0;
3899 del_timer_sync(&sdio_al_dev->timer);
3900 }
3901
Krishna Kondaa7af6062011-09-01 18:34:38 -07003902 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: "
3903 "notifying clients for card %d\n",
Maya Erez8afd564f2011-08-24 15:57:06 +03003904 __func__, card->host->index);
3905 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
3906 if (sdio_al_dev->channel[i].state ==
3907 SDIO_CHANNEL_STATE_INVALID)
3908 continue;
3909 platform_device_unregister(
3910 sdio_al_dev->channel[i].pdev);
3911 sdio_al_dev->channel[i].signature = 0x0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003912 }
3913 }
3914 if (card->sdio_func[0])
3915 sdio_release_host(card->sdio_func[0]);
3916
Krishna Kondaa7af6062011-09-01 18:34:38 -07003917 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: vote for sleep for "
3918 "card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003919 sdio_al_vote_for_sleep(sdio_al_dev, 1);
3920
Krishna Kondaa7af6062011-09-01 18:34:38 -07003921 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: flush_workqueue for "
3922 "card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003923 flush_workqueue(sdio_al_dev->workqueue);
3924 destroy_workqueue(sdio_al_dev->workqueue);
3925 wake_lock_destroy(&sdio_al_dev->wake_lock);
3926
Krishna Kondaa7af6062011-09-01 18:34:38 -07003927 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: delete data "
3928 "structures for card %d\n", __func__,
3929 card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003930 kfree(sdio_al_dev->sdioc_sw_header);
3931 kfree(sdio_al_dev->mailbox);
Maya Erez5795e0d2011-09-12 20:20:06 +03003932 kfree(sdio_al_dev->rx_flush_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003933 kfree(sdio_al_dev);
3934
Krishna Kondaa7af6062011-09-01 18:34:38 -07003935 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: sdio card %d removed."
3936 "\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003937}
3938
3939static void sdio_print_mailbox(char *prefix_str, struct sdio_mailbox *mailbox)
3940{
3941 int k = 0;
3942 char buf[256];
3943 char buf1[10];
3944
3945 if (!mailbox) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003946 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": mailbox is "
3947 "NULL\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003948 return;
3949 }
3950
Krishna Kondaa7af6062011-09-01 18:34:38 -07003951 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: pipes 0_7: eot=0x%x,"
3952 " thresh=0x%x, overflow=0x%x, "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003953 "underflow=0x%x, mask_thresh=0x%x\n",
3954 prefix_str, mailbox->eot_pipe_0_7,
3955 mailbox->thresh_above_limit_pipe_0_7,
3956 mailbox->overflow_pipe_0_7,
3957 mailbox->underflow_pipe_0_7,
3958 mailbox->mask_thresh_above_limit_pipe_0_7);
3959
3960 memset(buf, 0, sizeof(buf));
3961 strncat(buf, ": bytes_avail:", sizeof(buf));
3962
3963 for (k = 0 ; k < SDIO_AL_ACTIVE_PIPES ; ++k) {
3964 snprintf(buf1, sizeof(buf1), "%d, ",
3965 mailbox->pipe_bytes_avail[k]);
3966 strncat(buf, buf1, sizeof(buf));
3967 }
3968
Krishna Kondaa7af6062011-09-01 18:34:38 -07003969 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME "%s", buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003970}
3971
3972static void sdio_al_print_info(void)
3973{
3974 int i = 0;
3975 int j = 0;
3976 int ret = 0;
3977 struct sdio_mailbox *mailbox = NULL;
3978 struct sdio_mailbox *hw_mailbox = NULL;
3979 struct peer_sdioc_channel_config *ch_config = NULL;
3980 struct sdio_func *func1 = NULL;
3981 struct sdio_func *lpm_func = NULL;
3982 int offset = 0;
3983 int is_ok_to_sleep = 0;
3984 static atomic_t first_time;
3985 char buf[50];
3986
3987 if (atomic_read(&first_time) == 1)
3988 return;
3989
3990 atomic_set(&first_time, 1);
3991
Krishna Kondaa7af6062011-09-01 18:34:38 -07003992 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - SDIO DEBUG INFO\n",
3993 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003994
3995 if (!sdio_al) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003996 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - ERROR - "
3997 "sdio_al is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003998 return;
3999 }
4000
Krishna Kondaa7af6062011-09-01 18:34:38 -07004001 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": GPIO mdm2ap_status=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004002 sdio_al->pdata->get_mdm2ap_status());
4003
4004 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
4005 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
4006
4007 if (sdio_al_dev == NULL) {
4008 continue;
4009 }
4010
4011 if (!sdio_al_dev->card && !sdio_al_dev->card->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004012 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card"
4013 " or Host fields are NULL\n);");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004014 continue;
4015 }
4016
4017 snprintf(buf, sizeof(buf), "Card#%d: Shadow HW MB",
4018 sdio_al_dev->card->host->index);
4019
4020 /* printing Shadowing HW Mailbox*/
4021 mailbox = sdio_al_dev->mailbox;
4022 sdio_print_mailbox(buf, mailbox);
4023
Krishna Kondaa7af6062011-09-01 18:34:38 -07004024 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004025 "is_ok_to_sleep=%d\n",
4026 sdio_al_dev->card->host->index,
4027 sdio_al_dev->is_ok_to_sleep);
4028
4029
Krishna Kondaa7af6062011-09-01 18:34:38 -07004030 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004031 "Shadow channels SW MB:",
4032 sdio_al_dev->card->host->index);
4033
4034 /* printing Shadowing SW Mailbox per channel*/
4035 for (i = 0 ; i < SDIO_AL_MAX_CHANNELS ; ++i) {
4036 struct sdio_channel *ch = &sdio_al_dev->channel[i];
4037
4038 if (ch == NULL) {
4039 continue;
4040 }
4041
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03004042 if (ch->state == SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004043 continue;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004044
4045 ch_config = &sdio_al_dev->channel[i].ch_config;
4046
Krishna Kondaa7af6062011-09-01 18:34:38 -07004047 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4048 ": Ch %s: max_rx_thres=0x%x, "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004049 "max_tx_thres=0x%x, tx_buf=0x%x, "
4050 "is_packet_mode=%d, "
4051 "max_packet=0x%x, min_write=0x%x",
4052 ch->name, ch_config->max_rx_threshold,
4053 ch_config->max_tx_threshold,
4054 ch_config->tx_buf_size,
4055 ch_config->is_packet_mode,
4056 ch_config->max_packet_size,
4057 ch->min_write_avail);
4058
Krishna Kondaa7af6062011-09-01 18:34:38 -07004059 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4060 ": total_rx=0x%x, total_tx=0x%x, "
4061 "read_avail=0x%x, write_avail=0x%x, "
4062 "rx_pending=0x%x, num_reads=0x%x, "
4063 "num_notifs=0x%x", ch->total_rx_bytes,
4064 ch->total_tx_bytes, ch->read_avail,
4065 ch->write_avail, ch->rx_pending_bytes,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004066 ch->statistics.total_read_times,
4067 ch->statistics.total_notifs);
4068 } /* end loop over all channels */
4069
4070 } /* end loop over all devices */
4071
4072 /* reading from client and printing is_host_ok_to_sleep per device */
4073 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
4074 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
4075
4076 if (sdio_al_verify_dev(sdio_al_dev, __func__))
4077 return;
4078
4079 if (!sdio_al_dev->card->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004080 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4081 ": Host is NULL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004082 continue;
4083 }
4084
4085 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004086 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4087 ": %s - for Card#%d, is lpm_chan=="
4088 "INVALID_SDIO_CHAN. continuing...",
4089 __func__, sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004090 continue;
4091 }
4092
4093 offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
4094 sizeof(struct peer_sdioc_channel_config) *
4095 sdio_al_dev->lpm_chan+
4096 offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
4097
4098 lpm_func = sdio_al_dev->card->sdio_func[sdio_al_dev->
4099 lpm_chan+1];
4100 if (!lpm_func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004101 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4102 ": %s - lpm_func is NULL for card#%d"
4103 " continuing...\n", __func__,
4104 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004105 continue;
4106 }
4107
4108 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
4109 ret = sdio_memcpy_fromio(lpm_func,
4110 &is_ok_to_sleep,
4111 SDIOC_SW_MAILBOX_ADDR+offset,
4112 sizeof(int));
Maya Erez1dd658a2011-08-09 10:14:47 +03004113 if (sdio_al_verify_dev(sdio_al_dev, __func__))
4114 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004115 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
4116
4117 if (ret)
Krishna Kondaa7af6062011-09-01 18:34:38 -07004118 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4119 ": %s - fail to read "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004120 "is_HOST_ok_to_sleep from mailbox for card %d",
4121 __func__, sdio_al_dev->card->host->index);
4122 else
Krishna Kondaa7af6062011-09-01 18:34:38 -07004123 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4124 ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004125 "is_HOST_ok_to_sleep=%d\n",
4126 sdio_al_dev->card->host->index,
4127 is_ok_to_sleep);
4128 }
4129
4130 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
4131 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
4132
4133 if (sdio_al_verify_dev(sdio_al_dev, __func__))
4134 return;
4135
4136 if (!sdio_al_dev->card->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004137 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4138 ": Host is NULL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004139 continue;
4140 }
4141
4142 /* Reading HW Mailbox */
4143 hw_mailbox = sdio_al_dev->mailbox;
4144 func1 = sdio_al_dev->card->sdio_func[0];
4145
4146 sdio_claim_host(func1);
4147 ret = sdio_memcpy_fromio(func1, hw_mailbox,
4148 HW_MAILBOX_ADDR, sizeof(*hw_mailbox));
Maya Erez1dd658a2011-08-09 10:14:47 +03004149 if (sdio_al_verify_dev(sdio_al_dev, __func__))
4150 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004151 sdio_release_host(func1);
4152
4153 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004154 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4155 ": fail to read "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004156 "mailbox for card#%d. "
4157 "continuing...\n",
4158 sdio_al_dev->card->host->index);
4159 continue;
4160 }
4161
4162 snprintf(buf, sizeof(buf), "Card#%d: Current HW MB",
4163 sdio_al_dev->card->host->index);
4164
4165 /* Printing HW Mailbox */
4166 sdio_print_mailbox(buf, hw_mailbox);
4167 }
4168}
4169
4170static struct sdio_device_id sdio_al_sdioid[] = {
4171 {.class = 0, .vendor = 0x70, .device = 0x2460},
4172 {.class = 0, .vendor = 0x70, .device = 0x0460},
4173 {.class = 0, .vendor = 0x70, .device = 0x23F1},
4174 {.class = 0, .vendor = 0x70, .device = 0x23F0},
4175 {}
4176};
4177
4178static struct sdio_driver sdio_al_sdiofn_driver = {
4179 .name = "sdio_al_sdiofn",
4180 .id_table = sdio_al_sdioid,
4181 .probe = sdio_al_sdio_probe,
4182 .remove = sdio_al_sdio_remove,
4183};
4184
4185#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4186/*
4187 * Callback for notifications from restart mudule.
4188 * This function handles only the BEFORE_RESTART notification.
4189 * Stop all the activity on the card and notify our clients.
4190 */
4191static int sdio_al_subsys_notifier_cb(struct notifier_block *this,
4192 unsigned long notif_type,
4193 void *data)
4194{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004195 if (notif_type != SUBSYS_BEFORE_SHUTDOWN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004196 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: got "
4197 "notification %ld", __func__, notif_type);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004198 return NOTIFY_DONE;
4199 }
4200
Konstantin Dorfman52890522011-10-05 11:03:19 +02004201 sdio_al_reset();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004202 return NOTIFY_OK;
4203}
4204
4205static struct notifier_block sdio_al_nb = {
4206 .notifier_call = sdio_al_subsys_notifier_cb,
4207};
4208#endif
4209
4210/**
4211 * Module Init.
4212 *
4213 * @warn: allocate sdio_al context before registering driver.
4214 *
4215 */
4216static int __init sdio_al_init(void)
4217{
4218 int ret = 0;
4219 int i;
4220
4221 pr_debug(MODULE_NAME ":sdio_al_init\n");
4222
4223 pr_info(MODULE_NAME ":SDIO-AL SW version %s\n",
4224 DRV_VERSION);
4225
4226 sdio_al = kzalloc(sizeof(struct sdio_al), GFP_KERNEL);
4227 if (sdio_al == NULL)
4228 return -ENOMEM;
4229
4230 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
4231 sdio_al->devices[i] = NULL;
4232
4233 sdio_al->unittest_mode = false;
4234
4235 sdio_al->debug.debug_lpm_on = debug_lpm_on;
4236 sdio_al->debug.debug_data_on = debug_data_on;
Maya Erez7ad06d82011-10-02 15:47:57 +02004237 sdio_al->debug.debug_close_on = debug_close_on;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004238
4239#ifdef CONFIG_DEBUG_FS
4240 sdio_al_debugfs_init();
4241#endif
4242
4243
4244#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4245 sdio_al->subsys_notif_handle = subsys_notif_register_notifier(
4246 "external_modem", &sdio_al_nb);
4247#endif
4248
4249 ret = platform_driver_register(&msm_sdio_al_driver);
4250 if (ret) {
4251 pr_err(MODULE_NAME ": platform_driver_register failed: %d\n",
4252 ret);
4253 goto exit;
4254 }
4255
4256 sdio_register_driver(&sdio_al_sdiofn_driver);
Krishna Kondaa7af6062011-09-01 18:34:38 -07004257
4258 spin_lock_init(&sdio_al->gen_log.log_lock);
4259
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004260exit:
4261 if (ret)
4262 kfree(sdio_al);
4263 return ret;
4264}
4265
4266/**
4267 * Module Exit.
4268 *
4269 * Free allocated memory.
4270 * Disable SDIO-Card.
4271 * Unregister driver.
4272 *
4273 */
4274static void __exit sdio_al_exit(void)
4275{
4276 if (sdio_al == NULL)
4277 return;
4278
4279 pr_debug(MODULE_NAME ":sdio_al_exit\n");
4280
4281#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4282 subsys_notif_unregister_notifier(
4283 sdio_al->subsys_notif_handle, &sdio_al_nb);
4284#endif
4285
4286 sdio_al_tear_down();
4287
4288 sdio_unregister_driver(&sdio_al_sdiofn_driver);
4289
4290 kfree(sdio_al);
4291
4292#ifdef CONFIG_DEBUG_FS
4293 sdio_al_debugfs_cleanup();
4294#endif
4295
4296 platform_driver_unregister(&msm_sdio_al_driver);
4297
4298 pr_debug(MODULE_NAME ":sdio_al_exit complete\n");
4299}
4300
4301module_init(sdio_al_init);
4302module_exit(sdio_al_exit);
4303
4304MODULE_LICENSE("GPL v2");
4305MODULE_DESCRIPTION("SDIO Abstraction Layer");
4306MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
4307MODULE_VERSION(DRV_VERSION);
4308