blob: ace437b9e14455d0478373b7cd3208717ff38732 [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)
Maya Erez3eb7d4c2011-10-17 15:08:42 +0200111#define LOW_LATENCY_THRESHOLD (1)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700112
Maya Erez8ed0a9a2011-07-19 14:46:53 +0300113/* Extra bytes to ensure getting the rx threshold interrupt on stream channels
114 when restoring the threshold after sleep */
115#define THRESHOLD_CHANGE_EXTRA_BYTES (100)
116
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117/** SW threshold to trigger reading the mailbox. */
118#define DEFAULT_MIN_WRITE_THRESHOLD (1024)
119#define DEFAULT_MIN_WRITE_THRESHOLD_STREAMING (1600)
120
121#define THRESHOLD_DISABLE_VAL (0xFFFFFFFF)
122
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700123/** 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;
Maya Erezc7f63282011-10-11 12:15:23 +0200354 int skip_print_info;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700355};
356
357struct sdio_al_work {
358 struct work_struct work;
359 struct sdio_al_device *sdio_al_dev;
360};
361
362
363/**
364 * SDIO Abstraction Layer device context.
365 *
366 * @card - card claimed.
367 *
368 * @mailbox - A shadow of the SDIO-Client mailbox.
369 *
370 * @channel - Channels context.
371 *
372 * @workqueue - workqueue to read the mailbox and handle
373 * pending requests. Reading the mailbox should not happen
374 * in interrupt context.
375 *
376 * @work - work to submit to workqueue.
377 *
378 * @is_ready - driver is ready.
379 *
380 * @ask_mbox - Flag to request reading the mailbox,
381 * for different reasons.
382 *
383 * @wake_lock - Lock when can't sleep.
384 *
385 * @lpm_chan - Channel to use for LPM (low power mode)
386 * communication.
387 *
388 * @is_ok_to_sleep - Mark if driver is OK with going to sleep
389 * (no pending transactions).
390 *
391 * @inactivity_time - time allowed to be in inactivity before
392 * going to sleep
393 *
394 * @timer - timer to use for polling the mailbox.
395 *
396 * @poll_delay_msec - timer delay for polling the mailbox.
397 *
398 * @is_err - error detected.
399 *
400 * @signature - Context Validity Check.
401 *
402 * @flashless_boot_on - flag to indicate if sdio_al is in
403 * flshless boot mode
404 *
405 */
406struct sdio_al_device {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700407 struct sdio_al_local_log *dev_log;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700408 struct mmc_card *card;
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200409 struct mmc_host *host;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700410 struct sdio_mailbox *mailbox;
411 struct sdio_channel channel[SDIO_AL_MAX_CHANNELS];
412
413 struct peer_sdioc_sw_header *sdioc_sw_header;
414 struct peer_sdioc_boot_sw_header *sdioc_boot_sw_header;
415
416 struct workqueue_struct *workqueue;
417 struct sdio_al_work sdio_al_work;
418 struct sdio_al_work boot_work;
419
420 int is_ready;
421
422 wait_queue_head_t wait_mbox;
423 int ask_mbox;
424 int bootloader_done;
425
426 struct wake_lock wake_lock;
427 int lpm_chan;
428 int is_ok_to_sleep;
429 unsigned long inactivity_time;
430
431 struct timer_list timer;
432 u32 poll_delay_msec;
433 int is_timer_initialized;
434
435 int is_err;
436
437 u32 signature;
438
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700439 unsigned int is_suspended;
440
441 int flashless_boot_on;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300442 int ch_close_supported;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700443 int state;
444 int (*lpm_callback)(void *, int);
Maya Erez7b1ebd22011-08-20 20:53:24 +0300445
446 int print_after_interrupt;
Maya Erez5795e0d2011-09-12 20:20:06 +0300447
448 u8 *rx_flush_buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700449};
450
451/*
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300452 * Host operation:
453 * lower 16bits are operation code
454 * upper 16bits are operation state
455 */
456#define PEER_OPERATION(op_code , op_state) ((op_code) | ((op_state) << 16))
457#define GET_PEER_OPERATION_CODE(op) ((op) & 0xffff)
458#define GET_PEER_OPERATION_STATE(op) ((op) >> 16)
459
460enum peer_op_code {
461 PEER_OP_CODE_CLOSE = 1
462};
463
464enum peer_op_state {
465 PEER_OP_STATE_INIT = 0,
466 PEER_OP_STATE_START = 1
467};
468
469
470/*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700471 * On the kernel command line specify
472 * sdio_al.debug_lpm_on=1 to enable the LPM debug messages
473 * By default the LPM debug messages are turned off
474 */
475static int debug_lpm_on;
476module_param(debug_lpm_on, int, 0);
477
478/*
479 * On the kernel command line specify
480 * sdio_al.debug_data_on=1 to enable the DATA debug messages
481 * By default the DATA debug messages are turned off
482 */
483static int debug_data_on;
484module_param(debug_data_on, int, 0);
485
Maya Erez7ad06d82011-10-02 15:47:57 +0200486/*
487 * Enables / disables open close debug messages
488 */
489static int debug_close_on = 1;
490module_param(debug_close_on, int, 0);
491
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700492/** The driver context */
493static struct sdio_al *sdio_al;
494
495/* Static functions declaration */
496static int enable_eot_interrupt(struct sdio_al_device *sdio_al_dev,
497 int pipe_index, int enable);
498static int enable_threshold_interrupt(struct sdio_al_device *sdio_al_dev,
499 int pipe_index, int enable);
500static void sdio_func_irq(struct sdio_func *func);
501static void sdio_al_timer_handler(unsigned long data);
502static int get_min_poll_time_msec(struct sdio_al_device *sdio_al_dev);
503static u32 check_pending_rx_packet(struct sdio_channel *ch, u32 eot);
504static u32 remove_handled_rx_packet(struct sdio_channel *ch);
505static int set_pipe_threshold(struct sdio_al_device *sdio_al_dev,
506 int pipe_index, int threshold);
507static int sdio_al_wake_up(struct sdio_al_device *sdio_al_dev,
Maya Erez7b1ebd22011-08-20 20:53:24 +0300508 u32 not_from_int, struct sdio_channel *ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700509static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev);
510static int enable_mask_irq(struct sdio_al_device *sdio_al_dev,
511 int func_num, int enable, u8 bit_offset);
512static int sdio_al_enable_func_retry(struct sdio_func *func, const char *name);
513static void sdio_al_print_info(void);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300514static int sdio_read_internal(struct sdio_channel *ch, void *data, int len);
Maya Erez5795e0d2011-09-12 20:20:06 +0300515static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len);
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200516static void stop_and_del_timer(struct sdio_al_device *sdio_al_dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700517
518#define SDIO_AL_ERR(func) \
519 do { \
520 printk_once(KERN_ERR MODULE_NAME \
521 ":In Error state, ignore %s\n", \
522 func); \
523 sdio_al_print_info(); \
524 } while (0)
525
526#ifdef CONFIG_DEBUG_FS
527static int debug_info_open(struct inode *inode, struct file *file)
528{
529 file->private_data = inode->i_private;
530 return 0;
531}
532
533static ssize_t debug_info_write(struct file *file,
534 const char __user *buf, size_t count, loff_t *ppos)
535{
536 sdio_al_print_info();
537 return 1;
538}
539
540const struct file_operations debug_info_ops = {
541 .open = debug_info_open,
542 .write = debug_info_write,
543};
544
Krishna Kondaa7af6062011-09-01 18:34:38 -0700545struct debugfs_blob_wrapper sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES + 1];
546
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700547/*
548*
549* Trigger on/off for debug messages
550* for trigger off the data messages debug level use:
551* echo 0 > /sys/kernel/debugfs/sdio_al/debug_data_on
552* for trigger on the data messages debug level use:
553* echo 1 > /sys/kernel/debugfs/sdio_al/debug_data_on
554* for trigger off the lpm messages debug level use:
555* echo 0 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
556* for trigger on the lpm messages debug level use:
557* echo 1 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
558*/
559static int sdio_al_debugfs_init(void)
560{
Krishna Kondaa7af6062011-09-01 18:34:38 -0700561 int i, blob_errs = 0;
562
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563 sdio_al->debug.sdio_al_debug_root = debugfs_create_dir("sdio_al", NULL);
564 if (!sdio_al->debug.sdio_al_debug_root)
565 return -ENOENT;
566
567 sdio_al->debug.sdio_al_debug_lpm_on = debugfs_create_u8("debug_lpm_on",
568 S_IRUGO | S_IWUGO,
569 sdio_al->debug.sdio_al_debug_root,
570 &sdio_al->debug.debug_lpm_on);
571
572 sdio_al->debug.sdio_al_debug_data_on = debugfs_create_u8(
573 "debug_data_on",
574 S_IRUGO | S_IWUGO,
575 sdio_al->debug.sdio_al_debug_root,
576 &sdio_al->debug.debug_data_on);
577
Maya Erez7ad06d82011-10-02 15:47:57 +0200578 sdio_al->debug.sdio_al_debug_close_on = debugfs_create_u8(
579 "debug_close_on",
580 S_IRUGO | S_IWUGO,
581 sdio_al->debug.sdio_al_debug_root,
582 &sdio_al->debug.debug_close_on);
583
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700584 sdio_al->debug.sdio_al_debug_info = debugfs_create_file(
585 "sdio_debug_info",
586 S_IRUGO | S_IWUGO,
587 sdio_al->debug.sdio_al_debug_root,
588 NULL,
589 &debug_info_ops);
590
Krishna Kondaa7af6062011-09-01 18:34:38 -0700591 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
592 char temp[18];
593
594 scnprintf(temp, 18, "sdio_al_log_dev_%d", i + 1);
595 sdio_al->debug.sdio_al_debug_log_buffers[i] =
596 debugfs_create_blob(temp,
597 S_IRUGO | S_IWUGO,
598 sdio_al->debug.sdio_al_debug_root,
599 &sdio_al_dbgfs_log[i]);
600 }
601
602 sdio_al->debug.sdio_al_debug_log_buffers[MAX_NUM_OF_SDIO_DEVICES] =
603 debugfs_create_blob("sdio_al_gen_log",
604 S_IRUGO | S_IWUGO,
605 sdio_al->debug.sdio_al_debug_root,
606 &sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES]);
607
608 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i) {
609 if (!sdio_al->debug.sdio_al_debug_log_buffers[i]) {
610 pr_err(MODULE_NAME ": Failed to create debugfs buffer"
611 " entry for "
612 "sdio_al->debug.sdio_al_debug_log_buffers[%d]",
613 i);
614 blob_errs = 1;
615 }
616 }
617
618 if (blob_errs) {
619 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i)
620 if (sdio_al->debug.sdio_al_debug_log_buffers[i])
621 debugfs_remove(
622 sdio_al->
623 debug.sdio_al_debug_log_buffers[i]);
624 }
625
626
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700627 if ((!sdio_al->debug.sdio_al_debug_data_on) &&
628 (!sdio_al->debug.sdio_al_debug_lpm_on) &&
Maya Erez7ad06d82011-10-02 15:47:57 +0200629 (!sdio_al->debug.sdio_al_debug_close_on) &&
Krishna Kondaa7af6062011-09-01 18:34:38 -0700630 (!sdio_al->debug.sdio_al_debug_info) &&
631 blob_errs) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700632 debugfs_remove(sdio_al->debug.sdio_al_debug_root);
633 sdio_al->debug.sdio_al_debug_root = NULL;
634 return -ENOENT;
635 }
Krishna Kondaa7af6062011-09-01 18:34:38 -0700636
637 sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES].data =
638 sdio_al->gen_log.buffer;
639 sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES].size =
640 SDIO_AL_DEBUG_LOG_SIZE;
641
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700642 return 0;
643}
644
645static void sdio_al_debugfs_cleanup(void)
646{
Krishna Kondaa7af6062011-09-01 18:34:38 -0700647 int i;
648
649 debugfs_remove(sdio_al->debug.sdio_al_debug_lpm_on);
650 debugfs_remove(sdio_al->debug.sdio_al_debug_data_on);
Maya Erez7ad06d82011-10-02 15:47:57 +0200651 debugfs_remove(sdio_al->debug.sdio_al_debug_close_on);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700652 debugfs_remove(sdio_al->debug.sdio_al_debug_info);
Krishna Kondaa7af6062011-09-01 18:34:38 -0700653
654 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i)
655 debugfs_remove(sdio_al->debug.sdio_al_debug_log_buffers[i]);
656
657 debugfs_remove(sdio_al->debug.sdio_al_debug_root);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700658}
659#endif
660
Krishna Kondaa7af6062011-09-01 18:34:38 -0700661static int sdio_al_log(struct sdio_al_local_log *log, const char *fmt, ...)
662{
663 va_list args;
664 int r;
665 char *tp, *log_buf;
666 unsigned int *log_cur_pos;
667 struct timeval kt;
668 unsigned long flags;
669 static char sdio_al_log_tmp[SDIO_AL_DEBUG_TMP_LOG_SIZE];
670
671 spin_lock_irqsave(&log->log_lock, flags);
672
673 kt = ktime_to_timeval(ktime_get());
674 r = scnprintf(sdio_al_log_tmp, SDIO_AL_DEBUG_TMP_LOG_SIZE,
675 "[%8ld.%6ld] ", kt.tv_sec, kt.tv_usec);
676
677 va_start(args, fmt);
678 r += vscnprintf(&sdio_al_log_tmp[r], (SDIO_AL_DEBUG_TMP_LOG_SIZE - r),
679 fmt, args);
680 va_end(args);
681
682 log_buf = log->buffer;
683 log_cur_pos = &(log->buf_cur_pos);
684
685 for (tp = sdio_al_log_tmp; tp < (sdio_al_log_tmp + r); tp++) {
686 log_buf[(*log_cur_pos)++] = *tp;
687 if ((*log_cur_pos) == SDIO_AL_DEBUG_LOG_SIZE)
688 *log_cur_pos = 0;
689 }
690
691 spin_unlock_irqrestore(&log->log_lock, flags);
692
693 return r;
694}
695
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700696static int sdio_al_verify_func1(struct sdio_al_device *sdio_al_dev,
697 char const *func)
698{
699 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700700 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
701 "sdio_al_dev\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700702 return -ENODEV;
703 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200704
705 if (sdio_al_dev->signature != SDIO_AL_SIGNATURE) {
706 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
707 "signature\n", func);
708 return -ENODEV;
709 }
710
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700711 if (!sdio_al_dev->card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700712 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
713 "card\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700714 return -ENODEV;
715 }
716 if (!sdio_al_dev->card->sdio_func[0]) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700717 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
718 "func1\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700719 return -ENODEV;
720 }
721 return 0;
722}
723
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200724static int sdio_al_claim_mutex(struct sdio_al_device *sdio_al_dev,
725 char const *func)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700726{
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200727 if (!sdio_al_dev) {
728 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
729 "device\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700730 return -ENODEV;
731 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200732
733 if (sdio_al_dev->signature != SDIO_AL_SIGNATURE) {
734 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
735 "device signature\n", func);
736 return -ENODEV;
737 }
738
739 if (!sdio_al_dev->host) {
740 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
741 "host\n", func);
742 return -ENODEV;
743 }
744
745 mmc_claim_host(sdio_al_dev->host);
746
747 return 0;
748}
749
750static int sdio_al_release_mutex(struct sdio_al_device *sdio_al_dev,
751 char const *func)
752{
753 if (!sdio_al_dev) {
754 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
755 "device\n", func);
756 return -ENODEV;
757 }
758
759 if (sdio_al_dev->signature != SDIO_AL_SIGNATURE) {
760 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
761 "device signature\n", func);
762 return -ENODEV;
763 }
764
765 if (!sdio_al_dev->host) {
766 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
767 "host\n", func);
768 return -ENODEV;
769 }
770
771 mmc_release_host(sdio_al_dev->host);
772
773 return 0;
774}
775
776static int sdio_al_claim_mutex_and_verify_dev(
777 struct sdio_al_device *sdio_al_dev,
778 char const *func)
779{
780 if (sdio_al_claim_mutex(sdio_al_dev, __func__))
781 return -ENODEV;
782
783 if (sdio_al_dev->state != CARD_INSERTED) {
784 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
785 "device state %d\n", func, sdio_al_dev->state);
786 sdio_al_release_mutex(sdio_al_dev, __func__);
787 return -ENODEV;
788 }
789
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700790 return 0;
791}
792
793static void sdio_al_get_into_err_state(struct sdio_al_device *sdio_al_dev)
794{
795 if ((!sdio_al) || (!sdio_al_dev))
796 return;
797
798 sdio_al_dev->is_err = true;
799 sdio_al->debug.debug_data_on = 0;
800 sdio_al->debug.debug_lpm_on = 0;
801 sdio_al_print_info();
802}
803
804void sdio_al_register_lpm_cb(void *device_handle,
805 int(*lpm_callback)(void *, int))
806{
807 struct sdio_al_device *sdio_al_dev =
808 (struct sdio_al_device *) device_handle;
809
810 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700811 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - "
812 "device_handle is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700813 return;
814 }
815
816 if (lpm_callback) {
817 sdio_al_dev->lpm_callback = lpm_callback;
818 lpm_callback((void *)sdio_al_dev,
819 sdio_al_dev->is_ok_to_sleep);
820 }
Krishna Kondaa7af6062011-09-01 18:34:38 -0700821
822 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - device %d "
823 "registered for wakeup callback\n", __func__,
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200824 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700825}
826
827void sdio_al_unregister_lpm_cb(void *device_handle)
828{
829 struct sdio_al_device *sdio_al_dev =
830 (struct sdio_al_device *) device_handle;
831
832 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700833 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - "
834 "device_handle is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700835 return;
836 }
837
838 sdio_al_dev->lpm_callback = NULL;
Krishna Kondaa7af6062011-09-01 18:34:38 -0700839 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - device %d "
840 "unregister for wakeup callback\n", __func__,
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200841 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700842}
843
844static void sdio_al_vote_for_sleep(struct sdio_al_device *sdio_al_dev,
845 int is_vote_for_sleep)
846{
847 pr_debug(MODULE_NAME ": %s()", __func__);
848
Yaniv Gardi3e327762011-07-27 11:11:04 +0300849 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700850 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - sdio_al_dev"
851 " is NULL\n", __func__);
Yaniv Gardi3e327762011-07-27 11:11:04 +0300852 return;
853 }
854
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700855 if (is_vote_for_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +0300856 pr_debug(MODULE_NAME ": %s - sdio vote for Sleep", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700857 wake_unlock(&sdio_al_dev->wake_lock);
858 } else {
Maya Erez7b1ebd22011-08-20 20:53:24 +0300859 pr_debug(MODULE_NAME ": %s - sdio vote against sleep",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700860 __func__);
861 wake_lock(&sdio_al_dev->wake_lock);
862 }
863
864 if (sdio_al_dev->lpm_callback != NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700865 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - "
866 "is_vote_for_sleep=%d for card#%d, "
867 "calling callback...", __func__,
868 is_vote_for_sleep,
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200869 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700870 sdio_al_dev->lpm_callback((void *)sdio_al_dev,
871 is_vote_for_sleep);
872 }
873}
874
875/**
876 * Write SDIO-Client lpm information
877 * Should only be called with host claimed.
878 */
879static int write_lpm_info(struct sdio_al_device *sdio_al_dev)
880{
881 struct sdio_func *lpm_func =
882 sdio_al_dev->card->sdio_func[sdio_al_dev->lpm_chan+1];
883 int offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
884 sizeof(struct peer_sdioc_channel_config) *
885 sdio_al_dev->lpm_chan+
886 offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
887 int ret;
888
889 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700890 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
891 "lpm_chan for card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200892 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700893 return -EINVAL;
894 }
895
896 pr_debug(MODULE_NAME ":write_lpm_info is_ok_to_sleep=%d, device %d\n",
897 sdio_al_dev->is_ok_to_sleep,
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200898 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700899
900 ret = sdio_memcpy_toio(lpm_func, SDIOC_SW_MAILBOX_ADDR+offset,
901 &sdio_al_dev->is_ok_to_sleep, sizeof(u32));
902 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700903 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
904 "write lpm info for card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200905 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700906 return ret;
907 }
908
909 return 0;
910}
911
912/* Set inactivity counter to intial value to allow clients come up */
913static inline void start_inactive_time(struct sdio_al_device *sdio_al_dev)
914{
915 sdio_al_dev->inactivity_time = jiffies +
916 msecs_to_jiffies(INITIAL_INACTIVITY_TIME_MSEC);
917}
918
919static inline void restart_inactive_time(struct sdio_al_device *sdio_al_dev)
920{
921 sdio_al_dev->inactivity_time = jiffies +
922 msecs_to_jiffies(INACTIVITY_TIME_MSEC);
923}
924
925static inline int is_inactive_time_expired(struct sdio_al_device *sdio_al_dev)
926{
927 return time_after(jiffies, sdio_al_dev->inactivity_time);
928}
929
930
931static int is_user_irq_enabled(struct sdio_al_device *sdio_al_dev,
932 int func_num)
933{
934 int ret = 0;
935 struct sdio_func *func1;
936 u32 user_irq = 0;
937 u32 addr = 0;
938 u32 offset = 0;
939 u32 masked_user_irq = 0;
940
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200941 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700942 return 0;
943 func1 = sdio_al_dev->card->sdio_func[0];
944
945 if (func_num < 4) {
946 addr = FUNC_1_4_USER_IRQ_ADDR;
947 offset = func_num * 8;
948 } else {
949 addr = FUNC_5_7_USER_IRQ_ADDR;
950 offset = (func_num - 4) * 8;
951 }
952
953 user_irq = sdio_readl(func1, addr, &ret);
954 if (ret) {
955 pr_debug(MODULE_NAME ":read_user_irq fail\n");
956 return 0;
957 }
958
959 masked_user_irq = (user_irq >> offset) && 0xFF;
960 if (masked_user_irq == 0x1) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700961 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":user_irq "
962 "enabled\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700963 return 1;
964 }
965
966 return 0;
967}
968
969static void sdio_al_sleep(struct sdio_al_device *sdio_al_dev,
970 struct mmc_host *host)
971{
972 int i;
973
974 /* Go to sleep */
Maya Erez7b1ebd22011-08-20 20:53:24 +0300975 pr_debug(MODULE_NAME ":Inactivity timer expired."
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700976 " Going to sleep\n");
977 /* Stop mailbox timer */
Maya Erez0fdb5ad2011-10-09 19:16:27 +0200978 stop_and_del_timer(sdio_al_dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700979 /* Make sure we get interrupt for non-packet-mode right away */
980 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
981 struct sdio_channel *ch = &sdio_al_dev->channel[i];
Maya Erez5795e0d2011-09-12 20:20:06 +0300982 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
983 (ch->state != SDIO_CHANNEL_STATE_CLOSED)) {
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300984 pr_debug(MODULE_NAME ":continue for channel %s in"
985 " state %d\n", ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700986 continue;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300987 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700988 if (ch->is_packet_mode == false) {
Maya Erez3eb7d4c2011-10-17 15:08:42 +0200989 ch->read_threshold = LOW_LATENCY_THRESHOLD;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700990 set_pipe_threshold(sdio_al_dev,
991 ch->rx_pipe_index,
992 ch->read_threshold);
993 }
994 }
Maya Erezfd915312011-07-14 13:45:34 +0300995 /* Prevent modem to go to sleep until we get the PROG_DONE on
996 the dummy CMD52 */
Maya Erez86cebda2011-10-11 11:13:40 +0200997 msmsdcc_set_pwrsave(sdio_al_dev->host, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700998 /* Mark HOST_OK_TOSLEEP */
999 sdio_al_dev->is_ok_to_sleep = 1;
1000 write_lpm_info(sdio_al_dev);
1001
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001002 msmsdcc_lpm_enable(host);
Krishna Kondaa7af6062011-09-01 18:34:38 -07001003 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Finished sleep sequence"
1004 " for card %d. Sleep now.\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001005 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001006 /* Release wakelock */
1007 sdio_al_vote_for_sleep(sdio_al_dev, 1);
1008}
1009
1010
1011/**
1012 * Read SDIO-Client Mailbox from Function#1.thresh_pipe
1013 *
1014 * The mailbox contain the bytes available per pipe,
1015 * and the End-Of-Transfer indication per pipe (if available).
1016 *
1017 * WARNING: Each time the Mailbox is read from the client, the
1018 * read_bytes_avail is incremented with another pending
1019 * transfer. Therefore, a pending rx-packet should be added to a
1020 * list before the next read of the mailbox.
1021 *
1022 * This function should run from a workqueue context since it
1023 * notifies the clients.
1024 *
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001025 * This function assumes that sdio_al_claim_mutex was called before
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001026 * calling it.
1027 *
1028 */
1029static int read_mailbox(struct sdio_al_device *sdio_al_dev, int from_isr)
1030{
1031 int ret;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001032 struct sdio_func *func1 = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001033 struct sdio_mailbox *mailbox = sdio_al_dev->mailbox;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001034 struct mmc_host *host = sdio_al_dev->host;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001035 u32 new_write_avail = 0;
1036 u32 old_write_avail = 0;
1037 u32 any_read_avail = 0;
1038 u32 any_write_pending = 0;
1039 int i;
1040 u32 rx_notify_bitmask = 0;
1041 u32 tx_notify_bitmask = 0;
1042 u32 eot_pipe = 0;
1043 u32 thresh_pipe = 0;
1044 u32 overflow_pipe = 0;
1045 u32 underflow_pipe = 0;
1046 u32 thresh_intr_mask = 0;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001047 int is_closing = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001048
1049 if (sdio_al_dev->is_err) {
1050 SDIO_AL_ERR(__func__);
1051 return 0;
1052 }
1053
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001054 if (sdio_al_verify_func1(sdio_al_dev, __func__))
1055 return -ENODEV;
1056 func1 = sdio_al_dev->card->sdio_func[0];
1057
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001058 pr_debug(MODULE_NAME ":start %s from_isr = %d for card %d.\n"
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001059 , __func__, from_isr, sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001060
1061 pr_debug(MODULE_NAME ":before sdio_memcpy_fromio.\n");
Maya Erez320a7ca2011-08-03 09:41:27 +03001062 memset(mailbox, 0, sizeof(struct sdio_mailbox));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001063 ret = sdio_memcpy_fromio(func1, mailbox,
1064 HW_MAILBOX_ADDR, sizeof(*mailbox));
1065 pr_debug(MODULE_NAME ":after sdio_memcpy_fromio.\n");
Maya Erez320a7ca2011-08-03 09:41:27 +03001066 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001067 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to read "
1068 "Mailbox for card %d, goto error state\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001069 sdio_al_dev->host->index);
Maya Erez320a7ca2011-08-03 09:41:27 +03001070 sdio_al_get_into_err_state(sdio_al_dev);
Maya Erez320a7ca2011-08-03 09:41:27 +03001071 goto exit_err;
1072 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001073
1074 eot_pipe = (mailbox->eot_pipe_0_7) |
1075 (mailbox->eot_pipe_8_15<<8);
1076 thresh_pipe = (mailbox->thresh_above_limit_pipe_0_7) |
1077 (mailbox->thresh_above_limit_pipe_8_15<<8);
1078
1079 overflow_pipe = (mailbox->overflow_pipe_0_7) |
1080 (mailbox->overflow_pipe_8_15<<8);
1081 underflow_pipe = mailbox->underflow_pipe_0_7 |
1082 (mailbox->underflow_pipe_8_15<<8);
1083 thresh_intr_mask =
1084 (mailbox->mask_thresh_above_limit_pipe_0_7) |
1085 (mailbox->mask_thresh_above_limit_pipe_8_15<<8);
1086
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001087 if (overflow_pipe || underflow_pipe)
Krishna Kondaa7af6062011-09-01 18:34:38 -07001088 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Mailbox ERROR "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001089 "overflow=0x%x, underflow=0x%x\n",
1090 overflow_pipe, underflow_pipe);
1091
1092 /* In case of modem reset we would like to read the daya from the modem
1093 to clear the interrupts but do not process it */
1094 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001095 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_device"
1096 " (card %d) is in invalid state %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001097 sdio_al_dev->host->index,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001098 sdio_al_dev->state);
1099 return -ENODEV;
1100 }
1101
1102 pr_debug(MODULE_NAME ":card %d: eot=0x%x, thresh=0x%x\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001103 sdio_al_dev->host->index,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001104 eot_pipe, thresh_pipe);
1105
1106 /* Scan for Rx Packets available and update read available bytes */
1107 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1108 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1109 u32 old_read_avail;
1110 u32 read_avail;
1111 u32 new_packet_size = 0;
1112
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001113 if (ch->state == SDIO_CHANNEL_STATE_CLOSING)
1114 is_closing = true; /* used to prevent sleep */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001115
1116 old_read_avail = ch->read_avail;
1117 read_avail = mailbox->pipe_bytes_avail[ch->rx_pipe_index];
1118
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001119 if ((ch->state == SDIO_CHANNEL_STATE_CLOSED) &&
1120 (read_avail > 0)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001121 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1122 ":%s: Invalid read_avail 0x%x, for CLOSED ch %s\n",
Maya Erez5795e0d2011-09-12 20:20:06 +03001123 __func__, read_avail, ch->name);
1124 sdio_read_from_closed_ch(ch, read_avail);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001125 }
1126 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
1127 (ch->state != SDIO_CHANNEL_STATE_CLOSING))
1128 continue;
1129
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001130 if (read_avail > INVALID_DATA_AVAILABLE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001131 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001132 ":Invalid read_avail 0x%x for pipe %d\n",
1133 read_avail, ch->rx_pipe_index);
1134 continue;
1135 }
1136 any_read_avail |= read_avail | old_read_avail;
1137 ch->statistics.last_any_read_avail = any_read_avail;
1138 ch->statistics.last_read_avail = read_avail;
1139 ch->statistics.last_old_read_avail = old_read_avail;
1140
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001141 if (ch->is_packet_mode) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001142 if ((eot_pipe & (1<<ch->rx_pipe_index)) &&
1143 sdio_al_dev->print_after_interrupt) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001144 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME
1145 ":Interrupt on ch %s, "
1146 "card %d", ch->name,
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001147 sdio_al_dev->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03001148 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001149 new_packet_size = check_pending_rx_packet(ch, eot_pipe);
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001150 } else {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001151 if ((thresh_pipe & (1<<ch->rx_pipe_index)) &&
1152 sdio_al_dev->print_after_interrupt) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001153 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME
1154 ":Interrupt on ch %s, "
1155 "card %d", ch->name,
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001156 sdio_al_dev->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03001157 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001158 ch->read_avail = read_avail;
Maya Erez3eb7d4c2011-10-17 15:08:42 +02001159
1160 /*
1161 * Restore default thresh for non packet channels.
1162 * in case it IS low latency channel then read_threshold
1163 * and def_read_threshold are both
1164 * LOW_LATENCY_THRESHOLD
1165 */
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001166 if ((ch->read_threshold != ch->def_read_threshold) &&
1167 (read_avail >= ch->threshold_change_cnt)) {
Maya Erez3eb7d4c2011-10-17 15:08:42 +02001168 if (!ch->is_low_latency_ch) {
1169 ch->read_threshold =
1170 ch->def_read_threshold;
1171 set_pipe_threshold(sdio_al_dev,
1172 ch->rx_pipe_index,
1173 ch->read_threshold);
1174 }
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001175 }
1176 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001177
1178 if ((ch->is_packet_mode) && (new_packet_size > 0)) {
1179 rx_notify_bitmask |= (1<<ch->num);
1180 ch->statistics.total_notifs++;
1181 }
1182
1183 if ((!ch->is_packet_mode) && (ch->read_avail > 0) &&
1184 (old_read_avail == 0)) {
1185 rx_notify_bitmask |= (1<<ch->num);
1186 ch->statistics.total_notifs++;
1187 }
1188 }
Maya Erez7b1ebd22011-08-20 20:53:24 +03001189 sdio_al_dev->print_after_interrupt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001190
1191 /* Update Write available */
1192 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1193 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1194
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001195 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
1196 (ch->state != SDIO_CHANNEL_STATE_CLOSING))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001197 continue;
1198
1199 new_write_avail = mailbox->pipe_bytes_avail[ch->tx_pipe_index];
1200
1201 if (new_write_avail > INVALID_DATA_AVAILABLE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001202 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001203 ":Invalid write_avail 0x%x for pipe %d\n",
1204 new_write_avail, ch->tx_pipe_index);
1205 continue;
1206 }
1207
1208 old_write_avail = ch->write_avail;
1209 ch->write_avail = new_write_avail;
1210
1211 if ((old_write_avail <= ch->min_write_avail) &&
1212 (new_write_avail >= ch->min_write_avail))
1213 tx_notify_bitmask |= (1<<ch->num);
1214
1215 /* There is not enough write avail for this channel.
1216 We need to keep reading mailbox to wait for the appropriate
1217 write avail and cannot sleep. Ignore SMEM channel that has
1218 only one direction. */
1219 if (strcmp(ch->name, "SDIO_SMEM"))
1220 any_write_pending |=
1221 (new_write_avail < ch->ch_config.max_tx_threshold);
1222 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001223 /* notify clients */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001224 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1225 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1226
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001227 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) ||
1228 (ch->notify == NULL))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001229 continue;
1230
1231 if (rx_notify_bitmask & (1<<ch->num))
1232 ch->notify(ch->priv,
1233 SDIO_EVENT_DATA_READ_AVAIL);
1234
1235 if (tx_notify_bitmask & (1<<ch->num))
1236 ch->notify(ch->priv,
1237 SDIO_EVENT_DATA_WRITE_AVAIL);
1238 }
1239
1240
1241 if ((rx_notify_bitmask == 0) && (tx_notify_bitmask == 0) &&
1242 !any_read_avail && !any_write_pending) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001243 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Nothing to "
1244 "Notify for card %d, is_closing=%d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001245 sdio_al_dev->host->index, is_closing);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001246 if (is_closing)
1247 restart_inactive_time(sdio_al_dev);
1248 else if (is_inactive_time_expired(sdio_al_dev))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001249 sdio_al_sleep(sdio_al_dev, host);
1250 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001251 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Notify bitmask"
1252 " for card %d rx=0x%x, tx=0x%x.\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001253 sdio_al_dev->host->index,
Krishna Kondaa7af6062011-09-01 18:34:38 -07001254 rx_notify_bitmask, tx_notify_bitmask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001255 /* Restart inactivity timer if any activity on the channel */
1256 restart_inactive_time(sdio_al_dev);
1257 }
1258
1259 pr_debug(MODULE_NAME ":end %s.\n", __func__);
1260
1261exit_err:
1262 return ret;
1263}
1264
1265/**
1266 * Check pending rx packet when reading the mailbox.
1267 */
1268static u32 check_pending_rx_packet(struct sdio_channel *ch, u32 eot)
1269{
1270 u32 rx_pending;
1271 u32 rx_avail;
1272 u32 new_packet_size = 0;
1273 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
1274
1275
1276 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001277 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
1278 " for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001279 return -EINVAL;
1280 }
1281
1282 mutex_lock(&ch->ch_lock);
1283
1284 rx_pending = ch->rx_pending_bytes;
1285 rx_avail = sdio_al_dev->mailbox->pipe_bytes_avail[ch->rx_pipe_index];
1286
1287 pr_debug(MODULE_NAME ":pipe %d of card %d rx_avail=0x%x, "
1288 "rx_pending=0x%x\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001289 ch->rx_pipe_index, sdio_al_dev->host->index, rx_avail,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001290 rx_pending);
1291
1292
1293 /* new packet detected */
1294 if (eot & (1<<ch->rx_pipe_index)) {
1295 struct rx_packet_size *p = NULL;
1296 new_packet_size = rx_avail - rx_pending;
1297
1298 if ((rx_avail <= rx_pending)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001299 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1300 ": Invalid new packet size."
1301 " rx_avail=%d.\n", rx_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001302 new_packet_size = 0;
1303 goto exit_err;
1304 }
1305
1306 p = kzalloc(sizeof(*p), GFP_KERNEL);
Maya Erezd9cc2292011-08-04 09:20:31 +03001307 if (p == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001308 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1309 ": failed to allocate item for "
1310 "rx_pending list. rx_avail=%d, "
1311 "rx_pending=%d.\n",
1312 rx_avail, rx_pending);
Maya Erezd9cc2292011-08-04 09:20:31 +03001313 new_packet_size = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001314 goto exit_err;
Maya Erezd9cc2292011-08-04 09:20:31 +03001315 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001316 p->size = new_packet_size;
1317 /* Add new packet as last */
1318 list_add_tail(&p->list, &ch->rx_size_list_head);
1319 ch->rx_pending_bytes += new_packet_size;
1320
1321 if (ch->read_avail == 0)
1322 ch->read_avail = new_packet_size;
1323 }
1324
1325exit_err:
1326 mutex_unlock(&ch->ch_lock);
1327
1328 return new_packet_size;
1329}
1330
1331
1332
1333/**
1334 * Remove first pending packet from the list.
1335 */
1336static u32 remove_handled_rx_packet(struct sdio_channel *ch)
1337{
1338 struct rx_packet_size *p = NULL;
1339
1340 mutex_lock(&ch->ch_lock);
1341
1342 ch->rx_pending_bytes -= ch->read_avail;
1343
1344 if (!list_empty(&ch->rx_size_list_head)) {
1345 p = list_first_entry(&ch->rx_size_list_head,
1346 struct rx_packet_size, list);
1347 list_del(&p->list);
1348 kfree(p);
Maya Erezd9cc2292011-08-04 09:20:31 +03001349 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001350 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: ch "
1351 "%s: unexpected empty list!!\n",
1352 __func__, ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001353 }
1354
1355 if (list_empty(&ch->rx_size_list_head)) {
1356 ch->read_avail = 0;
1357 } else {
1358 p = list_first_entry(&ch->rx_size_list_head,
1359 struct rx_packet_size, list);
1360 ch->read_avail = p->size;
1361 }
1362
1363 mutex_unlock(&ch->ch_lock);
1364
1365 return ch->read_avail;
1366}
1367
1368
1369/**
1370 * Bootloader worker function.
1371 *
1372 * @note: clear the bootloader_done flag only after reading the
1373 * mailbox, to ignore more requests while reading the mailbox.
1374 */
1375static void boot_worker(struct work_struct *work)
1376{
1377 int ret = 0;
1378 int func_num = 0;
1379 int i;
1380 struct sdio_al_device *sdio_al_dev = NULL;
1381 struct sdio_al_work *sdio_al_work = container_of(work,
1382 struct sdio_al_work,
1383 work);
1384
1385 if (sdio_al_work == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001386 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1387 "sdio_al_work\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001388 return;
1389 }
1390
1391 sdio_al_dev = sdio_al_work->sdio_al_dev;
1392 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001393 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1394 "sdio_al_dev\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001395 return;
1396 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07001397 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":Bootloader Worker Started"
1398 ", wait for bootloader_done event..\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001399 wait_event(sdio_al_dev->wait_mbox,
1400 sdio_al_dev->bootloader_done);
Krishna Kondaa7af6062011-09-01 18:34:38 -07001401 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":Got bootloader_done "
1402 "event..\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001403 /* Do polling until MDM is up */
1404 for (i = 0; i < 5000; ++i) {
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001405 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001406 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001407 if (is_user_irq_enabled(sdio_al_dev, func_num)) {
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001408 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001409 sdio_al_dev->bootloader_done = 0;
1410 ret = sdio_al_client_setup(sdio_al_dev);
1411 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001412 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1413 ": sdio_al_client_setup failed, "
1414 "for card %d ret=%d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001415 sdio_al_dev->host->index, ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001416 sdio_al_get_into_err_state(sdio_al_dev);
1417 }
1418 goto done;
1419 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001420 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001421 msleep(100);
1422 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07001423 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Timeout waiting for "
1424 "user_irq for card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001425 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001426 sdio_al_get_into_err_state(sdio_al_dev);
1427
1428done:
1429 pr_debug(MODULE_NAME ":Boot Worker for card %d Exit!\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001430 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001431}
1432
1433/**
1434 * Worker function.
1435 *
1436 * @note: clear the ask_mbox flag only after
1437 * reading the mailbox, to ignore more requests while
1438 * reading the mailbox.
1439 */
1440static void worker(struct work_struct *work)
1441{
1442 int ret = 0;
1443 struct sdio_al_device *sdio_al_dev = NULL;
1444 struct sdio_al_work *sdio_al_work = container_of(work,
1445 struct sdio_al_work,
1446 work);
1447 if (sdio_al_work == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001448 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": worker: NULL "
1449 "sdio_al_work\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001450 return;
1451 }
1452
1453 sdio_al_dev = sdio_al_work->sdio_al_dev;
1454 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001455 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": worker: NULL "
1456 "sdio_al_dev\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001457 return;
1458 }
1459 pr_debug(MODULE_NAME ":Worker Started..\n");
1460 while ((sdio_al_dev->is_ready) && (ret == 0)) {
1461 pr_debug(MODULE_NAME ":Wait for read mailbox request..\n");
1462 wait_event(sdio_al_dev->wait_mbox, sdio_al_dev->ask_mbox);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001463 if (!sdio_al_dev->is_ready)
1464 break;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001465 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
1466 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001467 if (sdio_al_dev->is_ok_to_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001468 ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001469 if (ret) {
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001470 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001471 return;
1472 }
1473 }
1474 ret = read_mailbox(sdio_al_dev, false);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001475 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001476 sdio_al_dev->ask_mbox = false;
1477 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001478
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001479 pr_debug(MODULE_NAME ":Worker Exit!\n");
1480}
1481
1482/**
1483 * Write command using CMD54 rather than CMD53.
1484 * Writing with CMD54 generate EOT interrupt at the
1485 * SDIO-Client.
1486 * Based on mmc_io_rw_extended()
1487 */
1488static int sdio_write_cmd54(struct mmc_card *card, unsigned fn,
1489 unsigned addr, const u8 *buf,
1490 unsigned blocks, unsigned blksz)
1491{
1492 struct mmc_request mrq;
1493 struct mmc_command cmd;
1494 struct mmc_data data;
1495 struct scatterlist sg;
1496 int incr_addr = 1; /* MUST */
1497 int write = 1;
1498
1499 BUG_ON(!card);
1500 BUG_ON(fn > 7);
1501 BUG_ON(blocks == 1 && blksz > 512);
1502 WARN_ON(blocks == 0);
1503 WARN_ON(blksz == 0);
1504
1505 write = true;
1506 pr_debug(MODULE_NAME ":sdio_write_cmd54()"
1507 "fn=%d,buf=0x%x,blocks=%d,blksz=%d\n",
1508 fn, (u32) buf, blocks, blksz);
1509
1510 memset(&mrq, 0, sizeof(struct mmc_request));
1511 memset(&cmd, 0, sizeof(struct mmc_command));
1512 memset(&data, 0, sizeof(struct mmc_data));
1513
1514 mrq.cmd = &cmd;
1515 mrq.data = &data;
1516
1517 cmd.opcode = SD_IO_RW_EXTENDED_QCOM;
1518
1519 cmd.arg = write ? 0x80000000 : 0x00000000;
1520 cmd.arg |= fn << 28;
1521 cmd.arg |= incr_addr ? 0x04000000 : 0x00000000;
1522 cmd.arg |= addr << 9;
1523 if (blocks == 1 && blksz <= 512)
1524 cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */
1525 else
1526 cmd.arg |= 0x08000000 | blocks; /* block mode */
1527 cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
1528
1529 data.blksz = blksz;
1530 data.blocks = blocks;
1531 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
1532 data.sg = &sg;
1533 data.sg_len = 1;
1534
1535 sg_init_one(&sg, buf, blksz * blocks);
1536
1537 mmc_set_data_timeout(&data, card);
1538
1539 mmc_wait_for_req(card->host, &mrq);
1540
1541 if (cmd.error)
1542 return cmd.error;
1543 if (data.error)
1544 return data.error;
1545
1546 if (mmc_host_is_spi(card->host)) {
1547 /* host driver already reported errors */
1548 } else {
1549 if (cmd.resp[0] & R5_ERROR) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001550 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1551 ":%s: R5_ERROR for card %d",
1552 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001553 return -EIO;
1554 }
1555 if (cmd.resp[0] & R5_FUNCTION_NUMBER) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001556 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1557 ":%s: R5_FUNCTION_NUMBER for card %d",
1558 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001559 return -EINVAL;
1560 }
1561 if (cmd.resp[0] & R5_OUT_OF_RANGE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001562 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1563 ":%s: R5_OUT_OF_RANGE for card %d",
1564 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001565 return -ERANGE;
1566 }
1567 }
1568
1569 return 0;
1570}
1571
1572
1573/**
1574 * Write data to channel.
1575 * Handle different data size types.
1576 *
1577 */
1578static int sdio_ch_write(struct sdio_channel *ch, const u8 *buf, u32 len)
1579{
1580 int ret = 0;
1581 unsigned blksz = ch->func->cur_blksize;
1582 int blocks = len / blksz;
1583 int remain_bytes = len % blksz;
1584 struct mmc_card *card = NULL;
1585 u32 fn = ch->func->num;
1586
Krishna Kondaa7af6062011-09-01 18:34:38 -07001587 if (!ch) {
1588 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1589 "channel\n", __func__);
1590 return -ENODEV;
1591 }
1592
1593 if (!ch->sdio_al_dev) {
1594 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1595 "sdio_al_dev\n", __func__);
1596 return -ENODEV;
1597 }
1598
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001599 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001600 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":channel "
1601 "%s trying to write 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001602 return -EINVAL;
1603 }
1604
1605 card = ch->func->card;
1606
1607 if (remain_bytes) {
1608 /* CMD53 */
1609 if (blocks) {
1610 ret = sdio_memcpy_toio(ch->func, PIPE_TX_FIFO_ADDR,
1611 (void *) buf, blocks*blksz);
1612 if (ret != 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001613 sdio_al_loge(ch->sdio_al_dev->dev_log,
1614 MODULE_NAME ":%s: sdio_memcpy_toio "
1615 "failed for channel %s\n",
1616 __func__, ch->name);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001617 sdio_al_get_into_err_state(ch->sdio_al_dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001618 return ret;
1619 }
1620 }
1621
1622 buf += (blocks*blksz);
1623
1624 ret = sdio_write_cmd54(card, fn, PIPE_TX_FIFO_ADDR,
1625 buf, 1, remain_bytes);
1626 } else {
1627 ret = sdio_write_cmd54(card, fn, PIPE_TX_FIFO_ADDR,
1628 buf, blocks, blksz);
1629 }
1630
1631 if (ret != 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001632 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
1633 "sdio_write_cmd54 failed for channel %s\n",
1634 __func__, ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001635 ch->sdio_al_dev->is_err = true;
1636 return ret;
1637 }
1638
1639 return ret;
1640}
1641
1642static int sdio_al_bootloader_completed(void)
1643{
1644 int i;
1645
1646 pr_debug(MODULE_NAME ":sdio_al_bootloader_completed was called\n");
1647
1648 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
1649 struct sdio_al_device *dev = NULL;
1650 if (sdio_al->devices[i] == NULL)
1651 continue;
1652 dev = sdio_al->devices[i];
1653 dev->bootloader_done = 1;
1654 wake_up(&dev->wait_mbox);
1655 }
1656
1657 return 0;
1658}
1659
1660static int sdio_al_wait_for_bootloader_comp(struct sdio_al_device *sdio_al_dev)
1661{
1662 int ret = 0;
1663
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001664 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001665 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001666
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001667 /*
1668 * Enable function 0 interrupt mask to allow 9k to raise this interrupt
1669 * in power-up. When sdio_downloader will notify its completion
1670 * we will poll on this interrupt to wait for 9k power-up
1671 */
1672 ret = enable_mask_irq(sdio_al_dev, 0, 1, 0);
1673 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001674 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1675 ": Enable_mask_irq for card %d failed, "
1676 "ret=%d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001677 sdio_al_dev->host->index, ret);
1678 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001679 return ret;
1680 }
1681
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001682 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001683
1684 /*
1685 * Start bootloader worker that will wait for the bootloader
1686 * completion
1687 */
1688 sdio_al_dev->boot_work.sdio_al_dev = sdio_al_dev;
1689 INIT_WORK(&sdio_al_dev->boot_work.work, boot_worker);
1690 sdio_al_dev->bootloader_done = 0;
1691 queue_work(sdio_al_dev->workqueue, &sdio_al_dev->boot_work.work);
1692
1693 return 0;
1694}
1695
1696static int sdio_al_bootloader_setup(void)
1697{
1698 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001699 struct sdio_al_device *bootloader_dev = sdio_al->bootloader_dev;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001700 struct sdio_func *func1 = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001701
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001702 if (sdio_al_claim_mutex_and_verify_dev(bootloader_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001703 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001704
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001705 if (bootloader_dev->flashless_boot_on) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001706 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":Already "
1707 "in boot process.\n");
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001708 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001709 return 0;
1710 }
1711
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001712 bootloader_dev->sdioc_boot_sw_header
1713 = kzalloc(sizeof(*bootloader_dev->sdioc_boot_sw_header),
1714 GFP_KERNEL);
1715 if (bootloader_dev->sdioc_boot_sw_header == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001716 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":fail to "
1717 "allocate sdioc boot sw header.\n");
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001718 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001719 return -ENOMEM;
1720 }
1721
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001722 if (sdio_al_verify_func1(bootloader_dev, __func__)) {
1723 sdio_al_release_mutex(bootloader_dev, __func__);
1724 goto exit_err;
1725 }
1726 func1 = bootloader_dev->card->sdio_func[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001727
1728 ret = sdio_memcpy_fromio(func1,
1729 bootloader_dev->sdioc_boot_sw_header,
1730 SDIOC_SW_HEADER_ADDR,
1731 sizeof(struct peer_sdioc_boot_sw_header));
1732 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001733 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":fail to "
1734 "read sdioc boot sw header.\n");
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001735 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001736 goto exit_err;
1737 }
1738
1739 if (bootloader_dev->sdioc_boot_sw_header->signature !=
1740 (u32) PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001741 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":invalid "
1742 "mailbox signature 0x%x.\n",
1743 bootloader_dev->sdioc_boot_sw_header->signature);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001744 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001745 ret = -EINVAL;
1746 goto exit_err;
1747 }
1748
1749 /* Upper byte has to be equal - no backward compatibility for unequal */
1750 if ((bootloader_dev->sdioc_boot_sw_header->version >> 16) !=
1751 (sdio_al->pdata->peer_sdioc_boot_version_major)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001752 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ": HOST(0x%x)"
1753 " and CLIENT(0x%x) SDIO_AL BOOT VERSION don't match\n",
1754 ((sdio_al->pdata->peer_sdioc_boot_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001755 sdio_al->pdata->peer_sdioc_boot_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001756 bootloader_dev->sdioc_boot_sw_header->version);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001757 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001758 ret = -EIO;
1759 goto exit_err;
1760 }
1761
Krishna Kondaa7af6062011-09-01 18:34:38 -07001762 sdio_al_logi(bootloader_dev->dev_log, MODULE_NAME ": SDIOC BOOT SW "
1763 "version 0x%x\n",
1764 bootloader_dev->sdioc_boot_sw_header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001765
1766 bootloader_dev->flashless_boot_on = true;
1767
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001768 sdio_al_release_mutex(bootloader_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001769
1770 ret = sdio_al_wait_for_bootloader_comp(bootloader_dev);
1771 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001772 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
1773 ": sdio_al_wait_for_bootloader_comp failed, "
1774 "err=%d\n", ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001775 goto exit_err;
1776 }
1777
1778 ret = sdio_downloader_setup(bootloader_dev->card, 1,
1779 bootloader_dev->sdioc_boot_sw_header->boot_ch_num,
1780 sdio_al_bootloader_completed);
1781
1782 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001783 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
1784 ": sdio_downloader_setup failed, err=%d\n", ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785 goto exit_err;
1786 }
1787
Krishna Kondaa7af6062011-09-01 18:34:38 -07001788 sdio_al_logi(bootloader_dev->dev_log, MODULE_NAME ":In Flashless boot,"
1789 " waiting for its completion\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001790
1791
1792exit_err:
Krishna Kondaa7af6062011-09-01 18:34:38 -07001793 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":free "
1794 "sdioc_boot_sw_header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001795 kfree(bootloader_dev->sdioc_boot_sw_header);
1796 bootloader_dev->sdioc_boot_sw_header = NULL;
1797 bootloader_dev = NULL;
1798
1799 return ret;
1800}
1801
1802
1803/**
1804 * Read SDIO-Client software header
1805 *
1806 */
1807static int read_sdioc_software_header(struct sdio_al_device *sdio_al_dev,
1808 struct peer_sdioc_sw_header *header)
1809{
1810 int ret;
1811 int i;
1812 int test_version = 0;
1813 int sdioc_test_version = 0;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001814 struct sdio_func *func1 = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001815
1816 pr_debug(MODULE_NAME ":reading sdioc sw header.\n");
1817
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001818 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001819 return -ENODEV;
1820
Maya Erez0fdb5ad2011-10-09 19:16:27 +02001821 func1 = sdio_al_dev->card->sdio_func[0];
1822
1823 ret = sdio_memcpy_fromio(func1, header,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001824 SDIOC_SW_HEADER_ADDR, sizeof(*header));
1825 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001826 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
1827 "sdioc sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001828 goto exit_err;
1829 }
1830
1831 if (header->signature == (u32)PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001832 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW "
1833 "unittest signature. 0x%x\n",
1834 header->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001835 sdio_al->unittest_mode = true;
1836 /* Verify test code compatibility with the modem */
1837 sdioc_test_version = (header->version & 0xFF00) >> 8;
1838 test_version = sdio_al->pdata->peer_sdioc_version_minor >> 8;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001839 if (test_version != sdioc_test_version) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001840 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1841 ": HOST(0x%x) and CLIENT(0x%x) "
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001842 "testing VERSION don't match\n",
Krishna Kondaa7af6062011-09-01 18:34:38 -07001843 test_version,
1844 sdioc_test_version);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001845 msleep(500);
1846 BUG();
1847 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001848 }
1849
1850 if ((header->signature != (u32) PEER_SDIOC_SW_MAILBOX_SIGNATURE) &&
1851 (header->signature != (u32) PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001852 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW "
1853 "invalid signature. 0x%x\n", header->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001854 goto exit_err;
1855 }
1856 /* Upper byte has to be equal - no backward compatibility for unequal */
1857 sdio_al->sdioc_major = header->version >> 16;
1858 if (sdio_al->pdata->allow_sdioc_version_major_2) {
1859 if ((sdio_al->sdioc_major !=
1860 sdio_al->pdata->peer_sdioc_version_major) &&
1861 (sdio_al->sdioc_major != PEER_SDIOC_OLD_VERSION_MAJOR)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001862 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1863 ": HOST(0x%x) and CLIENT(0x%x) "
1864 "SDIO_AL VERSION don't match\n",
1865 ((sdio_al->pdata->peer_sdioc_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001866 sdio_al->pdata->peer_sdioc_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001867 header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001868 goto exit_err;
1869 }
1870 } else {
1871 if (sdio_al->sdioc_major !=
1872 sdio_al->pdata->peer_sdioc_version_major) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001873 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1874 ": HOST(0x%x) and CLIENT(0x%x) "
1875 "SDIO_AL VERSION don't match\n",
1876 ((sdio_al->pdata->peer_sdioc_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001877 sdio_al->pdata->peer_sdioc_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001878 header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001879 goto exit_err;
1880 }
1881 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001882 sdio_al_dev->ch_close_supported = (header->version & 0x000F) >=
1883 (sdio_al->pdata->peer_sdioc_version_minor & 0xF);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001884
Krishna Kondaa7af6062011-09-01 18:34:38 -07001885 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW version 0x%x,"
1886 " sdio_al major 0x%x minor 0x%x\n", header->version,
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001887 sdio_al->sdioc_major,
1888 sdio_al->pdata->peer_sdioc_version_minor);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001889
1890 sdio_al_dev->flashless_boot_on = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001891 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1892 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1893
1894 /* Set default values */
1895 ch->read_threshold = DEFAULT_READ_THRESHOLD;
1896 ch->write_threshold = DEFAULT_WRITE_THRESHOLD;
1897 ch->min_write_avail = DEFAULT_MIN_WRITE_THRESHOLD;
1898 ch->is_packet_mode = true;
1899 ch->peer_tx_buf_size = DEFAULT_PEER_TX_BUF_SIZE;
1900 ch->poll_delay_msec = 0;
1901
1902 ch->num = i;
1903
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001904 ch->func = sdio_al_dev->card->sdio_func[ch->num+1];
1905 ch->rx_pipe_index = ch->num*2;
1906 ch->tx_pipe_index = ch->num*2+1;
1907
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001908 memset(ch->name, 0, sizeof(ch->name));
1909
1910 if (header->channel_names[i][0]) {
1911 memcpy(ch->name, SDIO_PREFIX,
1912 strlen(SDIO_PREFIX));
1913 memcpy(ch->name + strlen(SDIO_PREFIX),
1914 header->channel_names[i],
1915 PEER_CHANNEL_NAME_SIZE);
1916
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001917 ch->state = SDIO_CHANNEL_STATE_IDLE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001918 ch->sdio_al_dev = sdio_al_dev;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001919 } else {
1920 ch->state = SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001921 }
1922
Krishna Kondaa7af6062011-09-01 18:34:38 -07001923 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":Channel=%s, "
1924 "state=%d\n", ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001925 }
1926
1927 return 0;
1928
1929exit_err:
1930 sdio_al_get_into_err_state(sdio_al_dev);
1931 memset(header, 0, sizeof(*header));
1932
1933 return -EIO;
1934}
1935
1936/**
1937 * Read SDIO-Client channel configuration
1938 *
1939 */
1940static int read_sdioc_channel_config(struct sdio_channel *ch)
1941{
1942 int ret;
1943 struct peer_sdioc_sw_mailbox *sw_mailbox = NULL;
1944 struct peer_sdioc_channel_config *ch_config = NULL;
1945 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
1946
1947 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001948 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
1949 " for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001950 return -EINVAL;
1951 }
1952
1953 if (sdio_al_dev->sdioc_sw_header->version == 0)
1954 return -1;
1955
1956 pr_debug(MODULE_NAME ":reading sw mailbox %s channel.\n", ch->name);
1957
1958 sw_mailbox = kzalloc(sizeof(*sw_mailbox), GFP_KERNEL);
1959 if (sw_mailbox == NULL)
1960 return -ENOMEM;
1961
1962 ret = sdio_memcpy_fromio(ch->func, sw_mailbox,
1963 SDIOC_SW_MAILBOX_ADDR, sizeof(*sw_mailbox));
1964 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001965 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
1966 "sw mailbox.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001967 goto exit_err;
1968 }
1969
1970 ch_config = &sw_mailbox->ch_config[ch->num];
1971 memcpy(&ch->ch_config, ch_config,
1972 sizeof(struct peer_sdioc_channel_config));
1973
1974 if (!ch_config->is_ready) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001975 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sw mailbox "
1976 "channel not ready.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001977 goto exit_err;
1978 }
1979
Maya Erez3eb7d4c2011-10-17 15:08:42 +02001980 ch->read_threshold = LOW_LATENCY_THRESHOLD;
1981 ch->is_low_latency_ch = ch_config->is_low_latency_ch;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001982 /* Threshold on 50% of the maximum size , sdioc uses double-buffer */
1983 ch->write_threshold = (ch_config->max_tx_threshold * 5) / 10;
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001984 ch->threshold_change_cnt = ch->ch_config.max_rx_threshold -
1985 ch->read_threshold + THRESHOLD_CHANGE_EXTRA_BYTES;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001986
Maya Erez3eb7d4c2011-10-17 15:08:42 +02001987 if (ch->is_low_latency_ch)
1988 ch->def_read_threshold = LOW_LATENCY_THRESHOLD;
1989 else /* Aggregation up to 90% of the maximum size */
1990 ch->def_read_threshold = (ch_config->max_rx_threshold * 9) / 10;
1991
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001992 ch->is_packet_mode = ch_config->is_packet_mode;
1993 if (!ch->is_packet_mode) {
1994 ch->poll_delay_msec = DEFAULT_POLL_DELAY_NOPACKET_MSEC;
1995 ch->min_write_avail = DEFAULT_MIN_WRITE_THRESHOLD_STREAMING;
1996 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001997 /* The max_packet_size is set by the modem in version 3 and on */
1998 if (sdio_al->sdioc_major > PEER_SDIOC_OLD_VERSION_MAJOR)
1999 ch->min_write_avail = ch_config->max_packet_size;
2000
2001 if (ch->min_write_avail > ch->write_threshold)
2002 ch->min_write_avail = ch->write_threshold;
2003
Maya Erez7ad06d82011-10-02 15:47:57 +02002004 CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":ch %s "
Krishna Kondaa7af6062011-09-01 18:34:38 -07002005 "read_threshold=%d, write_threshold=%d,"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002006 " min_write_avail=%d, max_rx_threshold=%d,"
2007 " max_tx_threshold=%d\n", ch->name, ch->read_threshold,
2008 ch->write_threshold, ch->min_write_avail,
2009 ch_config->max_rx_threshold,
2010 ch_config->max_tx_threshold);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002011
2012 ch->peer_tx_buf_size = ch_config->tx_buf_size;
2013
2014 kfree(sw_mailbox);
2015
2016 return 0;
2017
2018exit_err:
Krishna Kondaa7af6062011-09-01 18:34:38 -07002019 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":Reading SW Mailbox "
2020 "error.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002021 kfree(sw_mailbox);
2022
2023 return -1;
2024}
2025
2026
2027/**
2028 * Enable/Disable EOT interrupt of a pipe.
2029 *
2030 */
2031static int enable_eot_interrupt(struct sdio_al_device *sdio_al_dev,
2032 int pipe_index, int enable)
2033{
2034 int ret = 0;
2035 struct sdio_func *func1;
2036 u32 mask;
2037 u32 pipe_mask;
2038 u32 addr;
2039
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002040 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002041 return -ENODEV;
2042 func1 = sdio_al_dev->card->sdio_func[0];
2043
2044 if (pipe_index < 8) {
2045 addr = PIPES_0_7_IRQ_MASK_ADDR;
2046 pipe_mask = (1<<pipe_index);
2047 } else {
2048 addr = PIPES_8_15_IRQ_MASK_ADDR;
2049 pipe_mask = (1<<(pipe_index-8));
2050 }
2051
2052 mask = sdio_readl(func1, addr, &ret);
2053 if (ret) {
2054 pr_debug(MODULE_NAME ":enable_eot_interrupt fail\n");
2055 goto exit_err;
2056 }
2057
2058 if (enable)
2059 mask &= (~pipe_mask); /* 0 = enable */
2060 else
2061 mask |= (pipe_mask); /* 1 = disable */
2062
2063 sdio_writel(func1, mask, addr, &ret);
2064
2065exit_err:
2066 return ret;
2067}
2068
2069
2070/**
2071 * Enable/Disable mask interrupt of a function.
2072 *
2073 */
2074static int enable_mask_irq(struct sdio_al_device *sdio_al_dev,
2075 int func_num, int enable, u8 bit_offset)
2076{
2077 int ret = 0;
2078 struct sdio_func *func1 = NULL;
2079 u32 mask = 0;
2080 u32 func_mask = 0;
2081 u32 addr = 0;
2082 u32 offset = 0;
2083
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002084 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002085 return -ENODEV;
2086 func1 = sdio_al_dev->card->sdio_func[0];
2087
2088 if (func_num < 4) {
2089 addr = FUNC_1_4_MASK_IRQ_ADDR;
2090 offset = func_num * 8 + bit_offset;
2091 } else {
2092 addr = FUNC_5_7_MASK_IRQ_ADDR;
2093 offset = (func_num - 4) * 8 + bit_offset;
2094 }
2095
2096 func_mask = 1<<offset;
2097
2098 mask = sdio_readl(func1, addr, &ret);
2099 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002100 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2101 "enable_mask_irq fail\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002102 goto exit_err;
2103 }
2104
2105 if (enable)
2106 mask &= (~func_mask); /* 0 = enable */
2107 else
2108 mask |= (func_mask); /* 1 = disable */
2109
2110 pr_debug(MODULE_NAME ":enable_mask_irq, writing mask = 0x%x\n", mask);
2111
2112 sdio_writel(func1, mask, addr, &ret);
2113
2114exit_err:
2115 return ret;
2116}
2117
2118/**
2119 * Enable/Disable Threshold interrupt of a pipe.
2120 *
2121 */
2122static int enable_threshold_interrupt(struct sdio_al_device *sdio_al_dev,
2123 int pipe_index, int enable)
2124{
2125 int ret = 0;
2126 struct sdio_func *func1;
2127 u32 mask;
2128 u32 pipe_mask;
2129 u32 addr;
2130
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002131 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002132 return -ENODEV;
2133 func1 = sdio_al_dev->card->sdio_func[0];
2134
2135 if (pipe_index < 8) {
2136 addr = PIPES_0_7_IRQ_MASK_ADDR;
2137 pipe_mask = (1<<pipe_index);
2138 } else {
2139 addr = PIPES_8_15_IRQ_MASK_ADDR;
2140 pipe_mask = (1<<(pipe_index-8));
2141 }
2142
2143 mask = sdio_readl(func1, addr, &ret);
2144 if (ret) {
2145 pr_debug(MODULE_NAME ":enable_threshold_interrupt fail\n");
2146 goto exit_err;
2147 }
2148
2149 pipe_mask = pipe_mask<<8; /* Threshold bits 8..15 */
2150 if (enable)
2151 mask &= (~pipe_mask); /* 0 = enable */
2152 else
2153 mask |= (pipe_mask); /* 1 = disable */
2154
2155 sdio_writel(func1, mask, addr, &ret);
2156
2157exit_err:
2158 return ret;
2159}
2160
2161/**
2162 * Set the threshold to trigger interrupt from SDIO-Card on
2163 * pipe available bytes.
2164 *
2165 */
2166static int set_pipe_threshold(struct sdio_al_device *sdio_al_dev,
2167 int pipe_index, int threshold)
2168{
2169 int ret = 0;
2170 struct sdio_func *func1;
2171
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002172 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002173 return -ENODEV;
2174 func1 = sdio_al_dev->card->sdio_func[0];
2175
2176 sdio_writel(func1, threshold,
2177 PIPES_THRESHOLD_ADDR+pipe_index*4, &ret);
2178 if (ret)
Krishna Kondaa7af6062011-09-01 18:34:38 -07002179 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2180 "set_pipe_threshold err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002181
2182 return ret;
2183}
2184
2185/**
2186 * Enable func w/ retries
2187 *
2188 */
2189static int sdio_al_enable_func_retry(struct sdio_func *func, const char *name)
2190{
2191 int ret, i;
2192 for (i = 0; i < 200; i++) {
2193 ret = sdio_enable_func(func);
2194 if (ret) {
2195 pr_debug(MODULE_NAME ":retry enable %s func#%d "
2196 "ret=%d\n",
2197 name, func->num, ret);
2198 msleep(10);
2199 } else
2200 break;
2201 }
2202
2203 return ret;
2204}
2205
2206/**
2207 * Open Channel
2208 *
2209 * 1. Init Channel Context.
2210 * 2. Init the Channel SDIO-Function.
2211 * 3. Init the Channel Pipes on Mailbox.
2212 */
2213static int open_channel(struct sdio_channel *ch)
2214{
2215 int ret = 0;
2216 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
2217
2218 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002219 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL "
2220 "sdio_al_dev for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002221 return -EINVAL;
2222 }
2223
2224 /* Init channel Context */
2225 /** Func#1 is reserved for mailbox */
2226 ch->func = sdio_al_dev->card->sdio_func[ch->num+1];
2227 ch->rx_pipe_index = ch->num*2;
2228 ch->tx_pipe_index = ch->num*2+1;
2229 ch->signature = SDIO_AL_SIGNATURE;
2230
2231 ch->total_rx_bytes = 0;
2232 ch->total_tx_bytes = 0;
2233
2234 ch->write_avail = 0;
2235 ch->read_avail = 0;
2236 ch->rx_pending_bytes = 0;
2237
2238 mutex_init(&ch->ch_lock);
2239
2240 pr_debug(MODULE_NAME ":open_channel %s func#%d\n",
2241 ch->name, ch->func->num);
2242
2243 INIT_LIST_HEAD(&(ch->rx_size_list_head));
2244
2245 /* Init SDIO Function */
2246 ret = sdio_al_enable_func_retry(ch->func, ch->name);
2247 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002248 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2249 "sdio_enable_func() err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002250 goto exit_err;
2251 }
2252
2253 /* Note: Patch Func CIS tuple issue */
2254 ret = sdio_set_block_size(ch->func, SDIO_AL_BLOCK_SIZE);
2255 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002256 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2257 "sdio_set_block_size()failed, err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002258 goto exit_err;
2259 }
2260
2261 ch->func->max_blksize = SDIO_AL_BLOCK_SIZE;
2262
2263 sdio_set_drvdata(ch->func, ch);
2264
2265 /* Get channel parameters from the peer SDIO-Client */
2266 read_sdioc_channel_config(ch);
2267
2268 /* Set Pipes Threshold on Mailbox */
2269 ret = set_pipe_threshold(sdio_al_dev,
2270 ch->rx_pipe_index, ch->read_threshold);
2271 if (ret)
2272 goto exit_err;
2273 ret = set_pipe_threshold(sdio_al_dev,
2274 ch->tx_pipe_index, ch->write_threshold);
2275 if (ret)
2276 goto exit_err;
2277
2278 /* Set flag before interrupts are enabled to allow notify */
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002279 ch->state = SDIO_CHANNEL_STATE_OPEN;
2280 pr_debug(MODULE_NAME ":channel %s is in OPEN state now\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002281
2282 sdio_al_dev->poll_delay_msec = get_min_poll_time_msec(sdio_al_dev);
2283
2284 /* lpm mechanism lives under the assumption there is always a timer */
2285 /* Check if need to start the timer */
2286 if ((sdio_al_dev->poll_delay_msec) &&
2287 (sdio_al_dev->is_timer_initialized == false)) {
2288
2289 init_timer(&sdio_al_dev->timer);
2290 sdio_al_dev->timer.data = (unsigned long) sdio_al_dev;
2291 sdio_al_dev->timer.function = sdio_al_timer_handler;
2292 sdio_al_dev->timer.expires = jiffies +
2293 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2294 add_timer(&sdio_al_dev->timer);
2295 sdio_al_dev->is_timer_initialized = true;
2296 }
2297
2298 /* Enable Pipes Interrupts */
2299 enable_eot_interrupt(sdio_al_dev, ch->rx_pipe_index, true);
2300 enable_eot_interrupt(sdio_al_dev, ch->tx_pipe_index, true);
2301
2302 enable_threshold_interrupt(sdio_al_dev, ch->rx_pipe_index, true);
2303 enable_threshold_interrupt(sdio_al_dev, ch->tx_pipe_index, true);
2304
2305exit_err:
2306
2307 return ret;
2308}
2309
2310/**
2311 * Ask the worker to read the mailbox.
2312 */
2313static void ask_reading_mailbox(struct sdio_al_device *sdio_al_dev)
2314{
2315 if (!sdio_al_dev->ask_mbox) {
2316 pr_debug(MODULE_NAME ":ask_reading_mailbox for card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002317 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002318 sdio_al_dev->ask_mbox = true;
2319 wake_up(&sdio_al_dev->wait_mbox);
2320 }
2321}
2322
2323/**
2324 * Start the timer
2325 */
2326static void start_timer(struct sdio_al_device *sdio_al_dev)
2327{
2328 if ((sdio_al_dev->poll_delay_msec) &&
2329 (sdio_al_dev->state == CARD_INSERTED)) {
2330 sdio_al_dev->timer.expires = jiffies +
2331 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2332 add_timer(&sdio_al_dev->timer);
2333 }
2334}
2335
2336/**
2337 * Restart(postpone) the already working timer
2338 */
2339static void restart_timer(struct sdio_al_device *sdio_al_dev)
2340{
2341 if ((sdio_al_dev->poll_delay_msec) &&
2342 (sdio_al_dev->state == CARD_INSERTED)) {
2343 ulong expires = jiffies +
2344 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2345 mod_timer(&sdio_al_dev->timer, expires);
2346 }
2347}
2348
2349/**
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002350 * Stop and delete the timer
2351 */
2352static void stop_and_del_timer(struct sdio_al_device *sdio_al_dev)
2353{
2354 if (sdio_al_dev->is_timer_initialized) {
2355 sdio_al_dev->poll_delay_msec = 0;
2356 del_timer_sync(&sdio_al_dev->timer);
2357 }
2358}
2359
2360/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002361 * Do the wakup sequence.
2362 * This function should be called after claiming the host!
2363 * The caller is responsible for releasing the host.
2364 *
2365 * Wake up sequence
2366 * 1. Get lock
2367 * 2. Enable wake up function if needed
2368 * 3. Mark NOT OK to sleep and write it
2369 * 4. Restore default thresholds
2370 * 5. Start the mailbox and inactivity timer again
2371 */
2372static int sdio_al_wake_up(struct sdio_al_device *sdio_al_dev,
Maya Erez7b1ebd22011-08-20 20:53:24 +03002373 u32 not_from_int, struct sdio_channel *ch)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002374{
Maya Erez8ed0a9a2011-07-19 14:46:53 +03002375 int ret = 0;
Maya Erez86cebda2011-10-11 11:13:40 +02002376 struct sdio_func *wk_func = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002377 unsigned long time_to_wait;
Maya Erez86cebda2011-10-11 11:13:40 +02002378 struct mmc_host *host = sdio_al_dev->host;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002379
2380 if (sdio_al_dev->is_err) {
2381 SDIO_AL_ERR(__func__);
2382 return -ENODEV;
2383 }
2384
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002385 if (!sdio_al_dev->is_ok_to_sleep) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002386 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":card %d "
2387 "already awake, no need to wake up\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002388 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002389 return 0;
2390 }
Maya Erez7b1ebd22011-08-20 20:53:24 +03002391
2392 /* Wake up sequence */
2393 if (not_from_int) {
2394 if (ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002395 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up"
2396 " card %d (not by interrupt), ch %s",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002397 sdio_al_dev->host->index,
Krishna Kondaa7af6062011-09-01 18:34:38 -07002398 ch->name);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002399 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002400 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up"
2401 " card %d (not by interrupt)",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002402 sdio_al_dev->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002403 }
2404 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002405 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up card "
2406 "%d by interrupt",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002407 sdio_al_dev->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002408 sdio_al_dev->print_after_interrupt = 1;
2409 }
2410
Yaniv Gardi3e327762011-07-27 11:11:04 +03002411 sdio_al_vote_for_sleep(sdio_al_dev, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002412
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002413 msmsdcc_lpm_disable(host);
Maya Erez86cebda2011-10-11 11:13:40 +02002414 msmsdcc_set_pwrsave(host, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002415 /* Poll the GPIO */
2416 time_to_wait = jiffies + msecs_to_jiffies(1000);
2417 while (time_before(jiffies, time_to_wait)) {
2418 if (sdio_al->pdata->get_mdm2ap_status())
2419 break;
2420 udelay(TIME_TO_WAIT_US);
2421 }
Yaniv Gardi3e327762011-07-27 11:11:04 +03002422
Maya Erez7b1ebd22011-08-20 20:53:24 +03002423 pr_debug(MODULE_NAME ":GPIO mdm2ap_status=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002424 sdio_al->pdata->get_mdm2ap_status());
2425
2426 /* Here get_mdm2ap_status() returning 0 is not an error condition */
2427 if (sdio_al->pdata->get_mdm2ap_status() == 0)
Krishna Kondaa7af6062011-09-01 18:34:38 -07002428 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": "
2429 "get_mdm2ap_status() is 0\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002430
2431 /* Enable Wake up Function */
Maya Erez86cebda2011-10-11 11:13:40 +02002432 if (!sdio_al_dev->card ||
2433 !sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1]) {
2434 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2435 ": NULL card or wk_func\n");
2436 return -ENODEV;
2437 }
2438 wk_func = sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002439 ret = sdio_al_enable_func_retry(wk_func, "wakeup func");
2440 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002441 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2442 "sdio_enable_func() err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002443 goto error_exit;
2444 }
2445 /* Mark NOT OK_TOSLEEP */
2446 sdio_al_dev->is_ok_to_sleep = 0;
2447 ret = write_lpm_info(sdio_al_dev);
2448 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002449 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2450 "write_lpm_info() failed, err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002451 sdio_al_dev->is_ok_to_sleep = 1;
2452 sdio_disable_func(wk_func);
2453 goto error_exit;
2454 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002455 sdio_disable_func(wk_func);
2456
2457 /* Start the timer again*/
2458 restart_inactive_time(sdio_al_dev);
2459 sdio_al_dev->poll_delay_msec = get_min_poll_time_msec(sdio_al_dev);
2460 start_timer(sdio_al_dev);
2461
Krishna Kondaa7af6062011-09-01 18:34:38 -07002462 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME "Finished Wake up sequence"
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002463 " for card %d", sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002464
Maya Erez86cebda2011-10-11 11:13:40 +02002465 msmsdcc_set_pwrsave(host, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002466 pr_debug(MODULE_NAME ":Turn clock off\n");
2467
2468 return ret;
2469error_exit:
2470 sdio_al_vote_for_sleep(sdio_al_dev, 1);
Maya Erez86cebda2011-10-11 11:13:40 +02002471 msmsdcc_set_pwrsave(host, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002472 WARN_ON(ret);
2473 sdio_al_get_into_err_state(sdio_al_dev);
2474 return ret;
2475}
2476
2477
2478/**
2479 * SDIO Function Interrupt handler.
2480 *
2481 * Interrupt shall be triggered by SDIO-Client when:
2482 * 1. End-Of-Transfer (EOT) detected in packet mode.
2483 * 2. Bytes-available reached the threshold.
2484 *
2485 * Reading the mailbox clears the EOT/Threshold interrupt
2486 * source.
2487 * The interrupt source should be cleared before this ISR
2488 * returns. This ISR is called from IRQ Thread and not
2489 * interrupt, so it may sleep.
2490 *
2491 */
2492static void sdio_func_irq(struct sdio_func *func)
2493{
2494 struct sdio_al_device *sdio_al_dev = sdio_get_drvdata(func);
2495
2496 pr_debug(MODULE_NAME ":start %s.\n", __func__);
2497
2498 if (sdio_al_dev == NULL) {
Maya Erez86cebda2011-10-11 11:13:40 +02002499 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL device");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002500 return;
2501 }
2502
2503 if (sdio_al_dev->is_ok_to_sleep)
Maya Erez7b1ebd22011-08-20 20:53:24 +03002504 sdio_al_wake_up(sdio_al_dev, 0, NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002505 else
2506 restart_timer(sdio_al_dev);
2507
2508 read_mailbox(sdio_al_dev, true);
2509
2510 pr_debug(MODULE_NAME ":end %s.\n", __func__);
2511}
2512
2513/**
2514 * Timer Expire Handler
2515 *
2516 */
2517static void sdio_al_timer_handler(unsigned long data)
2518{
2519 struct sdio_al_device *sdio_al_dev = (struct sdio_al_device *)data;
2520 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002521 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": NULL "
2522 "sdio_al_dev for data %lu\n", data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002523 return;
2524 }
2525 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002526 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": sdio_al_dev "
2527 "is in invalid state %d\n", sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002528 return;
2529 }
2530 pr_debug(MODULE_NAME " Timer Expired\n");
2531
2532 ask_reading_mailbox(sdio_al_dev);
2533
2534 restart_timer(sdio_al_dev);
2535}
2536
2537/**
2538 * Driver Setup.
2539 *
2540 */
2541static int sdio_al_setup(struct sdio_al_device *sdio_al_dev)
2542{
2543 int ret = 0;
2544 struct mmc_card *card = sdio_al_dev->card;
2545 struct sdio_func *func1 = NULL;
2546 int i = 0;
2547 int fn = 0;
2548
Maya Erez86cebda2011-10-11 11:13:40 +02002549 if (sdio_al_verify_func1(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002550 return -ENODEV;
Maya Erez86cebda2011-10-11 11:13:40 +02002551 func1 = card->sdio_func[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002552
Krishna Kondaa7af6062011-09-01 18:34:38 -07002553 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_setup for "
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002554 "card %d\n", sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002555
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002556 ret = sdio_al->pdata->config_mdm2ap_status(1);
2557 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002558 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME "Could not "
2559 "request GPIO\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002560 return ret;
2561 }
2562
2563 INIT_WORK(&sdio_al_dev->sdio_al_work.work, worker);
2564 /* disable all pipes interrupts before claim irq.
2565 since all are enabled by default. */
2566 for (i = 0 ; i < SDIO_AL_MAX_PIPES; i++) {
2567 enable_eot_interrupt(sdio_al_dev, i, false);
2568 enable_threshold_interrupt(sdio_al_dev, i, false);
2569 }
2570
2571 /* Disable all SDIO Functions before claim irq. */
2572 for (fn = 1 ; fn <= card->sdio_funcs; fn++)
2573 sdio_disable_func(card->sdio_func[fn-1]);
2574
2575 sdio_set_drvdata(func1, sdio_al_dev);
Krishna Kondaa7af6062011-09-01 18:34:38 -07002576 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":claim IRQ for card "
Maya Erez86cebda2011-10-11 11:13:40 +02002577 "%d\n", sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002578
2579 ret = sdio_claim_irq(func1, sdio_func_irq);
2580 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002581 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to claim"
2582 " IRQ for card %d\n",
Maya Erez86cebda2011-10-11 11:13:40 +02002583 sdio_al_dev->host->index);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002584 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002585 }
2586
2587 sdio_al_dev->is_ready = true;
2588
2589 /* Start worker before interrupt might happen */
2590 queue_work(sdio_al_dev->workqueue, &sdio_al_dev->sdio_al_work.work);
2591
2592 start_inactive_time(sdio_al_dev);
2593
2594 pr_debug(MODULE_NAME ":Ready.\n");
2595
2596 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002597}
2598
2599/**
2600 * Driver Tear-Down.
2601 *
2602 */
2603static void sdio_al_tear_down(void)
2604{
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002605 int i, j;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002606 struct sdio_al_device *sdio_al_dev = NULL;
2607 struct sdio_func *func1;
2608
2609 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
2610 if (sdio_al->devices[i] == NULL)
2611 continue;
2612 sdio_al_dev = sdio_al->devices[i];
2613
2614 if (sdio_al_dev->is_ready) {
2615 sdio_al_dev->is_ready = false; /* Flag worker to exit */
2616 sdio_al_dev->ask_mbox = false;
2617 ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
2618 /* allow gracefully exit of the worker thread */
2619 msleep(100);
2620
2621 flush_workqueue(sdio_al_dev->workqueue);
2622 destroy_workqueue(sdio_al_dev->workqueue);
2623
2624 sdio_al_vote_for_sleep(sdio_al_dev, 1);
2625
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002626 if (!sdio_al_claim_mutex_and_verify_dev(sdio_al_dev,
2627 __func__)) {
2628 if (!sdio_al_dev->card ||
2629 !sdio_al_dev->card->sdio_func[0]) {
2630 sdio_al_loge(sdio_al_dev->dev_log,
2631 MODULE_NAME
2632 ": %s: Invalid func1",
2633 __func__);
2634 return;
2635 }
2636 func1 = sdio_al_dev->card->sdio_func[0];
2637 sdio_release_irq(func1);
2638 sdio_disable_func(func1);
2639 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002640 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002641 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002642
2643 for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++)
2644 sdio_al_dev->channel[j].signature = 0x0;
2645 sdio_al_dev->signature = 0;
2646
2647 kfree(sdio_al_dev->sdioc_sw_header);
2648 kfree(sdio_al_dev->mailbox);
2649 kfree(sdio_al_dev->rx_flush_buf);
2650 kfree(sdio_al_dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002651 }
2652
2653 sdio_al->pdata->config_mdm2ap_status(0);
2654}
2655
2656/**
2657 * Find channel by name.
2658 *
2659 */
2660static struct sdio_channel *find_channel_by_name(const char *name)
2661{
2662 struct sdio_channel *ch = NULL;
2663 int i, j;
2664 struct sdio_al_device *sdio_al_dev = NULL;
2665
2666 for (j = 0; j < MAX_NUM_OF_SDIO_DEVICES; ++j) {
2667 if (sdio_al->devices[j] == NULL)
2668 continue;
2669 sdio_al_dev = sdio_al->devices[j];
2670 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002671 if (sdio_al_dev->channel[i].state ==
2672 SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002673 continue;
2674 if (strcmp(sdio_al_dev->channel[i].name, name) == 0) {
2675 ch = &sdio_al_dev->channel[i];
2676 break;
2677 }
2678 }
2679 if (ch != NULL)
2680 break;
2681 }
2682
2683 return ch;
2684}
2685
2686/**
2687 * Find the minimal poll time.
2688 *
2689 */
2690static int get_min_poll_time_msec(struct sdio_al_device *sdio_sl_dev)
2691{
2692 int i;
2693 int poll_delay_msec = 0x0FFFFFFF;
2694
2695 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++)
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002696 if ((sdio_sl_dev->channel[i].state ==
2697 SDIO_CHANNEL_STATE_OPEN) &&
2698 (sdio_sl_dev->channel[i].poll_delay_msec > 0) &&
2699 (sdio_sl_dev->channel[i].poll_delay_msec < poll_delay_msec))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002700 poll_delay_msec =
2701 sdio_sl_dev->channel[i].poll_delay_msec;
2702
2703 if (poll_delay_msec == 0x0FFFFFFF)
2704 poll_delay_msec = SDIO_AL_POLL_TIME_NO_STREAMING;
2705
2706 pr_debug(MODULE_NAME ":poll delay time is %d msec\n", poll_delay_msec);
2707
2708 return poll_delay_msec;
2709}
2710
2711/**
2712 * Open SDIO Channel.
2713 *
2714 * Enable the channel.
2715 * Set the channel context.
2716 * Trigger reading the mailbox to check available bytes.
2717 *
2718 */
2719int sdio_open(const char *name, struct sdio_channel **ret_ch, void *priv,
2720 void (*notify)(void *priv, unsigned ch_event))
2721{
2722 int ret = 0;
2723 struct sdio_channel *ch = NULL;
2724 struct sdio_al_device *sdio_al_dev = NULL;
2725
2726 *ret_ch = NULL; /* default */
2727
2728 ch = find_channel_by_name(name);
2729 if (ch == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002730 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":Can't find "
2731 "channel name %s\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002732 return -EINVAL;
2733 }
2734
2735 sdio_al_dev = ch->sdio_al_dev;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002736 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002737 return -ENODEV;
2738
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002739 if ((ch->state != SDIO_CHANNEL_STATE_IDLE) &&
2740 (ch->state != SDIO_CHANNEL_STATE_CLOSED)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002741 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Wrong ch %s "
2742 "state %d\n", name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002743 ret = -EPERM;
2744 goto exit_err;
2745 }
2746
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002747 if (sdio_al_dev->is_err) {
2748 SDIO_AL_ERR(__func__);
2749 ret = -ENODEV;
2750 goto exit_err;
2751 }
2752
Maya Erez7b1ebd22011-08-20 20:53:24 +03002753 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002754 if (ret)
2755 goto exit_err;
2756
2757 ch->notify = notify;
2758 ch->priv = priv;
2759
2760 /* Note: Set caller returned context before interrupts are enabled */
2761 *ret_ch = ch;
2762
2763 ret = open_channel(ch);
2764 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002765 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_open %s "
2766 "err=%d\n", name, -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002767 goto exit_err;
2768 }
2769
Maya Erez7ad06d82011-10-02 15:47:57 +02002770 CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":sdio_open %s "
2771 "completed OK\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002772 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
2773 if (sdio_al->sdioc_major == PEER_SDIOC_OLD_VERSION_MAJOR) {
2774 if (!ch->is_packet_mode) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002775 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME
2776 ":setting channel %s as "
2777 "lpm_chan\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002778 sdio_al_dev->lpm_chan = ch->num;
2779 }
2780 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002781 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": "
2782 "setting channel %s as lpm_chan\n",
2783 name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002784 sdio_al_dev->lpm_chan = ch->num;
2785 }
2786 }
2787
2788exit_err:
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002789 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002790 return ret;
2791}
2792EXPORT_SYMBOL(sdio_open);
2793
2794/**
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002795 * Request peer operation
2796 * note: sanity checks of parameters done by caller
2797 * called under bus locked
2798 */
2799static int peer_set_operation(u32 opcode,
2800 struct sdio_al_device *sdio_al_dev,
2801 struct sdio_channel *ch)
2802{
2803 int ret;
2804 int offset;
2805 struct sdio_func *wk_func;
2806 u32 peer_operation;
2807 int loop_count = 0;
2808
2809 wk_func = sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
2810 if (!wk_func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002811 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: NULL "
2812 "wakeup func:%d\n", __func__,
2813 SDIO_AL_WAKEUP_FUNC);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002814 ret = -ENODEV;
2815 goto exit;
2816 }
2817 /* calculate offset of peer_operation field in sw mailbox struct */
2818 offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config) +
2819 sizeof(struct peer_sdioc_channel_config) * ch->num +
2820 offsetof(struct peer_sdioc_channel_config, peer_operation);
2821
Maya Erez7b1ebd22011-08-20 20:53:24 +03002822 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002823 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002824 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
2825 "wake up\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002826 goto exit;
2827 }
2828 /* request operation from MDM peer */
2829 peer_operation = PEER_OPERATION(opcode, PEER_OP_STATE_INIT);
2830 ret = sdio_memcpy_toio(ch->func, SDIOC_SW_MAILBOX_ADDR+offset,
2831 &peer_operation, sizeof(u32));
2832 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002833 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
2834 "request close operation\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002835 goto exit;
2836 }
2837 ret = sdio_al_enable_func_retry(wk_func, "wk_func");
2838 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002839 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to enable"
2840 " Func#%d\n", wk_func->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002841 goto exit;
2842 }
2843 pr_debug(MODULE_NAME ":%s: wk_func enabled on ch %s\n",
2844 __func__, ch->name);
2845 /* send "start" operation to MDM */
2846 peer_operation = PEER_OPERATION(opcode, PEER_OP_STATE_START);
2847 ret = sdio_memcpy_toio(ch->func, SDIOC_SW_MAILBOX_ADDR+offset,
2848 &peer_operation, sizeof(u32));
2849 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002850 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
2851 "send start close operation\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002852 goto exit;
2853 }
2854 ret = sdio_disable_func(wk_func);
2855 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002856 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
2857 "disable Func#%d\n", wk_func->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002858 goto exit;
2859 }
2860 /* poll for peer operation ack */
2861 while (peer_operation != 0) {
2862 ret = sdio_memcpy_fromio(ch->func,
2863 &peer_operation,
2864 SDIOC_SW_MAILBOX_ADDR+offset,
2865 sizeof(u32));
2866 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002867 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2868 ":failed to request ack on close"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002869 " operation, loop_count = %d\n",
2870 loop_count);
2871 goto exit;
2872 }
2873 loop_count++;
2874 if (loop_count > 10) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002875 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2876 "peer_operation=0x%x wait loop"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002877 " %d on ch %s\n", __func__,
2878 peer_operation, loop_count, ch->name);
2879 }
2880 }
2881exit:
2882 return ret;
2883}
2884
Konstantin Dorfman52890522011-10-05 11:03:19 +02002885static int channel_close(struct sdio_channel *ch, int flush_flag)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002886{
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002887 int ret;
2888 struct sdio_al_device *sdio_al_dev = NULL;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002889 int flush_len;
2890 ulong flush_expires;
2891
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002892 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002893 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
2894 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002895 return -ENODEV;
2896 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002897
2898 if (!ch->func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002899 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: NULL func"
2900 " on channel:%d\n", __func__, ch->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002901 return -ENODEV;
2902 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002903
2904 sdio_al_dev = ch->sdio_al_dev;
2905 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
2906 return -ENODEV;
2907
2908 if (!sdio_al_dev->ch_close_supported) {
2909 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: Not "
2910 "supported by mdm, ch %s\n",
2911 __func__, ch->name);
2912 ret = -ENOTSUPP;
2913 goto error_exit;
2914 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002915
2916 if (sdio_al_dev->is_err) {
2917 SDIO_AL_ERR(__func__);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002918 ret = -ENODEV;
2919 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002920 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02002921 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
2922 sdio_al_loge(sdio_al_dev->dev_log,
2923 MODULE_NAME ":%s: ch %s is not in "
2924 "open state (%d)\n",
2925 __func__, ch->name, ch->state);
2926 ret = -ENODEV;
2927 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002928 }
2929 ch->state = SDIO_CHANNEL_STATE_CLOSING;
2930 ret = peer_set_operation(PEER_OP_CODE_CLOSE, sdio_al_dev, ch);
2931 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002932 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2933 "peer_set_operation() failed: %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002934 __func__, ret);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002935 ret = -ENODEV;
2936 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002937 }
2938 /* udate poll time for opened channels */
2939 if (ch->poll_delay_msec > 0) {
2940 sdio_al_dev->poll_delay_msec =
2941 get_min_poll_time_msec(sdio_al_dev);
2942 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002943 sdio_al_release_mutex(ch->sdio_al_dev, __func__);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002944
2945 flush_expires = jiffies +
2946 msecs_to_jiffies(SDIO_CLOSE_FLUSH_TIMEOUT_MSEC);
2947 /* flush rx packets of the channel */
Konstantin Dorfman52890522011-10-05 11:03:19 +02002948 if (flush_flag) {
2949 do {
2950 while (ch->read_avail > 0) {
2951 flush_len = ch->read_avail;
2952 ret = sdio_read_internal(ch,
2953 sdio_al_dev->rx_flush_buf,
2954 flush_len);
2955 if (ret) {
2956 sdio_al_loge(&sdio_al->gen_log,
2957 MODULE_NAME ":%s sdio_read"
2958 " failed: %d, ch %s\n",
2959 __func__, ret,
2960 ch->name);
2961 return ret;
2962 }
Yaniv Gardic4663632011-08-31 19:55:38 +03002963
Konstantin Dorfman52890522011-10-05 11:03:19 +02002964 if (time_after(jiffies, flush_expires) != 0) {
2965 sdio_al_loge(&sdio_al->gen_log,
2966 MODULE_NAME ":%s flush rx "
2967 "packets timeout: ch %s\n",
Krishna Kondaa7af6062011-09-01 18:34:38 -07002968 __func__, ch->name);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002969 sdio_al_get_into_err_state(sdio_al_dev);
2970 return -EBUSY;
2971 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002972 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02002973 msleep(100);
2974 if (ch->signature != SDIO_AL_SIGNATURE) {
2975 sdio_al_loge(&sdio_al->gen_log,
2976 MODULE_NAME ":%s: after sleep,"
2977 " invalid signature"
2978 " 0x%x\n", __func__,
2979 ch->signature);
2980 return -ENODEV;
2981 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002982 if (sdio_al_claim_mutex_and_verify_dev(ch->sdio_al_dev,
2983 __func__))
Konstantin Dorfman52890522011-10-05 11:03:19 +02002984 return -ENODEV;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002985
Konstantin Dorfman52890522011-10-05 11:03:19 +02002986 ret = read_mailbox(sdio_al_dev, false);
2987 if (ret) {
2988 sdio_al_loge(&sdio_al->gen_log,
2989 MODULE_NAME ":%s: failed to"
2990 " read mailbox", __func__);
2991 goto error_exit;
2992 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002993 sdio_al_release_mutex(ch->sdio_al_dev, __func__);
Konstantin Dorfman52890522011-10-05 11:03:19 +02002994 } while (ch->read_avail > 0);
2995 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02002996 if (sdio_al_claim_mutex_and_verify_dev(ch->sdio_al_dev,
2997 __func__))
2998 return -ENODEV;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002999 /* disable function to be able to open the channel again */
3000 ret = sdio_disable_func(ch->func);
3001 if (ret) {
Konstantin Dorfman52890522011-10-05 11:03:19 +02003002 sdio_al_loge(&sdio_al->gen_log,
3003 MODULE_NAME ":Fail to disable Func#%d\n",
3004 ch->func->num);
3005 goto error_exit;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003006 }
3007 ch->state = SDIO_CHANNEL_STATE_CLOSED;
Maya Erez7ad06d82011-10-02 15:47:57 +02003008 CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":%s: Ch %s closed "
3009 "successfully\n", __func__, ch->name);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003010
3011error_exit:
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003012 sdio_al_release_mutex(ch->sdio_al_dev, __func__);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003013
3014 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003015}
Konstantin Dorfman52890522011-10-05 11:03:19 +02003016
3017/**
3018 * Close SDIO Channel.
3019 *
3020 */
3021int sdio_close(struct sdio_channel *ch)
3022{
3023 return channel_close(ch, true);
3024}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003025EXPORT_SYMBOL(sdio_close);
3026
3027/**
3028 * Get the number of available bytes to write.
3029 *
3030 */
3031int sdio_write_avail(struct sdio_channel *ch)
3032{
3033 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003034 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3035 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003036 return -ENODEV;
3037 }
3038 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003039 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
3040 "Invalid signature 0x%x\n", __func__,
3041 ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003042 return -ENODEV;
3043 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003044 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003045 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
3046 "channel %s state is not open (%d)\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003047 __func__, ch->name, ch->state);
3048 return -ENODEV;
3049 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003050 pr_debug(MODULE_NAME ":sdio_write_avail %s 0x%x\n",
3051 ch->name, ch->write_avail);
3052
3053 return ch->write_avail;
3054}
3055EXPORT_SYMBOL(sdio_write_avail);
3056
3057/**
3058 * Get the number of available bytes to read.
3059 *
3060 */
3061int sdio_read_avail(struct sdio_channel *ch)
3062{
3063 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003064 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3065 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003066 return -ENODEV;
3067 }
3068 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003069 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
3070 "Invalid signature 0x%x\n", __func__,
3071 ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003072 return -ENODEV;
3073 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003074 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003075 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
3076 "channel %s state is not open (%d)\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003077 __func__, ch->name, ch->state);
3078 return -ENODEV;
3079 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003080 pr_debug(MODULE_NAME ":sdio_read_avail %s 0x%x\n",
3081 ch->name, ch->read_avail);
3082
3083 return ch->read_avail;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003084}
3085EXPORT_SYMBOL(sdio_read_avail);
3086
Maya Erez5795e0d2011-09-12 20:20:06 +03003087static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len)
3088{
3089 int ret = 0;
3090 struct sdio_al_device *sdio_al_dev = NULL;
3091
3092 if (!ch) {
Konstantin Dorfman52890522011-10-05 11:03:19 +02003093 sdio_al_loge(ch->sdio_al_dev->dev_log,
3094 MODULE_NAME ":%s: NULL channel\n", __func__);
Maya Erez5795e0d2011-09-12 20:20:06 +03003095 return -ENODEV;
3096 }
3097
3098 sdio_al_dev = ch->sdio_al_dev;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003099 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
3100 return -ENODEV;
Maya Erez5795e0d2011-09-12 20:20:06 +03003101
3102 ret = sdio_memcpy_fromio(ch->func, sdio_al_dev->rx_flush_buf,
3103 PIPE_RX_FIFO_ADDR, len);
3104
3105 if (ret) {
Konstantin Dorfman52890522011-10-05 11:03:19 +02003106 sdio_al_loge(ch->sdio_al_dev->dev_log,
3107 MODULE_NAME ":ch %s: %s err=%d, len=%d\n",
Maya Erez5795e0d2011-09-12 20:20:06 +03003108 ch->name, __func__, -ret, len);
3109 sdio_al_dev->is_err = true;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003110 sdio_al_release_mutex(sdio_al_dev, __func__);
Maya Erez5795e0d2011-09-12 20:20:06 +03003111 return ret;
3112 }
3113
3114 restart_inactive_time(sdio_al_dev);
3115
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003116 sdio_al_release_mutex(sdio_al_dev, __func__);
Maya Erez5795e0d2011-09-12 20:20:06 +03003117
3118 return 0;
3119}
3120
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003121/**
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003122 * Internal read from SDIO Channel.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003123 *
3124 * Reading from the pipe will trigger interrupt if there are
3125 * other pending packets on the SDIO-Client.
3126 *
3127 */
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003128static int sdio_read_internal(struct sdio_channel *ch, void *data, int len)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003129{
3130 int ret = 0;
3131 struct sdio_al_device *sdio_al_dev = NULL;
3132
3133 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003134 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3135 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003136 return -ENODEV;
3137 }
3138 if (!data) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003139 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
3140 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003141 return -ENODEV;
3142 }
3143 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003144 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
3145 " to read 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003146 return -EINVAL;
3147 }
3148
3149 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003150 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
3151 "signature 0x%x\n", __func__, ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003152 return -ENODEV;
3153 }
3154
3155 sdio_al_dev = ch->sdio_al_dev;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003156 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003157 return -ENODEV;
3158
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003159 if (sdio_al_dev->is_err) {
3160 SDIO_AL_ERR(__func__);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003161 ret = -ENODEV;
3162 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003163 }
3164
3165 /* lpm policy says we can't go to sleep when we have pending rx data,
3166 so either we had rx interrupt and woken up, or we never went to
3167 sleep */
3168 if (sdio_al_dev->is_ok_to_sleep) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003169 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: called "
3170 "when is_ok_to_sleep is set for ch %s, len=%d,"
3171 " last_any_read_avail=%d, last_read_avail=%d, "
3172 "last_old_read_avail=%d", __func__, ch->name,
3173 len, ch->statistics.last_any_read_avail,
3174 ch->statistics.last_read_avail,
3175 ch->statistics.last_old_read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003176 }
3177 BUG_ON(sdio_al_dev->is_ok_to_sleep);
3178
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003179 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
3180 (ch->state != SDIO_CHANNEL_STATE_CLOSING)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003181 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s wrong "
3182 "channel %s state %d\n",
3183 __func__, ch->name, ch->state);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003184 ret = -EINVAL;
3185 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003186 }
3187
Krishna Kondaa7af6062011-09-01 18:34:38 -07003188 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s read %d "
3189 "avail %d.\n", ch->name, len, ch->read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003190
3191 restart_inactive_time(sdio_al_dev);
3192
3193 if ((ch->is_packet_mode) && (len != ch->read_avail)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003194 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_read ch "
3195 "%s len != read_avail\n", ch->name);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003196 ret = -EINVAL;
3197 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003198 }
3199
3200 if (len > ch->read_avail) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003201 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
3202 "reading more bytes (%d) than the avail(%d).\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003203 ch->name, len, ch->read_avail);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003204 ret = -ENOMEM;
3205 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003206 }
3207
3208 ret = sdio_memcpy_fromio(ch->func, data, PIPE_RX_FIFO_ADDR, len);
3209
3210 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003211 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ch %s: "
3212 "sdio_read err=%d, len=%d, read_avail=%d, "
3213 "last_read_avail=%d, last_old_read_avail=%d\n",
Maya Erezd9cc2292011-08-04 09:20:31 +03003214 ch->name, -ret, len, ch->read_avail,
3215 ch->statistics.last_read_avail,
3216 ch->statistics.last_old_read_avail);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003217 sdio_al_get_into_err_state(sdio_al_dev);
3218 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003219 }
3220
3221 ch->statistics.total_read_times++;
3222
3223 /* Remove handled packet from the list regardless if ret is ok */
3224 if (ch->is_packet_mode)
3225 remove_handled_rx_packet(ch);
3226 else
3227 ch->read_avail -= len;
3228
3229 ch->total_rx_bytes += len;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003230 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s read %d "
3231 "avail %d total %d.\n", ch->name, len,
3232 ch->read_avail, ch->total_rx_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003233
3234 if ((ch->read_avail == 0) && !(ch->is_packet_mode))
3235 ask_reading_mailbox(sdio_al_dev);
3236
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003237exit:
3238 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003239
3240 return ret;
3241}
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003242
3243/**
3244 * Read from SDIO Channel.
3245 *
3246 * Reading from the pipe will trigger interrupt if there are
3247 * other pending packets on the SDIO-Client.
3248 *
3249 */
3250int sdio_read(struct sdio_channel *ch, void *data, int len)
3251{
3252 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003253 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3254 "channel\n", __func__);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003255 return -ENODEV;
3256 }
3257 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003258 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
3259 "Invalid signature 0x%x\n", __func__, ch->signature);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003260 return -ENODEV;
3261 }
3262 if (ch->state == SDIO_CHANNEL_STATE_OPEN) {
3263 return sdio_read_internal(ch, data, len);
3264 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003265 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME
3266 ":%s: Invalid channel %s state %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003267 __func__, ch->name, ch->state);
3268 }
3269 return -ENODEV;
3270}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003271EXPORT_SYMBOL(sdio_read);
3272
3273/**
3274 * Write to SDIO Channel.
3275 *
3276 */
3277int sdio_write(struct sdio_channel *ch, const void *data, int len)
3278{
3279 int ret = 0;
3280 struct sdio_al_device *sdio_al_dev = NULL;
3281
3282 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003283 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3284 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003285 return -ENODEV;
3286 }
3287 if (!data) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003288 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
3289 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003290 return -ENODEV;
3291 }
3292 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003293 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
3294 " to write 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003295 return -EINVAL;
3296 }
3297
3298 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003299 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
3300 "signature 0x%x\n", __func__, ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003301 return -ENODEV;
3302 }
3303
3304 sdio_al_dev = ch->sdio_al_dev;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003305 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003306 return -ENODEV;
3307
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003308 WARN_ON(len > ch->write_avail);
3309
3310 if (sdio_al_dev->is_err) {
3311 SDIO_AL_ERR(__func__);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003312 ret = -ENODEV;
3313 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003314 }
3315
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003316 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003317 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":writing to "
3318 "closed channel %s\n", ch->name);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003319 ret = -EINVAL;
3320 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003321 }
3322
3323 if (sdio_al_dev->is_ok_to_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03003324 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003325 if (ret)
3326 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003327 } else {
3328 restart_inactive_time(sdio_al_dev);
3329 }
3330
Krishna Kondaa7af6062011-09-01 18:34:38 -07003331 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s write %d "
3332 "avail %d.\n", ch->name, len, ch->write_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003333
3334 if (len > ch->write_avail) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003335 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
3336 "write more bytes (%d) than available %d.\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003337 ch->name, len, ch->write_avail);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003338 ret = -ENOMEM;
3339 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003340 }
3341
3342 ret = sdio_ch_write(ch, data, len);
3343 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003344 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_write "
3345 "on channel %s err=%d\n", ch->name, -ret);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003346 goto exit;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003347 }
3348
3349 ch->total_tx_bytes += len;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003350 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s write %d "
3351 "avail %d total %d.\n", ch->name, len,
3352 ch->write_avail, ch->total_tx_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003353
3354 /* Round up to whole buffer size */
3355 len = ROUND_UP(len, ch->peer_tx_buf_size);
3356 /* Protect from wraparound */
3357 len = min(len, (int) ch->write_avail);
3358 ch->write_avail -= len;
3359
3360 if (ch->write_avail < ch->min_write_avail)
3361 ask_reading_mailbox(sdio_al_dev);
3362
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003363exit:
3364 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003365
3366 return ret;
3367}
3368EXPORT_SYMBOL(sdio_write);
3369
3370static int __devinit msm_sdio_al_probe(struct platform_device *pdev)
3371{
3372 if (!sdio_al) {
3373 pr_err(MODULE_NAME ": %s: NULL sdio_al\n", __func__);
3374 return -ENODEV;
3375 }
3376
3377 sdio_al->pdata = pdev->dev.platform_data;
3378 return 0;
3379}
3380
3381static int __devexit msm_sdio_al_remove(struct platform_device *pdev)
3382{
3383 return 0;
3384}
3385
Konstantin Dorfman52890522011-10-05 11:03:19 +02003386static void sdio_al_close_all_channels(struct sdio_al_device *sdio_al_dev)
Maya Erez6862b142011-08-22 09:07:07 +03003387{
Konstantin Dorfman52890522011-10-05 11:03:19 +02003388 int j;
Maya Erez6862b142011-08-22 09:07:07 +03003389 int ret;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003390 struct sdio_channel *ch = NULL;
Maya Erez6862b142011-08-22 09:07:07 +03003391
Konstantin Dorfman52890522011-10-05 11:03:19 +02003392 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
Maya Erez6862b142011-08-22 09:07:07 +03003393
Konstantin Dorfman52890522011-10-05 11:03:19 +02003394 if (!sdio_al_dev) {
3395 sdio_al_loge(sdio_al_dev->dev_log,
3396 MODULE_NAME ": %s: NULL device", __func__);
3397 return;
3398 }
3399 for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++) {
3400 ch = &sdio_al_dev->channel[j];
3401
3402 if (ch->state == SDIO_CHANNEL_STATE_OPEN) {
3403 sdio_al_loge(sdio_al_dev->dev_log,
3404 MODULE_NAME ": %s: Call to sdio_close() for"
3405 " ch %s\n", __func__, ch->name);
3406 ret = channel_close(ch, false);
3407 if (ret) {
3408 sdio_al_loge(sdio_al_dev->dev_log,
3409 MODULE_NAME ": %s: failed sdio_close()"
3410 " for ch %s (%d)\n",
3411 __func__, ch->name, ret);
3412 }
3413 } else {
3414 pr_debug(MODULE_NAME ": %s: skip sdio_close() ch %s"
3415 " (state=%d)\n", __func__,
3416 ch->name, ch->state);
Maya Erez6862b142011-08-22 09:07:07 +03003417 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02003418 }
3419}
3420
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003421static void sdio_al_invalidate_sdio_clients(struct sdio_al_device *sdio_al_dev,
3422 struct platform_device **pdev_arr)
3423{
3424 int j;
3425
3426 pr_debug(MODULE_NAME ": %s: Notifying SDIO clients for card %d",
3427 __func__, sdio_al_dev->host->index);
3428 for (j = 0; j < SDIO_AL_MAX_CHANNELS; ++j) {
3429 if (sdio_al_dev->channel[j].state ==
3430 SDIO_CHANNEL_STATE_INVALID)
3431 continue;
3432 pdev_arr[j] = sdio_al_dev->channel[j].pdev;
3433 sdio_al_dev->channel[j].signature = 0x0;
3434 sdio_al_dev->channel[j].state =
3435 SDIO_CHANNEL_STATE_INVALID;
3436 }
3437}
3438
3439static void sdio_al_modem_reset_operations(struct sdio_al_device
Konstantin Dorfman52890522011-10-05 11:03:19 +02003440 *sdio_al_dev)
3441{
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003442 int ret = 0;
3443 struct sdio_func *func1 = NULL;
3444 struct platform_device *pdev_arr[SDIO_AL_MAX_CHANNELS];
3445 int j;
3446
Konstantin Dorfman52890522011-10-05 11:03:19 +02003447 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
3448
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003449 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Konstantin Dorfman52890522011-10-05 11:03:19 +02003450 return;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003451
3452 if (!sdio_al_dev->card || !sdio_al_dev->card->sdio_func[0]) {
3453 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: "
3454 "NULL func1 for card %d", __func__,
3455 sdio_al_dev->host->index);
3456 goto exit_err;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003457 }
Maya Erez6862b142011-08-22 09:07:07 +03003458
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003459 if (sdio_al_dev->state == CARD_REMOVED) {
3460 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: "
3461 "card %d is already removed", __func__,
3462 sdio_al_dev->host->index);
3463 goto exit_err;
3464 }
3465
3466 if (sdio_al_dev->state == MODEM_RESTART) {
3467 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: "
3468 "card %d was already notified for modem reset",
3469 __func__, sdio_al_dev->host->index);
3470 goto exit_err;
3471 }
3472
3473 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: Set the "
3474 "state to MODEM_RESTART for card %d",
3475 __func__, sdio_al_dev->host->index);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003476 sdio_al_dev->state = MODEM_RESTART;
3477 sdio_al_dev->is_ready = false;
Maya Erez6862b142011-08-22 09:07:07 +03003478
Konstantin Dorfman52890522011-10-05 11:03:19 +02003479 /* Stop mailbox timer */
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003480 stop_and_del_timer(sdio_al_dev);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003481
Konstantin Dorfman52890522011-10-05 11:03:19 +02003482 if ((sdio_al_dev->is_ok_to_sleep) &&
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003483 (!sdio_al_dev->is_err)) {
3484 pr_debug(MODULE_NAME ": %s: wakeup modem for "
3485 "card %d", __func__,
3486 sdio_al_dev->host->index);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003487 ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
Maya Erez6862b142011-08-22 09:07:07 +03003488 }
3489
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003490 if (!ret && (!sdio_al_dev->is_err)) {
3491 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME
3492 ": %s: sdio_release_irq for card %d",
3493 __func__,
3494 sdio_al_dev->host->index);
3495 func1 = sdio_al_dev->card->sdio_func[0];
3496 sdio_release_irq(sdio_al_dev->card->sdio_func[0]);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003497 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003498
3499 memset(pdev_arr, 0, sizeof(pdev_arr));
3500 sdio_al_invalidate_sdio_clients(sdio_al_dev, pdev_arr);
3501
3502 sdio_al_release_mutex(sdio_al_dev, __func__);
3503
3504 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Notifying SDIO "
3505 "clients for card %d",
3506 __func__, sdio_al_dev->host->index);
3507 for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++) {
3508 if (!pdev_arr[j])
3509 continue;
3510 platform_device_unregister(pdev_arr[j]);
3511 }
3512 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Finished Notifying "
3513 "SDIO clients for card %d",
3514 __func__, sdio_al_dev->host->index);
3515
3516 return;
3517
3518exit_err:
3519 sdio_al_release_mutex(sdio_al_dev, __func__);
3520 return;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003521}
3522
3523#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
3524static void sdio_al_reset(void)
3525{
3526 int i;
3527 struct sdio_al_device *sdio_al_dev;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003528
3529 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
3530
Maya Erez6862b142011-08-22 09:07:07 +03003531 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
Maya Erez6862b142011-08-22 09:07:07 +03003532 if (sdio_al->devices[i] == NULL) {
3533 pr_debug(MODULE_NAME ": %s: NULL device in index %d",
Konstantin Dorfman52890522011-10-05 11:03:19 +02003534 __func__, i);
Maya Erez6862b142011-08-22 09:07:07 +03003535 continue;
3536 }
3537 sdio_al_dev = sdio_al->devices[i];
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003538 sdio_al_modem_reset_operations(sdio_al->devices[i]);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003539 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003540
3541 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s completed", __func__);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003542}
3543#endif
Maya Erez6862b142011-08-22 09:07:07 +03003544
Konstantin Dorfman52890522011-10-05 11:03:19 +02003545static void msm_sdio_al_shutdown(struct platform_device *pdev)
3546{
3547 int i;
Konstantin Dorfman52890522011-10-05 11:03:19 +02003548 struct sdio_al_device *sdio_al_dev;
3549
3550 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME
3551 "Initiating msm_sdio_al_shutdown...");
3552
3553 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
3554 if (sdio_al->devices[i] == NULL) {
3555 pr_debug(MODULE_NAME ": %s: NULL device in index %d",
3556 __func__, i);
3557 continue;
Maya Erez8afd5642011-08-24 15:57:06 +03003558 }
Konstantin Dorfman52890522011-10-05 11:03:19 +02003559 sdio_al_dev = sdio_al->devices[i];
Maya Erez6862b142011-08-22 09:07:07 +03003560
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003561 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
3562 return;
Maya Erez6862b142011-08-22 09:07:07 +03003563
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003564 if (sdio_al_dev->ch_close_supported)
3565 sdio_al_close_all_channels(sdio_al_dev);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003566
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003567 sdio_al_release_mutex(sdio_al_dev, __func__);
Konstantin Dorfman52890522011-10-05 11:03:19 +02003568
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003569 sdio_al_modem_reset_operations(sdio_al_dev);
Maya Erez6862b142011-08-22 09:07:07 +03003570 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07003571 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: "
3572 "msm_sdio_al_shutdown complete.", __func__);
Maya Erez6862b142011-08-22 09:07:07 +03003573}
3574
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003575static struct platform_driver msm_sdio_al_driver = {
3576 .probe = msm_sdio_al_probe,
3577 .remove = __exit_p(msm_sdio_al_remove),
Maya Erez6862b142011-08-22 09:07:07 +03003578 .shutdown = msm_sdio_al_shutdown,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003579 .driver = {
3580 .name = "msm_sdio_al",
3581 },
3582};
3583
3584/**
3585 * Initialize SDIO_AL channels.
3586 *
3587 */
3588static int init_channels(struct sdio_al_device *sdio_al_dev)
3589{
3590 int ret = 0;
3591 int i;
3592
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003593 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003594 return -ENODEV;
3595
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003596 ret = read_sdioc_software_header(sdio_al_dev,
3597 sdio_al_dev->sdioc_sw_header);
3598 if (ret)
3599 goto exit;
3600
3601 ret = sdio_al_setup(sdio_al_dev);
3602 if (ret)
3603 goto exit;
3604
3605 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
3606 int ch_name_size;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003607 if (sdio_al_dev->channel[i].state == SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003608 continue;
3609 if (sdio_al->unittest_mode) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003610 memset(sdio_al_dev->channel[i].ch_test_name, 0,
3611 sizeof(sdio_al_dev->channel[i].ch_test_name));
3612 ch_name_size = strnlen(sdio_al_dev->channel[i].name,
3613 CHANNEL_NAME_SIZE);
3614 strncpy(sdio_al_dev->channel[i].ch_test_name,
3615 sdio_al_dev->channel[i].name,
3616 ch_name_size);
3617 strncat(sdio_al_dev->channel[i].ch_test_name +
3618 ch_name_size,
3619 SDIO_TEST_POSTFIX,
3620 SDIO_TEST_POSTFIX_SIZE);
3621 pr_debug(MODULE_NAME ":pdev.name = %s\n",
3622 sdio_al_dev->channel[i].ch_test_name);
3623 sdio_al_dev->channel[i].pdev = platform_device_alloc(
3624 sdio_al_dev->channel[i].ch_test_name, -1);
3625 } else {
3626 pr_debug(MODULE_NAME ":pdev.name = %s\n",
3627 sdio_al_dev->channel[i].name);
3628 sdio_al_dev->channel[i].pdev = platform_device_alloc(
3629 sdio_al_dev->channel[i].name, -1);
3630 }
3631 if (!sdio_al_dev->channel[i].pdev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003632 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3633 ":NULL platform device for ch %s",
3634 sdio_al_dev->channel[i].name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003635 sdio_al_dev->channel[i].state =
3636 SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003637 continue;
3638 }
3639 ret = platform_device_add(sdio_al_dev->channel[i].pdev);
3640 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003641 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3642 ":platform_device_add failed, "
3643 "ret=%d\n", ret);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003644 sdio_al_dev->channel[i].state =
3645 SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003646 }
3647 }
3648
3649exit:
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003650 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003651 return ret;
3652}
3653
3654/**
3655 * Initialize SDIO_AL channels according to the client setup.
3656 * This function also check if the client is in boot mode and
3657 * flashless boot is required to be activated or the client is
3658 * up and running.
3659 *
3660 */
3661static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev)
3662{
3663 int ret = 0;
3664 struct sdio_func *func1;
3665 int signature = 0;
3666
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003667 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003668 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003669
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003670 if (!sdio_al_dev->card || !sdio_al_dev->card->sdio_func[0]) {
3671 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":NULL card or "
3672 "func1\n");
3673 sdio_al_release_mutex(sdio_al_dev, __func__);
3674 return -ENODEV;
3675 }
3676 func1 = sdio_al_dev->card->sdio_func[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003677
3678 /* Read the header signature to determine the status of the MDM
3679 * SDIO Client
3680 */
3681 signature = sdio_readl(func1, SDIOC_SW_HEADER_ADDR, &ret);
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003682 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003683 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003684 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
3685 "signature from sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003686 return ret;
3687 }
3688
3689 switch (signature) {
3690 case PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE:
3691 if (sdio_al_dev == sdio_al->bootloader_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003692 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":setup "
3693 "bootloader on card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003694 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003695 return sdio_al_bootloader_setup();
3696 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003697 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":wait "
3698 "for bootloader completion "
3699 "on card %d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003700 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003701 return sdio_al_wait_for_bootloader_comp(sdio_al_dev);
3702 }
3703 case PEER_SDIOC_SW_MAILBOX_SIGNATURE:
3704 case PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE:
3705 return init_channels(sdio_al_dev);
3706 default:
Krishna Kondaa7af6062011-09-01 18:34:38 -07003707 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
3708 "signature 0x%x\n", signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003709 return -EINVAL;
3710 }
3711
3712 return 0;
3713}
3714
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003715static void clean_sdio_al_device_data(struct sdio_al_device *sdio_al_dev)
3716{
3717 sdio_al_dev->is_ready = 0;
3718 sdio_al_dev->bootloader_done = 0;
3719 sdio_al_dev->lpm_chan = 0;
3720 sdio_al_dev->is_ok_to_sleep = 0;
3721 sdio_al_dev->inactivity_time = 0;
3722 sdio_al_dev->poll_delay_msec = 0;
3723 sdio_al_dev->is_timer_initialized = 0;
3724 sdio_al_dev->is_err = 0;
3725 sdio_al_dev->is_suspended = 0;
3726 sdio_al_dev->flashless_boot_on = 0;
3727 sdio_al_dev->ch_close_supported = 0;
3728 sdio_al_dev->print_after_interrupt = 0;
3729 memset(sdio_al_dev->sdioc_sw_header, 0,
3730 sizeof(*sdio_al_dev->sdioc_sw_header));
3731 memset(sdio_al_dev->mailbox, 0, sizeof(*sdio_al_dev->mailbox));
3732 memset(sdio_al_dev->rx_flush_buf, 0,
3733 sizeof(*sdio_al_dev->rx_flush_buf));
3734}
3735
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003736/*
3737 * SDIO driver functions
3738 */
3739static int sdio_al_sdio_probe(struct sdio_func *func,
3740 const struct sdio_device_id *sdio_dev_id)
3741{
3742 int ret = 0;
3743 struct sdio_al_device *sdio_al_dev = NULL;
3744 int i;
3745 struct mmc_card *card = NULL;
3746
3747 if (!func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003748 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
3749 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003750 return -ENODEV;
3751 }
3752 card = func->card;
3753
3754 if (!card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003755 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
3756 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003757 return -ENODEV;
3758 }
3759
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003760 if (!card->sdio_func[0]) {
3761 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
3762 "func1\n",
3763 __func__);
3764 return -ENODEV;
3765 }
3766
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003767 if (card->sdio_funcs < SDIO_AL_MAX_FUNCS) {
3768 dev_info(&card->dev,
3769 "SDIO-functions# %d less than expected.\n",
3770 card->sdio_funcs);
3771 return -ENODEV;
3772 }
3773
3774 /* Check if there is already a device for this card */
3775 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
3776 if (sdio_al->devices[i] == NULL)
3777 continue;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003778 if (sdio_al->devices[i]->host == card->host) {
3779 sdio_al_dev = sdio_al->devices[i];
3780 if (sdio_al_dev->state == CARD_INSERTED)
3781 return 0;
3782 clean_sdio_al_device_data(sdio_al_dev);
3783 break;
3784 }
3785 }
3786
3787 if (!sdio_al_dev) {
3788 sdio_al_dev = kzalloc(sizeof(struct sdio_al_device),
3789 GFP_KERNEL);
3790 if (sdio_al_dev == NULL)
3791 return -ENOMEM;
3792
3793 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
3794 if (sdio_al->devices[i] == NULL) {
3795 sdio_al->devices[i] = sdio_al_dev;
3796 sdio_al_dev->dev_log = &sdio_al->device_log[i];
3797 spin_lock_init(&sdio_al_dev->dev_log->log_lock);
3798 #ifdef CONFIG_DEBUG_FS
3799 sdio_al_dbgfs_log[i].data =
3800 sdio_al_dev->dev_log->buffer;
3801 sdio_al_dbgfs_log[i].size =
3802 SDIO_AL_DEBUG_LOG_SIZE;
3803 #endif
3804 break;
3805 }
3806 if (i == MAX_NUM_OF_SDIO_DEVICES) {
3807 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":No space "
3808 "in devices array for the device\n");
3809 return -ENOMEM;
3810 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003811 }
3812
3813 dev_info(&card->dev, "SDIO Card claimed.\n");
Maya Erezc7f63282011-10-11 12:15:23 +02003814 sdio_al->skip_print_info = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003815
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003816 sdio_al_dev->state = CARD_INSERTED;
3817
3818 if (card->host->index == SDIO_BOOTLOADER_CARD_INDEX)
3819 sdio_al->bootloader_dev = sdio_al_dev;
3820
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003821 sdio_al_dev->is_ready = false;
3822
3823 sdio_al_dev->signature = SDIO_AL_SIGNATURE;
3824
3825 sdio_al_dev->is_suspended = 0;
3826 sdio_al_dev->is_timer_initialized = false;
3827
3828 sdio_al_dev->lpm_chan = INVALID_SDIO_CHAN;
3829
3830 sdio_al_dev->card = card;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003831 sdio_al_dev->host = card->host;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003832
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003833 if (!sdio_al_dev->mailbox) {
3834 sdio_al_dev->mailbox = kzalloc(sizeof(struct sdio_mailbox),
3835 GFP_KERNEL);
3836 if (sdio_al_dev->mailbox == NULL)
3837 return -ENOMEM;
3838 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003839
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003840 if (!sdio_al_dev->sdioc_sw_header) {
3841 sdio_al_dev->sdioc_sw_header
3842 = kzalloc(sizeof(*sdio_al_dev->sdioc_sw_header),
3843 GFP_KERNEL);
3844 if (sdio_al_dev->sdioc_sw_header == NULL)
3845 return -ENOMEM;
3846 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003847
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003848 if (!sdio_al_dev->rx_flush_buf) {
3849 sdio_al_dev->rx_flush_buf = kzalloc(RX_FLUSH_BUFFER_SIZE,
3850 GFP_KERNEL);
3851 if (sdio_al_dev->rx_flush_buf == NULL) {
3852 sdio_al_loge(&sdio_al->gen_log,
3853 MODULE_NAME ":Fail to allocate "
3854 "rx_flush_buf for card %d\n",
3855 card->host->index);
3856 return -ENOMEM;
3857 }
Maya Erez5795e0d2011-09-12 20:20:06 +03003858 }
3859
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003860 sdio_al_dev->timer.data = (unsigned long)sdio_al_dev;
3861
3862 wake_lock_init(&sdio_al_dev->wake_lock, WAKE_LOCK_SUSPEND, MODULE_NAME);
3863 /* Don't allow sleep until all required clients register */
3864 sdio_al_vote_for_sleep(sdio_al_dev, 0);
3865
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003866 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
3867 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003868
3869 /* Init Func#1 */
Yaniv Gardi9a952d92011-09-06 13:46:30 +03003870 ret = sdio_al_enable_func_retry(card->sdio_func[0], "Init Func#1");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003871 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003872 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
3873 "enable Func#%d\n", card->sdio_func[0]->num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003874 goto exit;
3875 }
3876
3877 /* Patch Func CIS tuple issue */
3878 ret = sdio_set_block_size(card->sdio_func[0], SDIO_AL_BLOCK_SIZE);
3879 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003880 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to set "
3881 "block size, Func#%d\n", card->sdio_func[0]->num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003882 goto exit;
3883 }
3884 sdio_al_dev->card->sdio_func[0]->max_blksize = SDIO_AL_BLOCK_SIZE;
3885
3886 sdio_al_dev->workqueue = create_singlethread_workqueue("sdio_al_wq");
3887 sdio_al_dev->sdio_al_work.sdio_al_dev = sdio_al_dev;
3888 init_waitqueue_head(&sdio_al_dev->wait_mbox);
3889
3890 ret = sdio_al_client_setup(sdio_al_dev);
3891
3892exit:
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003893 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003894 return ret;
3895}
3896
3897static void sdio_al_sdio_remove(struct sdio_func *func)
3898{
3899 struct sdio_al_device *sdio_al_dev = NULL;
3900 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003901 struct mmc_card *card = NULL;
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003902 struct platform_device *pdev_arr[SDIO_AL_MAX_CHANNELS];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003903
3904 if (!func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003905 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
3906 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003907 return;
3908 }
3909 card = func->card;
3910
3911 if (!card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003912 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
3913 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003914 return;
3915 }
3916
3917 /* Find the sdio_al_device of this card */
3918 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
3919 if (sdio_al->devices[i] == NULL)
3920 continue;
3921 if (sdio_al->devices[i]->card == card) {
3922 sdio_al_dev = sdio_al->devices[i];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003923 break;
3924 }
3925 }
3926 if (sdio_al_dev == NULL) {
3927 pr_debug(MODULE_NAME ":%s :NULL sdio_al_dev for card %d\n",
3928 __func__, card->host->index);
3929 return;
3930 }
3931
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003932 if (sdio_al_claim_mutex(sdio_al_dev, __func__))
3933 return;
3934
3935 if (sdio_al_dev->state == CARD_REMOVED) {
3936 sdio_al_release_mutex(sdio_al_dev, __func__);
3937 return;
3938 }
3939
3940 if (!card->sdio_func[0]) {
3941 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
3942 "func1\n", __func__);
3943 sdio_al_release_mutex(sdio_al_dev, __func__);
3944 return;
3945 }
3946
Krishna Kondaa7af6062011-09-01 18:34:38 -07003947 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s for card %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003948 __func__, card->host->index);
3949
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003950 sdio_al_dev->state = CARD_REMOVED;
3951
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003952 memset(pdev_arr, 0, sizeof(pdev_arr));
3953 sdio_al_invalidate_sdio_clients(sdio_al_dev, pdev_arr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003954
Krishna Kondaa7af6062011-09-01 18:34:38 -07003955 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: ask_reading_mailbox "
3956 "for card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003957 sdio_al_dev->is_ready = false; /* Flag worker to exit */
3958 sdio_al_dev->ask_mbox = false;
3959 ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
3960
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003961 stop_and_del_timer(sdio_al_dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003962
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003963 sdio_al_release_mutex(sdio_al_dev, __func__);
3964
3965 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Notifying SDIO "
3966 "clients for card %d",
3967 __func__, sdio_al_dev->host->index);
3968 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
3969 if (!pdev_arr[i])
3970 continue;
3971 platform_device_unregister(pdev_arr[i]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003972 }
Maya Erez0fdb5ad2011-10-09 19:16:27 +02003973 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Finished Notifying "
3974 "SDIO clients for card %d",
3975 __func__, sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003976
Krishna Kondaa7af6062011-09-01 18:34:38 -07003977 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: vote for sleep for "
3978 "card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003979 sdio_al_vote_for_sleep(sdio_al_dev, 1);
3980
Krishna Kondaa7af6062011-09-01 18:34:38 -07003981 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: flush_workqueue for "
3982 "card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003983 flush_workqueue(sdio_al_dev->workqueue);
3984 destroy_workqueue(sdio_al_dev->workqueue);
3985 wake_lock_destroy(&sdio_al_dev->wake_lock);
3986
Krishna Kondaa7af6062011-09-01 18:34:38 -07003987 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: sdio card %d removed."
3988 "\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003989}
3990
3991static void sdio_print_mailbox(char *prefix_str, struct sdio_mailbox *mailbox)
3992{
3993 int k = 0;
3994 char buf[256];
3995 char buf1[10];
3996
3997 if (!mailbox) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003998 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": mailbox is "
3999 "NULL\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004000 return;
4001 }
4002
Krishna Kondaa7af6062011-09-01 18:34:38 -07004003 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: pipes 0_7: eot=0x%x,"
4004 " thresh=0x%x, overflow=0x%x, "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004005 "underflow=0x%x, mask_thresh=0x%x\n",
4006 prefix_str, mailbox->eot_pipe_0_7,
4007 mailbox->thresh_above_limit_pipe_0_7,
4008 mailbox->overflow_pipe_0_7,
4009 mailbox->underflow_pipe_0_7,
4010 mailbox->mask_thresh_above_limit_pipe_0_7);
4011
4012 memset(buf, 0, sizeof(buf));
4013 strncat(buf, ": bytes_avail:", sizeof(buf));
4014
4015 for (k = 0 ; k < SDIO_AL_ACTIVE_PIPES ; ++k) {
4016 snprintf(buf1, sizeof(buf1), "%d, ",
4017 mailbox->pipe_bytes_avail[k]);
4018 strncat(buf, buf1, sizeof(buf));
4019 }
4020
Krishna Kondaa7af6062011-09-01 18:34:38 -07004021 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME "%s", buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004022}
4023
4024static void sdio_al_print_info(void)
4025{
4026 int i = 0;
4027 int j = 0;
4028 int ret = 0;
4029 struct sdio_mailbox *mailbox = NULL;
4030 struct sdio_mailbox *hw_mailbox = NULL;
4031 struct peer_sdioc_channel_config *ch_config = NULL;
4032 struct sdio_func *func1 = NULL;
4033 struct sdio_func *lpm_func = NULL;
4034 int offset = 0;
4035 int is_ok_to_sleep = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004036 char buf[50];
4037
Maya Erezc7f63282011-10-11 12:15:23 +02004038 if (sdio_al->skip_print_info == 1)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004039 return;
4040
Maya Erezc7f63282011-10-11 12:15:23 +02004041 sdio_al->skip_print_info = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004042
Krishna Kondaa7af6062011-09-01 18:34:38 -07004043 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - SDIO DEBUG INFO\n",
4044 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004045
4046 if (!sdio_al) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004047 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - ERROR - "
4048 "sdio_al is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004049 return;
4050 }
4051
Krishna Kondaa7af6062011-09-01 18:34:38 -07004052 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": GPIO mdm2ap_status=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004053 sdio_al->pdata->get_mdm2ap_status());
4054
4055 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
4056 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
4057
4058 if (sdio_al_dev == NULL) {
4059 continue;
4060 }
4061
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004062 if (!sdio_al_dev->host) {
4063 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Host"
4064 " is NULL\n);");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004065 continue;
4066 }
4067
4068 snprintf(buf, sizeof(buf), "Card#%d: Shadow HW MB",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004069 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004070
4071 /* printing Shadowing HW Mailbox*/
4072 mailbox = sdio_al_dev->mailbox;
4073 sdio_print_mailbox(buf, mailbox);
4074
Krishna Kondaa7af6062011-09-01 18:34:38 -07004075 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004076 "is_ok_to_sleep=%d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004077 sdio_al_dev->host->index,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004078 sdio_al_dev->is_ok_to_sleep);
4079
4080
Krishna Kondaa7af6062011-09-01 18:34:38 -07004081 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004082 "Shadow channels SW MB:",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004083 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004084
4085 /* printing Shadowing SW Mailbox per channel*/
4086 for (i = 0 ; i < SDIO_AL_MAX_CHANNELS ; ++i) {
4087 struct sdio_channel *ch = &sdio_al_dev->channel[i];
4088
4089 if (ch == NULL) {
4090 continue;
4091 }
4092
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03004093 if (ch->state == SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004094 continue;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004095
4096 ch_config = &sdio_al_dev->channel[i].ch_config;
4097
Krishna Kondaa7af6062011-09-01 18:34:38 -07004098 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4099 ": Ch %s: max_rx_thres=0x%x, "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004100 "max_tx_thres=0x%x, tx_buf=0x%x, "
4101 "is_packet_mode=%d, "
4102 "max_packet=0x%x, min_write=0x%x",
4103 ch->name, ch_config->max_rx_threshold,
4104 ch_config->max_tx_threshold,
4105 ch_config->tx_buf_size,
4106 ch_config->is_packet_mode,
4107 ch_config->max_packet_size,
4108 ch->min_write_avail);
4109
Krishna Kondaa7af6062011-09-01 18:34:38 -07004110 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4111 ": total_rx=0x%x, total_tx=0x%x, "
4112 "read_avail=0x%x, write_avail=0x%x, "
4113 "rx_pending=0x%x, num_reads=0x%x, "
4114 "num_notifs=0x%x", ch->total_rx_bytes,
4115 ch->total_tx_bytes, ch->read_avail,
4116 ch->write_avail, ch->rx_pending_bytes,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004117 ch->statistics.total_read_times,
4118 ch->statistics.total_notifs);
4119 } /* end loop over all channels */
4120
4121 } /* end loop over all devices */
4122
4123 /* reading from client and printing is_host_ok_to_sleep per device */
4124 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
4125 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
4126
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004127 if (sdio_al_verify_func1(sdio_al_dev, __func__))
4128 continue;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004129
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004130 if (!sdio_al_dev->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004131 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4132 ": Host is NULL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004133 continue;
4134 }
4135
4136 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004137 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4138 ": %s - for Card#%d, is lpm_chan=="
4139 "INVALID_SDIO_CHAN. continuing...",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004140 __func__, sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004141 continue;
4142 }
4143
4144 offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
4145 sizeof(struct peer_sdioc_channel_config) *
4146 sdio_al_dev->lpm_chan+
4147 offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
4148
4149 lpm_func = sdio_al_dev->card->sdio_func[sdio_al_dev->
4150 lpm_chan+1];
4151 if (!lpm_func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004152 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4153 ": %s - lpm_func is NULL for card#%d"
4154 " continuing...\n", __func__,
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004155 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004156 continue;
4157 }
4158
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004159 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
4160 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004161 ret = sdio_memcpy_fromio(lpm_func,
4162 &is_ok_to_sleep,
4163 SDIOC_SW_MAILBOX_ADDR+offset,
4164 sizeof(int));
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004165 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004166
4167 if (ret)
Krishna Kondaa7af6062011-09-01 18:34:38 -07004168 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4169 ": %s - fail to read "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004170 "is_HOST_ok_to_sleep from mailbox for card %d",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004171 __func__, sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004172 else
Krishna Kondaa7af6062011-09-01 18:34:38 -07004173 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4174 ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004175 "is_HOST_ok_to_sleep=%d\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004176 sdio_al_dev->host->index,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004177 is_ok_to_sleep);
4178 }
4179
4180 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
4181 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
4182
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004183 if (!sdio_al_dev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004184 continue;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004185
4186 /* Reading HW Mailbox */
4187 hw_mailbox = sdio_al_dev->mailbox;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004188
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004189 if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
4190 return;
4191
4192 if (!sdio_al_dev->card || !sdio_al_dev->card->sdio_func[0]) {
4193 sdio_al_release_mutex(sdio_al_dev, __func__);
4194 return;
4195 }
4196 func1 = sdio_al_dev->card->sdio_func[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004197 ret = sdio_memcpy_fromio(func1, hw_mailbox,
4198 HW_MAILBOX_ADDR, sizeof(*hw_mailbox));
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004199 sdio_al_release_mutex(sdio_al_dev, __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004200
4201 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004202 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
4203 ": fail to read "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004204 "mailbox for card#%d. "
4205 "continuing...\n",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004206 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004207 continue;
4208 }
4209
4210 snprintf(buf, sizeof(buf), "Card#%d: Current HW MB",
Maya Erez0fdb5ad2011-10-09 19:16:27 +02004211 sdio_al_dev->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004212
4213 /* Printing HW Mailbox */
4214 sdio_print_mailbox(buf, hw_mailbox);
4215 }
4216}
4217
4218static struct sdio_device_id sdio_al_sdioid[] = {
4219 {.class = 0, .vendor = 0x70, .device = 0x2460},
4220 {.class = 0, .vendor = 0x70, .device = 0x0460},
4221 {.class = 0, .vendor = 0x70, .device = 0x23F1},
4222 {.class = 0, .vendor = 0x70, .device = 0x23F0},
4223 {}
4224};
4225
4226static struct sdio_driver sdio_al_sdiofn_driver = {
4227 .name = "sdio_al_sdiofn",
4228 .id_table = sdio_al_sdioid,
4229 .probe = sdio_al_sdio_probe,
4230 .remove = sdio_al_sdio_remove,
4231};
4232
4233#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4234/*
4235 * Callback for notifications from restart mudule.
4236 * This function handles only the BEFORE_RESTART notification.
4237 * Stop all the activity on the card and notify our clients.
4238 */
4239static int sdio_al_subsys_notifier_cb(struct notifier_block *this,
4240 unsigned long notif_type,
4241 void *data)
4242{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004243 if (notif_type != SUBSYS_BEFORE_SHUTDOWN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004244 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: got "
4245 "notification %ld", __func__, notif_type);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004246 return NOTIFY_DONE;
4247 }
4248
Konstantin Dorfman52890522011-10-05 11:03:19 +02004249 sdio_al_reset();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004250 return NOTIFY_OK;
4251}
4252
4253static struct notifier_block sdio_al_nb = {
4254 .notifier_call = sdio_al_subsys_notifier_cb,
4255};
4256#endif
4257
4258/**
4259 * Module Init.
4260 *
4261 * @warn: allocate sdio_al context before registering driver.
4262 *
4263 */
4264static int __init sdio_al_init(void)
4265{
4266 int ret = 0;
4267 int i;
4268
4269 pr_debug(MODULE_NAME ":sdio_al_init\n");
4270
4271 pr_info(MODULE_NAME ":SDIO-AL SW version %s\n",
4272 DRV_VERSION);
4273
4274 sdio_al = kzalloc(sizeof(struct sdio_al), GFP_KERNEL);
4275 if (sdio_al == NULL)
4276 return -ENOMEM;
4277
4278 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
4279 sdio_al->devices[i] = NULL;
4280
4281 sdio_al->unittest_mode = false;
4282
4283 sdio_al->debug.debug_lpm_on = debug_lpm_on;
4284 sdio_al->debug.debug_data_on = debug_data_on;
Maya Erez7ad06d82011-10-02 15:47:57 +02004285 sdio_al->debug.debug_close_on = debug_close_on;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004286
4287#ifdef CONFIG_DEBUG_FS
4288 sdio_al_debugfs_init();
4289#endif
4290
4291
4292#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4293 sdio_al->subsys_notif_handle = subsys_notif_register_notifier(
4294 "external_modem", &sdio_al_nb);
4295#endif
4296
4297 ret = platform_driver_register(&msm_sdio_al_driver);
4298 if (ret) {
4299 pr_err(MODULE_NAME ": platform_driver_register failed: %d\n",
4300 ret);
4301 goto exit;
4302 }
4303
4304 sdio_register_driver(&sdio_al_sdiofn_driver);
Krishna Kondaa7af6062011-09-01 18:34:38 -07004305
4306 spin_lock_init(&sdio_al->gen_log.log_lock);
4307
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004308exit:
4309 if (ret)
4310 kfree(sdio_al);
4311 return ret;
4312}
4313
4314/**
4315 * Module Exit.
4316 *
4317 * Free allocated memory.
4318 * Disable SDIO-Card.
4319 * Unregister driver.
4320 *
4321 */
4322static void __exit sdio_al_exit(void)
4323{
4324 if (sdio_al == NULL)
4325 return;
4326
4327 pr_debug(MODULE_NAME ":sdio_al_exit\n");
4328
4329#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4330 subsys_notif_unregister_notifier(
4331 sdio_al->subsys_notif_handle, &sdio_al_nb);
4332#endif
4333
4334 sdio_al_tear_down();
4335
4336 sdio_unregister_driver(&sdio_al_sdiofn_driver);
4337
4338 kfree(sdio_al);
4339
4340#ifdef CONFIG_DEBUG_FS
4341 sdio_al_debugfs_cleanup();
4342#endif
4343
4344 platform_driver_unregister(&msm_sdio_al_driver);
4345
4346 pr_debug(MODULE_NAME ":sdio_al_exit complete\n");
4347}
4348
4349module_init(sdio_al_init);
4350module_exit(sdio_al_exit);
4351
4352MODULE_LICENSE("GPL v2");
4353MODULE_DESCRIPTION("SDIO Abstraction Layer");
4354MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
4355MODULE_VERSION(DRV_VERSION);
4356