blob: f5b9ad73ad257443194f6c6233f7d55e57f585ee [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
2818/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002819 * Close SDIO Channel.
2820 *
2821 */
2822int sdio_close(struct sdio_channel *ch)
2823{
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002824 int ret;
2825 struct sdio_al_device *sdio_al_dev = NULL;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002826 int flush_len;
2827 ulong flush_expires;
2828
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002829 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002830 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
2831 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002832 return -ENODEV;
2833 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002834 sdio_al_dev = ch->sdio_al_dev;
2835 if (sdio_al_verify_dev(sdio_al_dev, __func__))
2836 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002837
Maya Erezc29f2912011-08-22 14:32:13 +03002838 if (!sdio_al_dev->ch_close_supported) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002839 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: Not "
2840 "supported by mdm, ch %s\n",
2841 __func__, ch->name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002842 return -ENOTSUPP;
2843 }
2844
2845 if (!ch->func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002846 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: NULL func"
2847 " on channel:%d\n", __func__, ch->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002848 return -ENODEV;
2849 }
2850 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
2851
2852 if (sdio_al_dev->is_err) {
2853 SDIO_AL_ERR(__func__);
2854 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2855 return -ENODEV;
2856 }
2857 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002858 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2859 "sdio_al_dev is in invalid state %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002860 __func__, sdio_al_dev->state);
2861 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2862 return -ENODEV;
2863 }
2864 ch->state = SDIO_CHANNEL_STATE_CLOSING;
2865 ret = peer_set_operation(PEER_OP_CODE_CLOSE, sdio_al_dev, ch);
2866 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002867 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2868 "peer_set_operation() failed: %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002869 __func__, ret);
2870 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2871 return -ENODEV;
2872 }
2873 /* udate poll time for opened channels */
2874 if (ch->poll_delay_msec > 0) {
2875 sdio_al_dev->poll_delay_msec =
2876 get_min_poll_time_msec(sdio_al_dev);
2877 }
2878 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2879
2880 flush_expires = jiffies +
2881 msecs_to_jiffies(SDIO_CLOSE_FLUSH_TIMEOUT_MSEC);
2882 /* flush rx packets of the channel */
2883 do {
2884 while (ch->read_avail > 0) {
2885 flush_len = ch->read_avail;
Maya Erez5795e0d2011-09-12 20:20:06 +03002886 ret = sdio_read_internal(ch, sdio_al_dev->rx_flush_buf,
2887 flush_len);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002888 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002889 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2890 ":%s failed to sdio_read: %d, ch %s\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002891 __func__, ret, ch->name);
2892 return ret;
2893 }
Yaniv Gardic4663632011-08-31 19:55:38 +03002894
2895 if (time_after(jiffies, flush_expires) != 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002896 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2897 ":%s flush rx packets"
2898 " timeout: ch %s\n",
2899 __func__, ch->name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002900 sdio_al_get_into_err_state(sdio_al_dev);
2901 return -EBUSY;
2902 }
2903 }
2904 msleep(100);
2905 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002906 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
2907 "after sleep, invalid signature"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002908 " 0x%x\n", __func__, ch->signature);
2909 return -ENODEV;
2910 }
Maya Erezd913f6c2011-09-07 13:12:10 +03002911 if (sdio_al_verify_dev(ch->sdio_al_dev, __func__))
2912 return -ENODEV;
2913 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
2914 ret = read_mailbox(sdio_al_dev, false);
2915 if (ret) {
2916 pr_err(MODULE_NAME ":%s: failed to read mailbox",
2917 __func__);
2918 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2919 return -ENODEV;
2920 }
2921 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002922 } while (ch->read_avail > 0);
2923
2924 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002925 /* disable function to be able to open the channel again */
2926 ret = sdio_disable_func(ch->func);
2927 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002928 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
2929 "disable Func#%d\n", ch->func->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002930 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2931 return ret;
2932 }
2933 ch->state = SDIO_CHANNEL_STATE_CLOSED;
Maya Erez7ad06d82011-10-02 15:47:57 +02002934 CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":%s: Ch %s closed "
2935 "successfully\n", __func__, ch->name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002936 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2937
2938 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002939}
2940EXPORT_SYMBOL(sdio_close);
2941
2942/**
2943 * Get the number of available bytes to write.
2944 *
2945 */
2946int sdio_write_avail(struct sdio_channel *ch)
2947{
2948 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002949 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
2950 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002951 return -ENODEV;
2952 }
2953 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002954 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
2955 "Invalid signature 0x%x\n", __func__,
2956 ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002957 return -ENODEV;
2958 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002959 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002960 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2961 "channel %s state is not open (%d)\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002962 __func__, ch->name, ch->state);
2963 return -ENODEV;
2964 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002965 pr_debug(MODULE_NAME ":sdio_write_avail %s 0x%x\n",
2966 ch->name, ch->write_avail);
2967
2968 return ch->write_avail;
2969}
2970EXPORT_SYMBOL(sdio_write_avail);
2971
2972/**
2973 * Get the number of available bytes to read.
2974 *
2975 */
2976int sdio_read_avail(struct sdio_channel *ch)
2977{
2978 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002979 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
2980 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002981 return -ENODEV;
2982 }
2983 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002984 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
2985 "Invalid signature 0x%x\n", __func__,
2986 ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002987 return -ENODEV;
2988 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002989 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002990 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2991 "channel %s state is not open (%d)\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002992 __func__, ch->name, ch->state);
2993 return -ENODEV;
2994 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002995 pr_debug(MODULE_NAME ":sdio_read_avail %s 0x%x\n",
2996 ch->name, ch->read_avail);
2997
2998 return ch->read_avail;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002999}
3000EXPORT_SYMBOL(sdio_read_avail);
3001
Maya Erez5795e0d2011-09-12 20:20:06 +03003002static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len)
3003{
3004 int ret = 0;
3005 struct sdio_al_device *sdio_al_dev = NULL;
3006
3007 if (!ch) {
3008 pr_err(MODULE_NAME ":%s: NULL channel\n", __func__);
3009 return -ENODEV;
3010 }
3011
3012 sdio_al_dev = ch->sdio_al_dev;
3013
3014 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3015
3016 ret = sdio_memcpy_fromio(ch->func, sdio_al_dev->rx_flush_buf,
3017 PIPE_RX_FIFO_ADDR, len);
3018
3019 if (ret) {
3020 pr_err(MODULE_NAME ":ch %s: %s err=%d, len=%d\n",
3021 ch->name, __func__, -ret, len);
3022 sdio_al_dev->is_err = true;
3023 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3024 return ret;
3025 }
3026
3027 restart_inactive_time(sdio_al_dev);
3028
3029 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3030
3031 return 0;
3032}
3033
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003034/**
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003035 * Internal read from SDIO Channel.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003036 *
3037 * Reading from the pipe will trigger interrupt if there are
3038 * other pending packets on the SDIO-Client.
3039 *
3040 */
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003041static int sdio_read_internal(struct sdio_channel *ch, void *data, int len)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003042{
3043 int ret = 0;
3044 struct sdio_al_device *sdio_al_dev = NULL;
3045
3046 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003047 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3048 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003049 return -ENODEV;
3050 }
3051 if (!data) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003052 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
3053 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003054 return -ENODEV;
3055 }
3056 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003057 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
3058 " to read 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003059 return -EINVAL;
3060 }
3061
3062 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003063 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
3064 "signature 0x%x\n", __func__, ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003065 return -ENODEV;
3066 }
3067
3068 sdio_al_dev = ch->sdio_al_dev;
3069 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3070 return -ENODEV;
3071
3072 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3073
3074 if (sdio_al_dev->is_err) {
3075 SDIO_AL_ERR(__func__);
3076 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3077 return -ENODEV;
3078 }
3079
3080 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003081 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
3082 "sdio_al_dev is in invalid state %d\n",
3083 __func__, sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003084 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3085 return -ENODEV;
3086 }
3087
3088 /* lpm policy says we can't go to sleep when we have pending rx data,
3089 so either we had rx interrupt and woken up, or we never went to
3090 sleep */
3091 if (sdio_al_dev->is_ok_to_sleep) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003092 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: called "
3093 "when is_ok_to_sleep is set for ch %s, len=%d,"
3094 " last_any_read_avail=%d, last_read_avail=%d, "
3095 "last_old_read_avail=%d", __func__, ch->name,
3096 len, ch->statistics.last_any_read_avail,
3097 ch->statistics.last_read_avail,
3098 ch->statistics.last_old_read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003099 }
3100 BUG_ON(sdio_al_dev->is_ok_to_sleep);
3101
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003102 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
3103 (ch->state != SDIO_CHANNEL_STATE_CLOSING)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003104 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s wrong "
3105 "channel %s state %d\n",
3106 __func__, ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003107 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3108 return -EINVAL;
3109 }
3110
Krishna Kondaa7af6062011-09-01 18:34:38 -07003111 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s read %d "
3112 "avail %d.\n", ch->name, len, ch->read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003113
3114 restart_inactive_time(sdio_al_dev);
3115
3116 if ((ch->is_packet_mode) && (len != ch->read_avail)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003117 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_read ch "
3118 "%s len != read_avail\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003119 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3120 return -EINVAL;
3121 }
3122
3123 if (len > ch->read_avail) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003124 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
3125 "reading more bytes (%d) than the avail(%d).\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003126 ch->name, len, ch->read_avail);
3127 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3128 return -ENOMEM;
3129 }
3130
3131 ret = sdio_memcpy_fromio(ch->func, data, PIPE_RX_FIFO_ADDR, len);
3132
3133 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003134 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ch %s: "
3135 "sdio_read err=%d, len=%d, read_avail=%d, "
3136 "last_read_avail=%d, last_old_read_avail=%d\n",
Maya Erezd9cc2292011-08-04 09:20:31 +03003137 ch->name, -ret, len, ch->read_avail,
3138 ch->statistics.last_read_avail,
3139 ch->statistics.last_old_read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003140 sdio_al_dev->is_err = true;
3141 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3142 return ret;
3143 }
3144
3145 ch->statistics.total_read_times++;
3146
3147 /* Remove handled packet from the list regardless if ret is ok */
3148 if (ch->is_packet_mode)
3149 remove_handled_rx_packet(ch);
3150 else
3151 ch->read_avail -= len;
3152
3153 ch->total_rx_bytes += len;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003154 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s read %d "
3155 "avail %d total %d.\n", ch->name, len,
3156 ch->read_avail, ch->total_rx_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003157
3158 if ((ch->read_avail == 0) && !(ch->is_packet_mode))
3159 ask_reading_mailbox(sdio_al_dev);
3160
3161 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3162
3163 return ret;
3164}
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003165
3166/**
3167 * Read from SDIO Channel.
3168 *
3169 * Reading from the pipe will trigger interrupt if there are
3170 * other pending packets on the SDIO-Client.
3171 *
3172 */
3173int sdio_read(struct sdio_channel *ch, void *data, int len)
3174{
3175 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003176 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3177 "channel\n", __func__);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003178 return -ENODEV;
3179 }
3180 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003181 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
3182 "Invalid signature 0x%x\n", __func__, ch->signature);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003183 return -ENODEV;
3184 }
3185 if (ch->state == SDIO_CHANNEL_STATE_OPEN) {
3186 return sdio_read_internal(ch, data, len);
3187 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003188 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME
3189 ":%s: Invalid channel %s state %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003190 __func__, ch->name, ch->state);
3191 }
3192 return -ENODEV;
3193}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003194EXPORT_SYMBOL(sdio_read);
3195
3196/**
3197 * Write to SDIO Channel.
3198 *
3199 */
3200int sdio_write(struct sdio_channel *ch, const void *data, int len)
3201{
3202 int ret = 0;
3203 struct sdio_al_device *sdio_al_dev = NULL;
3204
3205 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003206 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3207 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003208 return -ENODEV;
3209 }
3210 if (!data) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003211 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
3212 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003213 return -ENODEV;
3214 }
3215 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003216 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
3217 " to write 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003218 return -EINVAL;
3219 }
3220
3221 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003222 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
3223 "signature 0x%x\n", __func__, ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003224 return -ENODEV;
3225 }
3226
3227 sdio_al_dev = ch->sdio_al_dev;
3228 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3229 return -ENODEV;
3230
3231 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3232
3233
3234 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003235 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3236 ":%s: sdio_al_dev is in invalid state %d\n",
3237 __func__, sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003238 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3239 return -ENODEV;
3240 }
3241 WARN_ON(len > ch->write_avail);
3242
3243 if (sdio_al_dev->is_err) {
3244 SDIO_AL_ERR(__func__);
3245 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3246 return -ENODEV;
3247 }
3248
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003249 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003250 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":writing to "
3251 "closed channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003252 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3253 return -EINVAL;
3254 }
3255
3256 if (sdio_al_dev->is_ok_to_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03003257 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003258 if (ret) {
3259 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3260 return ret;
3261 }
3262 } else {
3263 restart_inactive_time(sdio_al_dev);
3264 }
3265
Krishna Kondaa7af6062011-09-01 18:34:38 -07003266 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s write %d "
3267 "avail %d.\n", ch->name, len, ch->write_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003268
3269 if (len > ch->write_avail) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003270 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
3271 "write more bytes (%d) than available %d.\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003272 ch->name, len, ch->write_avail);
3273 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3274 return -ENOMEM;
3275 }
3276
3277 ret = sdio_ch_write(ch, data, len);
3278 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003279 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_write "
3280 "on channel %s err=%d\n", ch->name, -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003281 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3282 return ret;
3283 }
3284
3285 ch->total_tx_bytes += len;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003286 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s write %d "
3287 "avail %d total %d.\n", ch->name, len,
3288 ch->write_avail, ch->total_tx_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003289
3290 /* Round up to whole buffer size */
3291 len = ROUND_UP(len, ch->peer_tx_buf_size);
3292 /* Protect from wraparound */
3293 len = min(len, (int) ch->write_avail);
3294 ch->write_avail -= len;
3295
3296 if (ch->write_avail < ch->min_write_avail)
3297 ask_reading_mailbox(sdio_al_dev);
3298
3299 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3300
3301 return ret;
3302}
3303EXPORT_SYMBOL(sdio_write);
3304
3305static int __devinit msm_sdio_al_probe(struct platform_device *pdev)
3306{
3307 if (!sdio_al) {
3308 pr_err(MODULE_NAME ": %s: NULL sdio_al\n", __func__);
3309 return -ENODEV;
3310 }
3311
3312 sdio_al->pdata = pdev->dev.platform_data;
3313 return 0;
3314}
3315
3316static int __devexit msm_sdio_al_remove(struct platform_device *pdev)
3317{
3318 return 0;
3319}
3320
Maya Erez6862b142011-08-22 09:07:07 +03003321static void msm_sdio_al_shutdown(struct platform_device *pdev)
3322{
3323 int i, j;
3324 struct sdio_func *func1 = NULL;
3325 int ret;
3326
Krishna Kondaa7af6062011-09-01 18:34:38 -07003327 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Initiating "
3328 "msm_sdio_al_shutdown...", __func__);
Maya Erez6862b142011-08-22 09:07:07 +03003329
3330 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
3331 struct sdio_al_device *sdio_al_dev = NULL;
3332 if (sdio_al->devices[i] == NULL) {
3333 pr_debug(MODULE_NAME ": %s: NULL device in index %d",
3334 __func__, i);
3335 continue;
3336 }
3337 sdio_al_dev = sdio_al->devices[i];
3338 if (sdio_al_dev->state == CARD_REMOVED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003339 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: "
3340 "card %d is already removed", __func__,
3341 sdio_al_dev->card->host->index);
Maya Erez6862b142011-08-22 09:07:07 +03003342 continue;
3343 }
3344 if (sdio_al_dev->state == MODEM_RESTART) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003345 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: "
3346 "card %d was already notified for modem reset",
Maya Erez6862b142011-08-22 09:07:07 +03003347 __func__, sdio_al_dev->card->host->index);
3348 continue;
3349 }
3350
Krishna Kondaa7af6062011-09-01 18:34:38 -07003351 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: Set the "
3352 "state to MODEM_RESTART for card %d",
Maya Erez6862b142011-08-22 09:07:07 +03003353 __func__, sdio_al_dev->card->host->index);
3354 sdio_al_dev->state = MODEM_RESTART;
3355 sdio_al_dev->is_ready = false;
3356
3357 /* Stop mailbox timer */
3358 if (sdio_al_dev->is_timer_initialized) {
3359 pr_debug(MODULE_NAME ": %s: Stop timer for card %d",
3360 __func__, sdio_al_dev->card->host->index);
3361 sdio_al_dev->poll_delay_msec = 0;
3362 del_timer_sync(&sdio_al_dev->timer);
3363 }
3364 }
3365
3366 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
3367 struct sdio_al_device *sdio_al_dev;
3368 if (sdio_al->devices[i] == NULL) {
3369 pr_debug(MODULE_NAME ": %s: NULL device in index %d",
3370 __func__, i);
3371 continue;
3372 }
3373 sdio_al_dev = sdio_al->devices[i];
3374
3375 if (!sdio_al_verify_func1(sdio_al_dev, __func__)) {
3376 func1 = sdio_al_dev->card->sdio_func[0];
3377 sdio_claim_host(func1);
3378
3379 if ((sdio_al_dev->is_ok_to_sleep) &&
3380 (!sdio_al_dev->is_err)) {
3381 pr_debug(MODULE_NAME ": %s: wakeup modem for "
3382 "card %d", __func__,
3383 sdio_al_dev->card->host->index);
3384 ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
3385 if (ret == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003386 sdio_al_logi(sdio_al_dev->dev_log,
3387 MODULE_NAME ": %s: "
3388 "sdio_release_irq for card %d",
Maya Erez6862b142011-08-22 09:07:07 +03003389 __func__,
3390 sdio_al_dev->card->host->index);
3391 sdio_release_irq(func1);
3392 }
3393 } else {
3394 pr_debug(MODULE_NAME ": %s: sdio_release_irq"
3395 " for card %d",
3396 __func__,
3397 sdio_al_dev->card->host->index);
3398 sdio_release_irq(func1);
3399 }
3400 }
3401
3402 pr_debug(MODULE_NAME ": %s: Notifying SDIO clients for card %d",
3403 __func__, sdio_al_dev->card->host->index);
Maya Erez8afd5642011-08-24 15:57:06 +03003404 for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++) {
3405 if (sdio_al_dev->channel[j].state ==
3406 SDIO_CHANNEL_STATE_INVALID)
3407 continue;
3408 platform_device_unregister(
3409 sdio_al_dev->channel[j].pdev);
3410 sdio_al_dev->channel[i].signature = 0x0;
3411 }
Maya Erez6862b142011-08-22 09:07:07 +03003412
3413 if (!sdio_al_verify_func1(sdio_al_dev, __func__))
3414 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3415
3416 pr_debug(MODULE_NAME ": %s: Allows sleep for card %d", __func__,
3417 sdio_al_dev->card->host->index);
3418 sdio_al_vote_for_sleep(sdio_al_dev, 1);
3419 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07003420 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: "
3421 "msm_sdio_al_shutdown complete.", __func__);
Maya Erez6862b142011-08-22 09:07:07 +03003422}
3423
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003424static struct platform_driver msm_sdio_al_driver = {
3425 .probe = msm_sdio_al_probe,
3426 .remove = __exit_p(msm_sdio_al_remove),
Maya Erez6862b142011-08-22 09:07:07 +03003427 .shutdown = msm_sdio_al_shutdown,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003428 .driver = {
3429 .name = "msm_sdio_al",
3430 },
3431};
3432
3433/**
3434 * Initialize SDIO_AL channels.
3435 *
3436 */
3437static int init_channels(struct sdio_al_device *sdio_al_dev)
3438{
3439 int ret = 0;
3440 int i;
3441
3442 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3443 return -ENODEV;
3444
3445 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3446
3447 ret = read_sdioc_software_header(sdio_al_dev,
3448 sdio_al_dev->sdioc_sw_header);
3449 if (ret)
3450 goto exit;
3451
3452 ret = sdio_al_setup(sdio_al_dev);
3453 if (ret)
3454 goto exit;
3455
3456 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
3457 int ch_name_size;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003458 if (sdio_al_dev->channel[i].state == SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003459 continue;
3460 if (sdio_al->unittest_mode) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003461 memset(sdio_al_dev->channel[i].ch_test_name, 0,
3462 sizeof(sdio_al_dev->channel[i].ch_test_name));
3463 ch_name_size = strnlen(sdio_al_dev->channel[i].name,
3464 CHANNEL_NAME_SIZE);
3465 strncpy(sdio_al_dev->channel[i].ch_test_name,
3466 sdio_al_dev->channel[i].name,
3467 ch_name_size);
3468 strncat(sdio_al_dev->channel[i].ch_test_name +
3469 ch_name_size,
3470 SDIO_TEST_POSTFIX,
3471 SDIO_TEST_POSTFIX_SIZE);
3472 pr_debug(MODULE_NAME ":pdev.name = %s\n",
3473 sdio_al_dev->channel[i].ch_test_name);
3474 sdio_al_dev->channel[i].pdev = platform_device_alloc(
3475 sdio_al_dev->channel[i].ch_test_name, -1);
3476 } else {
3477 pr_debug(MODULE_NAME ":pdev.name = %s\n",
3478 sdio_al_dev->channel[i].name);
3479 sdio_al_dev->channel[i].pdev = platform_device_alloc(
3480 sdio_al_dev->channel[i].name, -1);
3481 }
3482 if (!sdio_al_dev->channel[i].pdev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003483 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3484 ":NULL platform device for ch %s",
3485 sdio_al_dev->channel[i].name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003486 sdio_al_dev->channel[i].state =
3487 SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003488 continue;
3489 }
3490 ret = platform_device_add(sdio_al_dev->channel[i].pdev);
3491 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003492 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3493 ":platform_device_add failed, "
3494 "ret=%d\n", ret);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003495 sdio_al_dev->channel[i].state =
3496 SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003497 }
3498 }
3499
3500exit:
3501 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3502 return ret;
3503}
3504
3505/**
3506 * Initialize SDIO_AL channels according to the client setup.
3507 * This function also check if the client is in boot mode and
3508 * flashless boot is required to be activated or the client is
3509 * up and running.
3510 *
3511 */
3512static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev)
3513{
3514 int ret = 0;
3515 struct sdio_func *func1;
3516 int signature = 0;
3517
3518 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3519 return -ENODEV;
3520 func1 = sdio_al_dev->card->sdio_func[0];
3521
3522 sdio_claim_host(func1);
3523
3524 /* Read the header signature to determine the status of the MDM
3525 * SDIO Client
3526 */
3527 signature = sdio_readl(func1, SDIOC_SW_HEADER_ADDR, &ret);
3528 sdio_release_host(func1);
3529 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003530 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
3531 "signature from sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003532 return ret;
3533 }
3534
3535 switch (signature) {
3536 case PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE:
3537 if (sdio_al_dev == sdio_al->bootloader_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003538 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":setup "
3539 "bootloader on card %d\n",
3540 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003541 return sdio_al_bootloader_setup();
3542 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003543 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":wait "
3544 "for bootloader completion "
3545 "on card %d\n",
3546 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003547 return sdio_al_wait_for_bootloader_comp(sdio_al_dev);
3548 }
3549 case PEER_SDIOC_SW_MAILBOX_SIGNATURE:
3550 case PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE:
3551 return init_channels(sdio_al_dev);
3552 default:
Krishna Kondaa7af6062011-09-01 18:34:38 -07003553 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
3554 "signature 0x%x\n", signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003555 return -EINVAL;
3556 }
3557
3558 return 0;
3559}
3560
3561/*
3562 * SDIO driver functions
3563 */
3564static int sdio_al_sdio_probe(struct sdio_func *func,
3565 const struct sdio_device_id *sdio_dev_id)
3566{
3567 int ret = 0;
3568 struct sdio_al_device *sdio_al_dev = NULL;
3569 int i;
3570 struct mmc_card *card = NULL;
3571
3572 if (!func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003573 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
3574 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003575 return -ENODEV;
3576 }
3577 card = func->card;
3578
3579 if (!card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003580 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
3581 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003582 return -ENODEV;
3583 }
3584
3585 if (card->sdio_funcs < SDIO_AL_MAX_FUNCS) {
3586 dev_info(&card->dev,
3587 "SDIO-functions# %d less than expected.\n",
3588 card->sdio_funcs);
3589 return -ENODEV;
3590 }
3591
3592 /* Check if there is already a device for this card */
3593 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
3594 if (sdio_al->devices[i] == NULL)
3595 continue;
3596 if (sdio_al->devices[i]->card == card)
3597 return 0;
3598 }
3599
3600 dev_info(&card->dev, "SDIO Card claimed.\n");
3601
3602 sdio_al_dev = kzalloc(sizeof(struct sdio_al_device), GFP_KERNEL);
3603 if (sdio_al_dev == NULL)
3604 return -ENOMEM;
3605
3606 sdio_al_dev->state = CARD_INSERTED;
3607
3608 if (card->host->index == SDIO_BOOTLOADER_CARD_INDEX)
3609 sdio_al->bootloader_dev = sdio_al_dev;
3610
3611 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
3612 if (sdio_al->devices[i] == NULL) {
3613 sdio_al->devices[i] = sdio_al_dev;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003614 sdio_al_dev->dev_log = &sdio_al->device_log[i];
3615 spin_lock_init(&sdio_al_dev->dev_log->log_lock);
3616#ifdef CONFIG_DEBUG_FS
3617 sdio_al_dbgfs_log[i].data =
3618 sdio_al_dev->dev_log->buffer;
3619 sdio_al_dbgfs_log[i].size = SDIO_AL_DEBUG_LOG_SIZE;
3620#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003621 break;
3622 }
3623 if (i == MAX_NUM_OF_SDIO_DEVICES) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003624 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":No space in "
3625 "devices array for the device\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003626 return -ENOMEM;
3627 }
3628
3629 sdio_al_dev->is_ready = false;
3630
3631 sdio_al_dev->signature = SDIO_AL_SIGNATURE;
3632
3633 sdio_al_dev->is_suspended = 0;
3634 sdio_al_dev->is_timer_initialized = false;
3635
3636 sdio_al_dev->lpm_chan = INVALID_SDIO_CHAN;
3637
3638 sdio_al_dev->card = card;
3639
3640 sdio_al_dev->mailbox = kzalloc(sizeof(struct sdio_mailbox), GFP_KERNEL);
3641 if (sdio_al_dev->mailbox == NULL)
3642 return -ENOMEM;
3643
3644 sdio_al_dev->sdioc_sw_header
3645 = kzalloc(sizeof(*sdio_al_dev->sdioc_sw_header), GFP_KERNEL);
3646 if (sdio_al_dev->sdioc_sw_header == NULL)
3647 return -ENOMEM;
3648
Maya Erez5795e0d2011-09-12 20:20:06 +03003649
3650 sdio_al_dev->rx_flush_buf = kzalloc(RX_FLUSH_BUFFER_SIZE, GFP_KERNEL);
3651 if (sdio_al_dev->rx_flush_buf == NULL) {
3652 pr_err(MODULE_NAME ":Fail to allocate rx_flush_buf "
3653 "for card %d\n",
3654 card->host->index);
3655 return -ENOMEM;
3656 }
3657
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003658 sdio_al_dev->timer.data = (unsigned long)sdio_al_dev;
3659
3660 wake_lock_init(&sdio_al_dev->wake_lock, WAKE_LOCK_SUSPEND, MODULE_NAME);
3661 /* Don't allow sleep until all required clients register */
3662 sdio_al_vote_for_sleep(sdio_al_dev, 0);
3663
3664 sdio_claim_host(card->sdio_func[0]);
3665
3666 /* Init Func#1 */
Yaniv Gardi9a952d92011-09-06 13:46:30 +03003667 ret = sdio_al_enable_func_retry(card->sdio_func[0], "Init Func#1");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003668 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003669 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
3670 "enable Func#%d\n", card->sdio_func[0]->num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003671 goto exit;
3672 }
3673
3674 /* Patch Func CIS tuple issue */
3675 ret = sdio_set_block_size(card->sdio_func[0], SDIO_AL_BLOCK_SIZE);
3676 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003677 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to set "
3678 "block size, Func#%d\n", card->sdio_func[0]->num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003679 goto exit;
3680 }
3681 sdio_al_dev->card->sdio_func[0]->max_blksize = SDIO_AL_BLOCK_SIZE;
3682
3683 sdio_al_dev->workqueue = create_singlethread_workqueue("sdio_al_wq");
3684 sdio_al_dev->sdio_al_work.sdio_al_dev = sdio_al_dev;
3685 init_waitqueue_head(&sdio_al_dev->wait_mbox);
3686
3687 ret = sdio_al_client_setup(sdio_al_dev);
3688
3689exit:
3690 sdio_release_host(card->sdio_func[0]);
3691 return ret;
3692}
3693
3694static void sdio_al_sdio_remove(struct sdio_func *func)
3695{
3696 struct sdio_al_device *sdio_al_dev = NULL;
3697 int i;
3698 int state;
3699 struct mmc_card *card = NULL;
3700
3701 if (!func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003702 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
3703 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003704 return;
3705 }
3706 card = func->card;
3707
3708 if (!card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003709 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
3710 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003711 return;
3712 }
3713
3714 /* Find the sdio_al_device of this card */
3715 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
3716 if (sdio_al->devices[i] == NULL)
3717 continue;
3718 if (sdio_al->devices[i]->card == card) {
3719 sdio_al_dev = sdio_al->devices[i];
3720 sdio_al->devices[i] = NULL;
3721 break;
3722 }
3723 }
3724 if (sdio_al_dev == NULL) {
3725 pr_debug(MODULE_NAME ":%s :NULL sdio_al_dev for card %d\n",
3726 __func__, card->host->index);
3727 return;
3728 }
3729
Krishna Kondaa7af6062011-09-01 18:34:38 -07003730 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s for card %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003731 __func__, card->host->index);
3732
3733 if (card->sdio_func[0])
3734 sdio_claim_host(card->sdio_func[0]);
3735 else
Krishna Kondaa7af6062011-09-01 18:34:38 -07003736 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL func1 "
3737 "for card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003738
3739 if (sdio_al_dev->state == CARD_REMOVED)
3740 return;
3741
3742 state = sdio_al_dev->state;
3743 sdio_al_dev->state = CARD_REMOVED;
3744
3745 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++)
3746 sdio_al_dev->channel[i].signature = 0x0;
3747
Krishna Kondaa7af6062011-09-01 18:34:38 -07003748 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: ask_reading_mailbox "
3749 "for card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003750 sdio_al_dev->is_ready = false; /* Flag worker to exit */
3751 sdio_al_dev->ask_mbox = false;
3752 ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
3753
3754 if (state != MODEM_RESTART) {
3755 if (sdio_al_dev->is_timer_initialized) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003756 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Stop"
3757 " timer for card %d", __func__,
3758 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003759 sdio_al_dev->poll_delay_msec = 0;
3760 del_timer_sync(&sdio_al_dev->timer);
3761 }
3762
Krishna Kondaa7af6062011-09-01 18:34:38 -07003763 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: "
3764 "notifying clients for card %d\n",
Maya Erez8afd5642011-08-24 15:57:06 +03003765 __func__, card->host->index);
3766 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
3767 if (sdio_al_dev->channel[i].state ==
3768 SDIO_CHANNEL_STATE_INVALID)
3769 continue;
3770 platform_device_unregister(
3771 sdio_al_dev->channel[i].pdev);
3772 sdio_al_dev->channel[i].signature = 0x0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003773 }
3774 }
3775 if (card->sdio_func[0])
3776 sdio_release_host(card->sdio_func[0]);
3777
Krishna Kondaa7af6062011-09-01 18:34:38 -07003778 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: vote for sleep for "
3779 "card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003780 sdio_al_vote_for_sleep(sdio_al_dev, 1);
3781
Krishna Kondaa7af6062011-09-01 18:34:38 -07003782 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: flush_workqueue for "
3783 "card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003784 flush_workqueue(sdio_al_dev->workqueue);
3785 destroy_workqueue(sdio_al_dev->workqueue);
3786 wake_lock_destroy(&sdio_al_dev->wake_lock);
3787
Krishna Kondaa7af6062011-09-01 18:34:38 -07003788 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: delete data "
3789 "structures for card %d\n", __func__,
3790 card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003791 kfree(sdio_al_dev->sdioc_sw_header);
3792 kfree(sdio_al_dev->mailbox);
Maya Erez5795e0d2011-09-12 20:20:06 +03003793 kfree(sdio_al_dev->rx_flush_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003794 kfree(sdio_al_dev);
3795
Krishna Kondaa7af6062011-09-01 18:34:38 -07003796 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: sdio card %d removed."
3797 "\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003798}
3799
3800static void sdio_print_mailbox(char *prefix_str, struct sdio_mailbox *mailbox)
3801{
3802 int k = 0;
3803 char buf[256];
3804 char buf1[10];
3805
3806 if (!mailbox) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003807 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": mailbox is "
3808 "NULL\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003809 return;
3810 }
3811
Krishna Kondaa7af6062011-09-01 18:34:38 -07003812 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: pipes 0_7: eot=0x%x,"
3813 " thresh=0x%x, overflow=0x%x, "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003814 "underflow=0x%x, mask_thresh=0x%x\n",
3815 prefix_str, mailbox->eot_pipe_0_7,
3816 mailbox->thresh_above_limit_pipe_0_7,
3817 mailbox->overflow_pipe_0_7,
3818 mailbox->underflow_pipe_0_7,
3819 mailbox->mask_thresh_above_limit_pipe_0_7);
3820
3821 memset(buf, 0, sizeof(buf));
3822 strncat(buf, ": bytes_avail:", sizeof(buf));
3823
3824 for (k = 0 ; k < SDIO_AL_ACTIVE_PIPES ; ++k) {
3825 snprintf(buf1, sizeof(buf1), "%d, ",
3826 mailbox->pipe_bytes_avail[k]);
3827 strncat(buf, buf1, sizeof(buf));
3828 }
3829
Krishna Kondaa7af6062011-09-01 18:34:38 -07003830 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME "%s", buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003831}
3832
3833static void sdio_al_print_info(void)
3834{
3835 int i = 0;
3836 int j = 0;
3837 int ret = 0;
3838 struct sdio_mailbox *mailbox = NULL;
3839 struct sdio_mailbox *hw_mailbox = NULL;
3840 struct peer_sdioc_channel_config *ch_config = NULL;
3841 struct sdio_func *func1 = NULL;
3842 struct sdio_func *lpm_func = NULL;
3843 int offset = 0;
3844 int is_ok_to_sleep = 0;
3845 static atomic_t first_time;
3846 char buf[50];
3847
3848 if (atomic_read(&first_time) == 1)
3849 return;
3850
3851 atomic_set(&first_time, 1);
3852
Krishna Kondaa7af6062011-09-01 18:34:38 -07003853 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - SDIO DEBUG INFO\n",
3854 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003855
3856 if (!sdio_al) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003857 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - ERROR - "
3858 "sdio_al is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003859 return;
3860 }
3861
Krishna Kondaa7af6062011-09-01 18:34:38 -07003862 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": GPIO mdm2ap_status=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003863 sdio_al->pdata->get_mdm2ap_status());
3864
3865 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
3866 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
3867
3868 if (sdio_al_dev == NULL) {
3869 continue;
3870 }
3871
3872 if (!sdio_al_dev->card && !sdio_al_dev->card->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003873 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card"
3874 " or Host fields are NULL\n);");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003875 continue;
3876 }
3877
3878 snprintf(buf, sizeof(buf), "Card#%d: Shadow HW MB",
3879 sdio_al_dev->card->host->index);
3880
3881 /* printing Shadowing HW Mailbox*/
3882 mailbox = sdio_al_dev->mailbox;
3883 sdio_print_mailbox(buf, mailbox);
3884
Krishna Kondaa7af6062011-09-01 18:34:38 -07003885 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003886 "is_ok_to_sleep=%d\n",
3887 sdio_al_dev->card->host->index,
3888 sdio_al_dev->is_ok_to_sleep);
3889
3890
Krishna Kondaa7af6062011-09-01 18:34:38 -07003891 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003892 "Shadow channels SW MB:",
3893 sdio_al_dev->card->host->index);
3894
3895 /* printing Shadowing SW Mailbox per channel*/
3896 for (i = 0 ; i < SDIO_AL_MAX_CHANNELS ; ++i) {
3897 struct sdio_channel *ch = &sdio_al_dev->channel[i];
3898
3899 if (ch == NULL) {
3900 continue;
3901 }
3902
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003903 if (ch->state == SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003904 continue;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003905
3906 ch_config = &sdio_al_dev->channel[i].ch_config;
3907
Krishna Kondaa7af6062011-09-01 18:34:38 -07003908 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3909 ": Ch %s: max_rx_thres=0x%x, "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003910 "max_tx_thres=0x%x, tx_buf=0x%x, "
3911 "is_packet_mode=%d, "
3912 "max_packet=0x%x, min_write=0x%x",
3913 ch->name, ch_config->max_rx_threshold,
3914 ch_config->max_tx_threshold,
3915 ch_config->tx_buf_size,
3916 ch_config->is_packet_mode,
3917 ch_config->max_packet_size,
3918 ch->min_write_avail);
3919
Krishna Kondaa7af6062011-09-01 18:34:38 -07003920 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3921 ": total_rx=0x%x, total_tx=0x%x, "
3922 "read_avail=0x%x, write_avail=0x%x, "
3923 "rx_pending=0x%x, num_reads=0x%x, "
3924 "num_notifs=0x%x", ch->total_rx_bytes,
3925 ch->total_tx_bytes, ch->read_avail,
3926 ch->write_avail, ch->rx_pending_bytes,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003927 ch->statistics.total_read_times,
3928 ch->statistics.total_notifs);
3929 } /* end loop over all channels */
3930
3931 } /* end loop over all devices */
3932
3933 /* reading from client and printing is_host_ok_to_sleep per device */
3934 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
3935 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
3936
3937 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3938 return;
3939
3940 if (!sdio_al_dev->card->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003941 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3942 ": Host is NULL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003943 continue;
3944 }
3945
3946 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003947 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3948 ": %s - for Card#%d, is lpm_chan=="
3949 "INVALID_SDIO_CHAN. continuing...",
3950 __func__, sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003951 continue;
3952 }
3953
3954 offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
3955 sizeof(struct peer_sdioc_channel_config) *
3956 sdio_al_dev->lpm_chan+
3957 offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
3958
3959 lpm_func = sdio_al_dev->card->sdio_func[sdio_al_dev->
3960 lpm_chan+1];
3961 if (!lpm_func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003962 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3963 ": %s - lpm_func is NULL for card#%d"
3964 " continuing...\n", __func__,
3965 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003966 continue;
3967 }
3968
3969 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3970 ret = sdio_memcpy_fromio(lpm_func,
3971 &is_ok_to_sleep,
3972 SDIOC_SW_MAILBOX_ADDR+offset,
3973 sizeof(int));
Maya Erez1dd658a2011-08-09 10:14:47 +03003974 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3975 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003976 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3977
3978 if (ret)
Krishna Kondaa7af6062011-09-01 18:34:38 -07003979 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3980 ": %s - fail to read "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003981 "is_HOST_ok_to_sleep from mailbox for card %d",
3982 __func__, sdio_al_dev->card->host->index);
3983 else
Krishna Kondaa7af6062011-09-01 18:34:38 -07003984 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3985 ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003986 "is_HOST_ok_to_sleep=%d\n",
3987 sdio_al_dev->card->host->index,
3988 is_ok_to_sleep);
3989 }
3990
3991 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
3992 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
3993
3994 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3995 return;
3996
3997 if (!sdio_al_dev->card->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003998 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3999 ": Host is NULL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004000 continue;
4001 }
4002
4003 /* Reading HW Mailbox */
4004 hw_mailbox = sdio_al_dev->mailbox;
4005 func1 = sdio_al_dev->card->sdio_func[0];
4006
4007 sdio_claim_host(func1);
4008 ret = sdio_memcpy_fromio(func1, hw_mailbox,
4009 HW_MAILBOX_ADDR, sizeof(*hw_mailbox));
Maya Erez1dd658a2011-08-09 10:14:47 +03004010 if (sdio_al_verify_dev(sdio_al_dev, __func__))
4011 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004012 sdio_release_host(func1);
4013
4014 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004015 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4016 ": fail to read "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004017 "mailbox for card#%d. "
4018 "continuing...\n",
4019 sdio_al_dev->card->host->index);
4020 continue;
4021 }
4022
4023 snprintf(buf, sizeof(buf), "Card#%d: Current HW MB",
4024 sdio_al_dev->card->host->index);
4025
4026 /* Printing HW Mailbox */
4027 sdio_print_mailbox(buf, hw_mailbox);
4028 }
4029}
4030
4031static struct sdio_device_id sdio_al_sdioid[] = {
4032 {.class = 0, .vendor = 0x70, .device = 0x2460},
4033 {.class = 0, .vendor = 0x70, .device = 0x0460},
4034 {.class = 0, .vendor = 0x70, .device = 0x23F1},
4035 {.class = 0, .vendor = 0x70, .device = 0x23F0},
4036 {}
4037};
4038
4039static struct sdio_driver sdio_al_sdiofn_driver = {
4040 .name = "sdio_al_sdiofn",
4041 .id_table = sdio_al_sdioid,
4042 .probe = sdio_al_sdio_probe,
4043 .remove = sdio_al_sdio_remove,
4044};
4045
4046#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4047/*
4048 * Callback for notifications from restart mudule.
4049 * This function handles only the BEFORE_RESTART notification.
4050 * Stop all the activity on the card and notify our clients.
4051 */
4052static int sdio_al_subsys_notifier_cb(struct notifier_block *this,
4053 unsigned long notif_type,
4054 void *data)
4055{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004056 if (notif_type != SUBSYS_BEFORE_SHUTDOWN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004057 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: got "
4058 "notification %ld", __func__, notif_type);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004059 return NOTIFY_DONE;
4060 }
4061
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004062
Maya Erez6862b142011-08-22 09:07:07 +03004063 msm_sdio_al_shutdown(NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004064 return NOTIFY_OK;
4065}
4066
4067static struct notifier_block sdio_al_nb = {
4068 .notifier_call = sdio_al_subsys_notifier_cb,
4069};
4070#endif
4071
4072/**
4073 * Module Init.
4074 *
4075 * @warn: allocate sdio_al context before registering driver.
4076 *
4077 */
4078static int __init sdio_al_init(void)
4079{
4080 int ret = 0;
4081 int i;
4082
4083 pr_debug(MODULE_NAME ":sdio_al_init\n");
4084
4085 pr_info(MODULE_NAME ":SDIO-AL SW version %s\n",
4086 DRV_VERSION);
4087
4088 sdio_al = kzalloc(sizeof(struct sdio_al), GFP_KERNEL);
4089 if (sdio_al == NULL)
4090 return -ENOMEM;
4091
4092 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
4093 sdio_al->devices[i] = NULL;
4094
4095 sdio_al->unittest_mode = false;
4096
4097 sdio_al->debug.debug_lpm_on = debug_lpm_on;
4098 sdio_al->debug.debug_data_on = debug_data_on;
Maya Erez7ad06d82011-10-02 15:47:57 +02004099 sdio_al->debug.debug_close_on = debug_close_on;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004100
4101#ifdef CONFIG_DEBUG_FS
4102 sdio_al_debugfs_init();
4103#endif
4104
4105
4106#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4107 sdio_al->subsys_notif_handle = subsys_notif_register_notifier(
4108 "external_modem", &sdio_al_nb);
4109#endif
4110
4111 ret = platform_driver_register(&msm_sdio_al_driver);
4112 if (ret) {
4113 pr_err(MODULE_NAME ": platform_driver_register failed: %d\n",
4114 ret);
4115 goto exit;
4116 }
4117
4118 sdio_register_driver(&sdio_al_sdiofn_driver);
Krishna Kondaa7af6062011-09-01 18:34:38 -07004119
4120 spin_lock_init(&sdio_al->gen_log.log_lock);
4121
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004122exit:
4123 if (ret)
4124 kfree(sdio_al);
4125 return ret;
4126}
4127
4128/**
4129 * Module Exit.
4130 *
4131 * Free allocated memory.
4132 * Disable SDIO-Card.
4133 * Unregister driver.
4134 *
4135 */
4136static void __exit sdio_al_exit(void)
4137{
4138 if (sdio_al == NULL)
4139 return;
4140
4141 pr_debug(MODULE_NAME ":sdio_al_exit\n");
4142
4143#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4144 subsys_notif_unregister_notifier(
4145 sdio_al->subsys_notif_handle, &sdio_al_nb);
4146#endif
4147
4148 sdio_al_tear_down();
4149
4150 sdio_unregister_driver(&sdio_al_sdiofn_driver);
4151
4152 kfree(sdio_al);
4153
4154#ifdef CONFIG_DEBUG_FS
4155 sdio_al_debugfs_cleanup();
4156#endif
4157
4158 platform_driver_unregister(&msm_sdio_al_driver);
4159
4160 pr_debug(MODULE_NAME ":sdio_al_exit complete\n");
4161}
4162
4163module_init(sdio_al_init);
4164module_exit(sdio_al_exit);
4165
4166MODULE_LICENSE("GPL v2");
4167MODULE_DESCRIPTION("SDIO Abstraction Layer");
4168MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
4169MODULE_VERSION(DRV_VERSION);
4170