blob: 2213f9f9e3dc878071352ad2e93c224b6fa350a6 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13/*
14 * SDIO-Abstraction-Layer Module.
15 *
16 * To be used with Qualcomm's SDIO-Client connected to this host.
17 */
18#include <sdio_al_private.h>
19
20#include <linux/module.h>
21#include <linux/scatterlist.h>
22#include <linux/workqueue.h>
23#include <linux/wait.h>
24#include <linux/delay.h>
25#include <linux/fs.h>
26#include <linux/slab.h>
27#include <linux/wakelock.h>
28#include <linux/mmc/core.h>
29#include <linux/mmc/card.h>
30#include <linux/mmc/host.h>
31#include <linux/mmc/mmc.h>
32#include <linux/mmc/sdio.h>
33#include <linux/mmc/sdio_func.h>
34#include <linux/mmc/sdio_ids.h>
35#include <linux/gpio.h>
36#include <linux/dma-mapping.h>
37#include <linux/earlysuspend.h>
38#include <linux/debugfs.h>
39#include <linux/uaccess.h>
40#include <linux/syscalls.h>
Krishna Kondaa7af6062011-09-01 18:34:38 -070041#include <linux/time.h>
42#include <linux/spinlock.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043
44#include <mach/dma.h>
45#include <mach/gpio.h>
46#include <mach/subsystem_notif.h>
47
48#include "../../../drivers/mmc/host/msm_sdcc.h"
49
50/**
51 * Func#0 has SDIO standard registers
52 * Func#1 is for Mailbox.
53 * Functions 2..7 are for channels.
54 * Currently only functions 2..5 are active due to SDIO-Client
55 * number of pipes.
56 *
57 */
58#define SDIO_AL_MAX_CHANNELS 6
59
60/** Func 1..5 */
61#define SDIO_AL_MAX_FUNCS (SDIO_AL_MAX_CHANNELS+1)
62#define SDIO_AL_WAKEUP_FUNC 6
63
64/** Number of SDIO-Client pipes */
65#define SDIO_AL_MAX_PIPES 16
66#define SDIO_AL_ACTIVE_PIPES 8
67
68/** CMD53/CMD54 Block size */
Yaniv Gardie5370b82011-07-27 11:46:51 +030069#define SDIO_AL_BLOCK_SIZE 256
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070070
71/** Func#1 hardware Mailbox base address */
72#define HW_MAILBOX_ADDR 0x1000
73
74/** Func#1 peer sdioc software version.
75 * The header is duplicated also to the mailbox of the other
76 * functions. It can be used before other functions are enabled. */
77#define SDIOC_SW_HEADER_ADDR 0x0400
78
79/** Func#2..7 software Mailbox base address at 16K */
80#define SDIOC_SW_MAILBOX_ADDR 0x4000
81
82/** Some Mailbox registers address, written by host for
83 control */
84#define PIPES_THRESHOLD_ADDR 0x01000
85
86#define PIPES_0_7_IRQ_MASK_ADDR 0x01048
87
88#define PIPES_8_15_IRQ_MASK_ADDR 0x0104C
89
90#define FUNC_1_4_MASK_IRQ_ADDR 0x01040
91#define FUNC_5_7_MASK_IRQ_ADDR 0x01044
92#define FUNC_1_4_USER_IRQ_ADDR 0x01050
93#define FUNC_5_7_USER_IRQ_ADDR 0x01054
94
95#define EOT_PIPES_ENABLE 0x00
96
97/** Maximum read/write data available is SDIO-Client limitation */
98#define MAX_DATA_AVAILABLE (16*1024)
99#define INVALID_DATA_AVAILABLE (0x8000)
100
101/** SDIO-Client HW threshold to generate interrupt to the
102 * SDIO-Host on write available bytes.
103 */
104#define DEFAULT_WRITE_THRESHOLD (1024)
105
106/** SDIO-Client HW threshold to generate interrupt to the
107 * SDIO-Host on read available bytes, for streaming (non
108 * packet) rx data.
109 */
110#define DEFAULT_READ_THRESHOLD (1024)
111
Maya Erez8ed0a9a2011-07-19 14:46:53 +0300112/* Extra bytes to ensure getting the rx threshold interrupt on stream channels
113 when restoring the threshold after sleep */
114#define THRESHOLD_CHANGE_EXTRA_BYTES (100)
115
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700116/** SW threshold to trigger reading the mailbox. */
117#define DEFAULT_MIN_WRITE_THRESHOLD (1024)
118#define DEFAULT_MIN_WRITE_THRESHOLD_STREAMING (1600)
119
120#define THRESHOLD_DISABLE_VAL (0xFFFFFFFF)
121
122
123/** Mailbox polling time for packet channels */
124#define DEFAULT_POLL_DELAY_MSEC 10
125/** Mailbox polling time for streaming channels */
126#define DEFAULT_POLL_DELAY_NOPACKET_MSEC 30
127
128/** The SDIO-Client prepares N buffers of size X per Tx pipe.
129 * Even when the transfer fills a partial buffer,
130 * that buffer becomes unusable for the next transfer. */
131#define DEFAULT_PEER_TX_BUF_SIZE (128)
132
133#define ROUND_UP(x, n) (((x + n - 1) / n) * n)
134
135/** Func#2..7 FIFOs are r/w via
136 sdio_readsb() & sdio_writesb(),when inc_addr=0 */
137#define PIPE_RX_FIFO_ADDR 0x00
138#define PIPE_TX_FIFO_ADDR 0x00
139
140/** Inactivity time to go to sleep in mseconds */
141#define INACTIVITY_TIME_MSEC 30
142#define INITIAL_INACTIVITY_TIME_MSEC 5000
143
144/** Context validity check */
145#define SDIO_AL_SIGNATURE 0xAABBCCDD
146
147/* Vendor Specific Command */
148#define SD_IO_RW_EXTENDED_QCOM 54
149
150#define TIME_TO_WAIT_US 500
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300151#define SDIO_CLOSE_FLUSH_TIMEOUT_MSEC (10000)
Maya Erez5795e0d2011-09-12 20:20:06 +0300152#define RX_FLUSH_BUFFER_SIZE (16*1024)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153
154#define SDIO_TEST_POSTFIX "_TEST"
155
Krishna Kondaa7af6062011-09-01 18:34:38 -0700156#define DATA_DEBUG(x, y...) \
157 do { \
158 if (sdio_al->debug.debug_data_on) \
159 pr_info(y); \
160 sdio_al_log(x, y); \
161 } while (0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700162
Krishna Kondaa7af6062011-09-01 18:34:38 -0700163#define LPM_DEBUG(x, y...) \
164 do { \
165 if (sdio_al->debug.debug_lpm_on) \
166 pr_info(y); \
167 sdio_al_log(x, y); \
168 } while (0)
169
170#define sdio_al_loge(x, y...) \
171 do { \
172 pr_err(y); \
173 sdio_al_log(x, y); \
174 } while (0)
175
176#define sdio_al_logi(x, y...) \
177 do { \
178 pr_info(y); \
179 sdio_al_log(x, y); \
180 } while (0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700181
182/* The index of the SDIO card used for the sdio_al_dloader */
183#define SDIO_BOOTLOADER_CARD_INDEX 1
184
185
186/* SDIO card state machine */
187enum sdio_al_device_state {
188 CARD_INSERTED,
189 CARD_REMOVED,
190 MODEM_RESTART
191};
192
193struct sdio_al_debug {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700194 u8 debug_lpm_on;
195 u8 debug_data_on;
196 struct dentry *sdio_al_debug_root;
197 struct dentry *sdio_al_debug_lpm_on;
198 struct dentry *sdio_al_debug_data_on;
199 struct dentry *sdio_al_debug_info;
Krishna Kondaa7af6062011-09-01 18:34:38 -0700200 struct dentry *sdio_al_debug_log_buffers[MAX_NUM_OF_SDIO_DEVICES + 1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700201};
202
203/* Polling time for the inactivity timer for devices that doesn't have
204 * a streaming channel
205 */
206#define SDIO_AL_POLL_TIME_NO_STREAMING 30
207
208#define CHAN_TO_FUNC(x) ((x) + 2 - 1)
209
210/**
211 * Mailbox structure.
212 * The Mailbox is located on the SDIO-Client Function#1.
213 * The mailbox size is 128 bytes, which is one block.
214 * The mailbox allows the host ton:
215 * 1. Get the number of available bytes on the pipes.
216 * 2. Enable/Disable SDIO-Client interrupt, related to pipes.
217 * 3. Set the Threshold for generating interrupt.
218 *
219 */
220struct sdio_mailbox {
221 u32 pipe_bytes_threshold[SDIO_AL_MAX_PIPES]; /* Addr 0x1000 */
222
223 /* Mask USER interrupts generated towards host - Addr 0x1040 */
224 u32 mask_irq_func_1:8; /* LSB */
225 u32 mask_irq_func_2:8;
226 u32 mask_irq_func_3:8;
227 u32 mask_irq_func_4:8;
228
229 u32 mask_irq_func_5:8;
230 u32 mask_irq_func_6:8;
231 u32 mask_irq_func_7:8;
232 u32 mask_mutex_irq:8;
233
234 /* Mask PIPE interrupts generated towards host - Addr 0x1048 */
235 u32 mask_eot_pipe_0_7:8;
236 u32 mask_thresh_above_limit_pipe_0_7:8;
237 u32 mask_overflow_pipe_0_7:8;
238 u32 mask_underflow_pipe_0_7:8;
239
240 u32 mask_eot_pipe_8_15:8;
241 u32 mask_thresh_above_limit_pipe_8_15:8;
242 u32 mask_overflow_pipe_8_15:8;
243 u32 mask_underflow_pipe_8_15:8;
244
245 /* Status of User interrupts generated towards host - Addr 0x1050 */
246 u32 user_irq_func_1:8;
247 u32 user_irq_func_2:8;
248 u32 user_irq_func_3:8;
249 u32 user_irq_func_4:8;
250
251 u32 user_irq_func_5:8;
252 u32 user_irq_func_6:8;
253 u32 user_irq_func_7:8;
254 u32 user_mutex_irq:8;
255
256 /* Status of PIPE interrupts generated towards host */
257 /* Note: All sources are cleared once they read. - Addr 0x1058 */
258 u32 eot_pipe_0_7:8;
259 u32 thresh_above_limit_pipe_0_7:8;
260 u32 overflow_pipe_0_7:8;
261 u32 underflow_pipe_0_7:8;
262
263 u32 eot_pipe_8_15:8;
264 u32 thresh_above_limit_pipe_8_15:8;
265 u32 overflow_pipe_8_15:8;
266 u32 underflow_pipe_8_15:8;
267
268 u16 pipe_bytes_avail[SDIO_AL_MAX_PIPES];
269};
270
271/** Track pending Rx Packet size */
272struct rx_packet_size {
273 u32 size; /* in bytes */
274 struct list_head list;
275};
276
277#define PEER_SDIOC_SW_MAILBOX_SIGNATURE 0xFACECAFE
278#define PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE 0x5D107E57
279#define PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE 0xDEADBEEF
280
281/* Allow support in old sdio version */
282#define PEER_SDIOC_OLD_VERSION_MAJOR 0x0002
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283#define INVALID_SDIO_CHAN 0xFF
284
285/**
286 * Peer SDIO-Client software header.
287 */
288struct peer_sdioc_sw_header {
289 u32 signature;
290 u32 version;
291 u32 max_channels;
292 char channel_names[SDIO_AL_MAX_CHANNELS][PEER_CHANNEL_NAME_SIZE];
293 u32 reserved[23];
294};
295
296struct peer_sdioc_boot_sw_header {
297 u32 signature;
298 u32 version;
299 u32 boot_ch_num;
300 u32 reserved[29]; /* 32 - previous fields */
301};
302
303/**
304 * Peer SDIO-Client software mailbox.
305 */
306struct peer_sdioc_sw_mailbox {
307 struct peer_sdioc_sw_header sw_header;
308 struct peer_sdioc_channel_config ch_config[SDIO_AL_MAX_CHANNELS];
309};
310
Krishna Kondaa7af6062011-09-01 18:34:38 -0700311#define SDIO_AL_DEBUG_LOG_SIZE 3000
312struct sdio_al_local_log {
313 char buffer[SDIO_AL_DEBUG_LOG_SIZE];
314 unsigned int buf_cur_pos;
315 spinlock_t log_lock;
316};
317
318#define SDIO_AL_DEBUG_TMP_LOG_SIZE 250
319static int sdio_al_log(struct sdio_al_local_log *, const char *fmt, ...);
320
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700321/**
322 * SDIO Abstraction Layer driver context.
323 *
324 * @pdata -
325 * @debug -
326 * @devices - an array of the the devices claimed by sdio_al
327 * @unittest_mode - a flag to indicate if sdio_al is in
328 * unittest mode
329 * @bootloader_dev - the device which is used for the
330 * bootloader
331 * @subsys_notif_handle - handle for modem restart
332 * notifications
333 *
334 */
335struct sdio_al {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700336 struct sdio_al_local_log gen_log;
337 struct sdio_al_local_log device_log[MAX_NUM_OF_SDIO_DEVICES];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700338 struct sdio_al_platform_data *pdata;
339 struct sdio_al_debug debug;
340 struct sdio_al_device *devices[MAX_NUM_OF_SDIO_DEVICES];
341 int unittest_mode;
342 struct sdio_al_device *bootloader_dev;
343 void *subsys_notif_handle;
344 int sdioc_major;
345};
346
347struct sdio_al_work {
348 struct work_struct work;
349 struct sdio_al_device *sdio_al_dev;
350};
351
352
353/**
354 * SDIO Abstraction Layer device context.
355 *
356 * @card - card claimed.
357 *
358 * @mailbox - A shadow of the SDIO-Client mailbox.
359 *
360 * @channel - Channels context.
361 *
362 * @workqueue - workqueue to read the mailbox and handle
363 * pending requests. Reading the mailbox should not happen
364 * in interrupt context.
365 *
366 * @work - work to submit to workqueue.
367 *
368 * @is_ready - driver is ready.
369 *
370 * @ask_mbox - Flag to request reading the mailbox,
371 * for different reasons.
372 *
373 * @wake_lock - Lock when can't sleep.
374 *
375 * @lpm_chan - Channel to use for LPM (low power mode)
376 * communication.
377 *
378 * @is_ok_to_sleep - Mark if driver is OK with going to sleep
379 * (no pending transactions).
380 *
381 * @inactivity_time - time allowed to be in inactivity before
382 * going to sleep
383 *
384 * @timer - timer to use for polling the mailbox.
385 *
386 * @poll_delay_msec - timer delay for polling the mailbox.
387 *
388 * @is_err - error detected.
389 *
390 * @signature - Context Validity Check.
391 *
392 * @flashless_boot_on - flag to indicate if sdio_al is in
393 * flshless boot mode
394 *
395 */
396struct sdio_al_device {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700397 struct sdio_al_local_log *dev_log;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700398 struct mmc_card *card;
399 struct sdio_mailbox *mailbox;
400 struct sdio_channel channel[SDIO_AL_MAX_CHANNELS];
401
402 struct peer_sdioc_sw_header *sdioc_sw_header;
403 struct peer_sdioc_boot_sw_header *sdioc_boot_sw_header;
404
405 struct workqueue_struct *workqueue;
406 struct sdio_al_work sdio_al_work;
407 struct sdio_al_work boot_work;
408
409 int is_ready;
410
411 wait_queue_head_t wait_mbox;
412 int ask_mbox;
413 int bootloader_done;
414
415 struct wake_lock wake_lock;
416 int lpm_chan;
417 int is_ok_to_sleep;
418 unsigned long inactivity_time;
419
420 struct timer_list timer;
421 u32 poll_delay_msec;
422 int is_timer_initialized;
423
424 int is_err;
425
426 u32 signature;
427
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700428 unsigned int is_suspended;
429
430 int flashless_boot_on;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300431 int ch_close_supported;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700432 int state;
433 int (*lpm_callback)(void *, int);
Maya Erez7b1ebd22011-08-20 20:53:24 +0300434
435 int print_after_interrupt;
Maya Erez5795e0d2011-09-12 20:20:06 +0300436
437 u8 *rx_flush_buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700438};
439
440/*
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300441 * Host operation:
442 * lower 16bits are operation code
443 * upper 16bits are operation state
444 */
445#define PEER_OPERATION(op_code , op_state) ((op_code) | ((op_state) << 16))
446#define GET_PEER_OPERATION_CODE(op) ((op) & 0xffff)
447#define GET_PEER_OPERATION_STATE(op) ((op) >> 16)
448
449enum peer_op_code {
450 PEER_OP_CODE_CLOSE = 1
451};
452
453enum peer_op_state {
454 PEER_OP_STATE_INIT = 0,
455 PEER_OP_STATE_START = 1
456};
457
458
459/*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700460 * On the kernel command line specify
461 * sdio_al.debug_lpm_on=1 to enable the LPM debug messages
462 * By default the LPM debug messages are turned off
463 */
464static int debug_lpm_on;
465module_param(debug_lpm_on, int, 0);
466
467/*
468 * On the kernel command line specify
469 * sdio_al.debug_data_on=1 to enable the DATA debug messages
470 * By default the DATA debug messages are turned off
471 */
472static int debug_data_on;
473module_param(debug_data_on, int, 0);
474
475/** The driver context */
476static struct sdio_al *sdio_al;
477
478/* Static functions declaration */
479static int enable_eot_interrupt(struct sdio_al_device *sdio_al_dev,
480 int pipe_index, int enable);
481static int enable_threshold_interrupt(struct sdio_al_device *sdio_al_dev,
482 int pipe_index, int enable);
483static void sdio_func_irq(struct sdio_func *func);
484static void sdio_al_timer_handler(unsigned long data);
485static int get_min_poll_time_msec(struct sdio_al_device *sdio_al_dev);
486static u32 check_pending_rx_packet(struct sdio_channel *ch, u32 eot);
487static u32 remove_handled_rx_packet(struct sdio_channel *ch);
488static int set_pipe_threshold(struct sdio_al_device *sdio_al_dev,
489 int pipe_index, int threshold);
490static int sdio_al_wake_up(struct sdio_al_device *sdio_al_dev,
Maya Erez7b1ebd22011-08-20 20:53:24 +0300491 u32 not_from_int, struct sdio_channel *ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700492static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev);
493static int enable_mask_irq(struct sdio_al_device *sdio_al_dev,
494 int func_num, int enable, u8 bit_offset);
495static int sdio_al_enable_func_retry(struct sdio_func *func, const char *name);
496static void sdio_al_print_info(void);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300497static int sdio_read_internal(struct sdio_channel *ch, void *data, int len);
Maya Erez5795e0d2011-09-12 20:20:06 +0300498static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700499
500#define SDIO_AL_ERR(func) \
501 do { \
502 printk_once(KERN_ERR MODULE_NAME \
503 ":In Error state, ignore %s\n", \
504 func); \
505 sdio_al_print_info(); \
506 } while (0)
507
508#ifdef CONFIG_DEBUG_FS
509static int debug_info_open(struct inode *inode, struct file *file)
510{
511 file->private_data = inode->i_private;
512 return 0;
513}
514
515static ssize_t debug_info_write(struct file *file,
516 const char __user *buf, size_t count, loff_t *ppos)
517{
518 sdio_al_print_info();
519 return 1;
520}
521
522const struct file_operations debug_info_ops = {
523 .open = debug_info_open,
524 .write = debug_info_write,
525};
526
Krishna Kondaa7af6062011-09-01 18:34:38 -0700527struct debugfs_blob_wrapper sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES + 1];
528
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700529/*
530*
531* Trigger on/off for debug messages
532* for trigger off the data messages debug level use:
533* echo 0 > /sys/kernel/debugfs/sdio_al/debug_data_on
534* for trigger on the data messages debug level use:
535* echo 1 > /sys/kernel/debugfs/sdio_al/debug_data_on
536* for trigger off the lpm messages debug level use:
537* echo 0 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
538* for trigger on the lpm messages debug level use:
539* echo 1 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
540*/
541static int sdio_al_debugfs_init(void)
542{
Krishna Kondaa7af6062011-09-01 18:34:38 -0700543 int i, blob_errs = 0;
544
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700545 sdio_al->debug.sdio_al_debug_root = debugfs_create_dir("sdio_al", NULL);
546 if (!sdio_al->debug.sdio_al_debug_root)
547 return -ENOENT;
548
549 sdio_al->debug.sdio_al_debug_lpm_on = debugfs_create_u8("debug_lpm_on",
550 S_IRUGO | S_IWUGO,
551 sdio_al->debug.sdio_al_debug_root,
552 &sdio_al->debug.debug_lpm_on);
553
554 sdio_al->debug.sdio_al_debug_data_on = debugfs_create_u8(
555 "debug_data_on",
556 S_IRUGO | S_IWUGO,
557 sdio_al->debug.sdio_al_debug_root,
558 &sdio_al->debug.debug_data_on);
559
560 sdio_al->debug.sdio_al_debug_info = debugfs_create_file(
561 "sdio_debug_info",
562 S_IRUGO | S_IWUGO,
563 sdio_al->debug.sdio_al_debug_root,
564 NULL,
565 &debug_info_ops);
566
Krishna Kondaa7af6062011-09-01 18:34:38 -0700567 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
568 char temp[18];
569
570 scnprintf(temp, 18, "sdio_al_log_dev_%d", i + 1);
571 sdio_al->debug.sdio_al_debug_log_buffers[i] =
572 debugfs_create_blob(temp,
573 S_IRUGO | S_IWUGO,
574 sdio_al->debug.sdio_al_debug_root,
575 &sdio_al_dbgfs_log[i]);
576 }
577
578 sdio_al->debug.sdio_al_debug_log_buffers[MAX_NUM_OF_SDIO_DEVICES] =
579 debugfs_create_blob("sdio_al_gen_log",
580 S_IRUGO | S_IWUGO,
581 sdio_al->debug.sdio_al_debug_root,
582 &sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES]);
583
584 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i) {
585 if (!sdio_al->debug.sdio_al_debug_log_buffers[i]) {
586 pr_err(MODULE_NAME ": Failed to create debugfs buffer"
587 " entry for "
588 "sdio_al->debug.sdio_al_debug_log_buffers[%d]",
589 i);
590 blob_errs = 1;
591 }
592 }
593
594 if (blob_errs) {
595 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i)
596 if (sdio_al->debug.sdio_al_debug_log_buffers[i])
597 debugfs_remove(
598 sdio_al->
599 debug.sdio_al_debug_log_buffers[i]);
600 }
601
602
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700603 if ((!sdio_al->debug.sdio_al_debug_data_on) &&
604 (!sdio_al->debug.sdio_al_debug_lpm_on) &&
Krishna Kondaa7af6062011-09-01 18:34:38 -0700605 (!sdio_al->debug.sdio_al_debug_info) &&
606 blob_errs) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700607 debugfs_remove(sdio_al->debug.sdio_al_debug_root);
608 sdio_al->debug.sdio_al_debug_root = NULL;
609 return -ENOENT;
610 }
Krishna Kondaa7af6062011-09-01 18:34:38 -0700611
612 sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES].data =
613 sdio_al->gen_log.buffer;
614 sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES].size =
615 SDIO_AL_DEBUG_LOG_SIZE;
616
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700617 return 0;
618}
619
620static void sdio_al_debugfs_cleanup(void)
621{
Krishna Kondaa7af6062011-09-01 18:34:38 -0700622 int i;
623
624 debugfs_remove(sdio_al->debug.sdio_al_debug_lpm_on);
625 debugfs_remove(sdio_al->debug.sdio_al_debug_data_on);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700626 debugfs_remove(sdio_al->debug.sdio_al_debug_info);
Krishna Kondaa7af6062011-09-01 18:34:38 -0700627
628 for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i)
629 debugfs_remove(sdio_al->debug.sdio_al_debug_log_buffers[i]);
630
631 debugfs_remove(sdio_al->debug.sdio_al_debug_root);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700632}
633#endif
634
Krishna Kondaa7af6062011-09-01 18:34:38 -0700635static int sdio_al_log(struct sdio_al_local_log *log, const char *fmt, ...)
636{
637 va_list args;
638 int r;
639 char *tp, *log_buf;
640 unsigned int *log_cur_pos;
641 struct timeval kt;
642 unsigned long flags;
643 static char sdio_al_log_tmp[SDIO_AL_DEBUG_TMP_LOG_SIZE];
644
645 spin_lock_irqsave(&log->log_lock, flags);
646
647 kt = ktime_to_timeval(ktime_get());
648 r = scnprintf(sdio_al_log_tmp, SDIO_AL_DEBUG_TMP_LOG_SIZE,
649 "[%8ld.%6ld] ", kt.tv_sec, kt.tv_usec);
650
651 va_start(args, fmt);
652 r += vscnprintf(&sdio_al_log_tmp[r], (SDIO_AL_DEBUG_TMP_LOG_SIZE - r),
653 fmt, args);
654 va_end(args);
655
656 log_buf = log->buffer;
657 log_cur_pos = &(log->buf_cur_pos);
658
659 for (tp = sdio_al_log_tmp; tp < (sdio_al_log_tmp + r); tp++) {
660 log_buf[(*log_cur_pos)++] = *tp;
661 if ((*log_cur_pos) == SDIO_AL_DEBUG_LOG_SIZE)
662 *log_cur_pos = 0;
663 }
664
665 spin_unlock_irqrestore(&log->log_lock, flags);
666
667 return r;
668}
669
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700670static int sdio_al_verify_func1(struct sdio_al_device *sdio_al_dev,
671 char const *func)
672{
673 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700674 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
675 "sdio_al_dev\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700676 return -ENODEV;
677 }
678 if (!sdio_al_dev->card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700679 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
680 "card\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700681 return -ENODEV;
682 }
683 if (!sdio_al_dev->card->sdio_func[0]) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700684 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
685 "func1\n", func);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700686 return -ENODEV;
687 }
688 return 0;
689}
690
691
692static int sdio_al_verify_dev(struct sdio_al_device *sdio_al_dev,
693 char const *func)
694{
695 int ret;
696
697 ret = sdio_al_verify_func1(sdio_al_dev, func);
698 if (ret)
699 return ret;
700
701 if ((sdio_al_dev->state == MODEM_RESTART) ||
702 (sdio_al_dev->state == CARD_REMOVED)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700703 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: device "
704 "state %d\n", func, sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700705 return -ENODEV;
706 }
707 return 0;
708}
709
710static void sdio_al_get_into_err_state(struct sdio_al_device *sdio_al_dev)
711{
712 if ((!sdio_al) || (!sdio_al_dev))
713 return;
714
715 sdio_al_dev->is_err = true;
716 sdio_al->debug.debug_data_on = 0;
717 sdio_al->debug.debug_lpm_on = 0;
718 sdio_al_print_info();
719}
720
721void sdio_al_register_lpm_cb(void *device_handle,
722 int(*lpm_callback)(void *, int))
723{
724 struct sdio_al_device *sdio_al_dev =
725 (struct sdio_al_device *) device_handle;
726
727 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700728 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - "
729 "device_handle is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700730 return;
731 }
732
733 if (lpm_callback) {
734 sdio_al_dev->lpm_callback = lpm_callback;
735 lpm_callback((void *)sdio_al_dev,
736 sdio_al_dev->is_ok_to_sleep);
737 }
Krishna Kondaa7af6062011-09-01 18:34:38 -0700738
739 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - device %d "
740 "registered for wakeup callback\n", __func__,
741 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700742}
743
744void sdio_al_unregister_lpm_cb(void *device_handle)
745{
746 struct sdio_al_device *sdio_al_dev =
747 (struct sdio_al_device *) device_handle;
748
749 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700750 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - "
751 "device_handle is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700752 return;
753 }
754
755 sdio_al_dev->lpm_callback = NULL;
Krishna Kondaa7af6062011-09-01 18:34:38 -0700756 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - device %d "
757 "unregister for wakeup callback\n", __func__,
758 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700759}
760
761static void sdio_al_vote_for_sleep(struct sdio_al_device *sdio_al_dev,
762 int is_vote_for_sleep)
763{
764 pr_debug(MODULE_NAME ": %s()", __func__);
765
Yaniv Gardi3e327762011-07-27 11:11:04 +0300766 if (!sdio_al_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700767 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - sdio_al_dev"
768 " is NULL\n", __func__);
Yaniv Gardi3e327762011-07-27 11:11:04 +0300769 return;
770 }
771
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700772 if (is_vote_for_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +0300773 pr_debug(MODULE_NAME ": %s - sdio vote for Sleep", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700774 wake_unlock(&sdio_al_dev->wake_lock);
775 } else {
Maya Erez7b1ebd22011-08-20 20:53:24 +0300776 pr_debug(MODULE_NAME ": %s - sdio vote against sleep",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700777 __func__);
778 wake_lock(&sdio_al_dev->wake_lock);
779 }
780
781 if (sdio_al_dev->lpm_callback != NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700782 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - "
783 "is_vote_for_sleep=%d for card#%d, "
784 "calling callback...", __func__,
785 is_vote_for_sleep,
786 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700787 sdio_al_dev->lpm_callback((void *)sdio_al_dev,
788 is_vote_for_sleep);
789 }
790}
791
792/**
793 * Write SDIO-Client lpm information
794 * Should only be called with host claimed.
795 */
796static int write_lpm_info(struct sdio_al_device *sdio_al_dev)
797{
798 struct sdio_func *lpm_func =
799 sdio_al_dev->card->sdio_func[sdio_al_dev->lpm_chan+1];
800 int offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
801 sizeof(struct peer_sdioc_channel_config) *
802 sdio_al_dev->lpm_chan+
803 offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
804 int ret;
805
806 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700807 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
808 "lpm_chan for card %d\n",
809 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700810 return -EINVAL;
811 }
812
813 pr_debug(MODULE_NAME ":write_lpm_info is_ok_to_sleep=%d, device %d\n",
814 sdio_al_dev->is_ok_to_sleep,
815 sdio_al_dev->card->host->index);
816
817 ret = sdio_memcpy_toio(lpm_func, SDIOC_SW_MAILBOX_ADDR+offset,
818 &sdio_al_dev->is_ok_to_sleep, sizeof(u32));
819 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700820 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
821 "write lpm info for card %d\n",
822 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700823 return ret;
824 }
825
826 return 0;
827}
828
829/* Set inactivity counter to intial value to allow clients come up */
830static inline void start_inactive_time(struct sdio_al_device *sdio_al_dev)
831{
832 sdio_al_dev->inactivity_time = jiffies +
833 msecs_to_jiffies(INITIAL_INACTIVITY_TIME_MSEC);
834}
835
836static inline void restart_inactive_time(struct sdio_al_device *sdio_al_dev)
837{
838 sdio_al_dev->inactivity_time = jiffies +
839 msecs_to_jiffies(INACTIVITY_TIME_MSEC);
840}
841
842static inline int is_inactive_time_expired(struct sdio_al_device *sdio_al_dev)
843{
844 return time_after(jiffies, sdio_al_dev->inactivity_time);
845}
846
847
848static int is_user_irq_enabled(struct sdio_al_device *sdio_al_dev,
849 int func_num)
850{
851 int ret = 0;
852 struct sdio_func *func1;
853 u32 user_irq = 0;
854 u32 addr = 0;
855 u32 offset = 0;
856 u32 masked_user_irq = 0;
857
858 if (sdio_al_verify_dev(sdio_al_dev, __func__))
859 return 0;
860 func1 = sdio_al_dev->card->sdio_func[0];
861
862 if (func_num < 4) {
863 addr = FUNC_1_4_USER_IRQ_ADDR;
864 offset = func_num * 8;
865 } else {
866 addr = FUNC_5_7_USER_IRQ_ADDR;
867 offset = (func_num - 4) * 8;
868 }
869
870 user_irq = sdio_readl(func1, addr, &ret);
871 if (ret) {
872 pr_debug(MODULE_NAME ":read_user_irq fail\n");
873 return 0;
874 }
875
876 masked_user_irq = (user_irq >> offset) && 0xFF;
877 if (masked_user_irq == 0x1) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700878 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":user_irq "
879 "enabled\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700880 return 1;
881 }
882
883 return 0;
884}
885
886static void sdio_al_sleep(struct sdio_al_device *sdio_al_dev,
887 struct mmc_host *host)
888{
889 int i;
890
891 /* Go to sleep */
Maya Erez7b1ebd22011-08-20 20:53:24 +0300892 pr_debug(MODULE_NAME ":Inactivity timer expired."
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700893 " Going to sleep\n");
894 /* Stop mailbox timer */
895 sdio_al_dev->poll_delay_msec = 0;
896 del_timer_sync(&sdio_al_dev->timer);
897 /* Make sure we get interrupt for non-packet-mode right away */
898 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
899 struct sdio_channel *ch = &sdio_al_dev->channel[i];
Maya Erez5795e0d2011-09-12 20:20:06 +0300900 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
901 (ch->state != SDIO_CHANNEL_STATE_CLOSED)) {
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300902 pr_debug(MODULE_NAME ":continue for channel %s in"
903 " state %d\n", ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904 continue;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300905 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700906 if (ch->is_packet_mode == false) {
907 ch->read_threshold = 1;
908 set_pipe_threshold(sdio_al_dev,
909 ch->rx_pipe_index,
910 ch->read_threshold);
911 }
912 }
Maya Erezfd915312011-07-14 13:45:34 +0300913 /* Prevent modem to go to sleep until we get the PROG_DONE on
914 the dummy CMD52 */
915 msmsdcc_set_pwrsave(sdio_al_dev->card->host, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700916 /* Mark HOST_OK_TOSLEEP */
917 sdio_al_dev->is_ok_to_sleep = 1;
918 write_lpm_info(sdio_al_dev);
919
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700920 msmsdcc_lpm_enable(host);
Krishna Kondaa7af6062011-09-01 18:34:38 -0700921 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Finished sleep sequence"
922 " for card %d. Sleep now.\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700923 sdio_al_dev->card->host->index);
924 /* Release wakelock */
925 sdio_al_vote_for_sleep(sdio_al_dev, 1);
926}
927
928
929/**
930 * Read SDIO-Client Mailbox from Function#1.thresh_pipe
931 *
932 * The mailbox contain the bytes available per pipe,
933 * and the End-Of-Transfer indication per pipe (if available).
934 *
935 * WARNING: Each time the Mailbox is read from the client, the
936 * read_bytes_avail is incremented with another pending
937 * transfer. Therefore, a pending rx-packet should be added to a
938 * list before the next read of the mailbox.
939 *
940 * This function should run from a workqueue context since it
941 * notifies the clients.
942 *
943 * This function assumes that sdio_claim_host was called before
944 * calling it.
945 *
946 */
947static int read_mailbox(struct sdio_al_device *sdio_al_dev, int from_isr)
948{
949 int ret;
950 struct sdio_func *func1 = sdio_al_dev->card->sdio_func[0];
951 struct sdio_mailbox *mailbox = sdio_al_dev->mailbox;
952 struct mmc_host *host = func1->card->host;
953 u32 new_write_avail = 0;
954 u32 old_write_avail = 0;
955 u32 any_read_avail = 0;
956 u32 any_write_pending = 0;
957 int i;
958 u32 rx_notify_bitmask = 0;
959 u32 tx_notify_bitmask = 0;
960 u32 eot_pipe = 0;
961 u32 thresh_pipe = 0;
962 u32 overflow_pipe = 0;
963 u32 underflow_pipe = 0;
964 u32 thresh_intr_mask = 0;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +0300965 int is_closing = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700966
967 if (sdio_al_dev->is_err) {
968 SDIO_AL_ERR(__func__);
969 return 0;
970 }
971
972 pr_debug(MODULE_NAME ":start %s from_isr = %d for card %d.\n"
973 , __func__, from_isr, sdio_al_dev->card->host->index);
974
975 pr_debug(MODULE_NAME ":before sdio_memcpy_fromio.\n");
Maya Erez320a7ca2011-08-03 09:41:27 +0300976 memset(mailbox, 0, sizeof(struct sdio_mailbox));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700977 ret = sdio_memcpy_fromio(func1, mailbox,
978 HW_MAILBOX_ADDR, sizeof(*mailbox));
979 pr_debug(MODULE_NAME ":after sdio_memcpy_fromio.\n");
Maya Erez320a7ca2011-08-03 09:41:27 +0300980 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -0700981 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to read "
982 "Mailbox for card %d, goto error state\n",
983 sdio_al_dev->card->host->index);
Maya Erez320a7ca2011-08-03 09:41:27 +0300984 sdio_al_get_into_err_state(sdio_al_dev);
985 /* Stop the timer to stop reading the mailbox */
986 sdio_al_dev->poll_delay_msec = 0;
987 goto exit_err;
988 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700989
990 eot_pipe = (mailbox->eot_pipe_0_7) |
991 (mailbox->eot_pipe_8_15<<8);
992 thresh_pipe = (mailbox->thresh_above_limit_pipe_0_7) |
993 (mailbox->thresh_above_limit_pipe_8_15<<8);
994
995 overflow_pipe = (mailbox->overflow_pipe_0_7) |
996 (mailbox->overflow_pipe_8_15<<8);
997 underflow_pipe = mailbox->underflow_pipe_0_7 |
998 (mailbox->underflow_pipe_8_15<<8);
999 thresh_intr_mask =
1000 (mailbox->mask_thresh_above_limit_pipe_0_7) |
1001 (mailbox->mask_thresh_above_limit_pipe_8_15<<8);
1002
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001003 if (overflow_pipe || underflow_pipe)
Krishna Kondaa7af6062011-09-01 18:34:38 -07001004 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Mailbox ERROR "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001005 "overflow=0x%x, underflow=0x%x\n",
1006 overflow_pipe, underflow_pipe);
1007
1008 /* In case of modem reset we would like to read the daya from the modem
1009 to clear the interrupts but do not process it */
1010 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001011 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_device"
1012 " (card %d) is in invalid state %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001013 sdio_al_dev->card->host->index,
1014 sdio_al_dev->state);
1015 return -ENODEV;
1016 }
1017
1018 pr_debug(MODULE_NAME ":card %d: eot=0x%x, thresh=0x%x\n",
1019 sdio_al_dev->card->host->index,
1020 eot_pipe, thresh_pipe);
1021
1022 /* Scan for Rx Packets available and update read available bytes */
1023 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1024 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1025 u32 old_read_avail;
1026 u32 read_avail;
1027 u32 new_packet_size = 0;
1028
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001029 if (ch->state == SDIO_CHANNEL_STATE_CLOSING)
1030 is_closing = true; /* used to prevent sleep */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001031
1032 old_read_avail = ch->read_avail;
1033 read_avail = mailbox->pipe_bytes_avail[ch->rx_pipe_index];
1034
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001035 if ((ch->state == SDIO_CHANNEL_STATE_CLOSED) &&
1036 (read_avail > 0)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001037 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1038 ":%s: Invalid read_avail 0x%x, for CLOSED ch %s\n",
Maya Erez5795e0d2011-09-12 20:20:06 +03001039 __func__, read_avail, ch->name);
1040 sdio_read_from_closed_ch(ch, read_avail);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001041 }
1042 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
1043 (ch->state != SDIO_CHANNEL_STATE_CLOSING))
1044 continue;
1045
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001046 if (read_avail > INVALID_DATA_AVAILABLE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001047 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001048 ":Invalid read_avail 0x%x for pipe %d\n",
1049 read_avail, ch->rx_pipe_index);
1050 continue;
1051 }
1052 any_read_avail |= read_avail | old_read_avail;
1053 ch->statistics.last_any_read_avail = any_read_avail;
1054 ch->statistics.last_read_avail = read_avail;
1055 ch->statistics.last_old_read_avail = old_read_avail;
1056
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001057 if (ch->is_packet_mode) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001058 if ((eot_pipe & (1<<ch->rx_pipe_index)) &&
1059 sdio_al_dev->print_after_interrupt) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001060 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME
1061 ":Interrupt on ch %s, "
1062 "card %d", ch->name,
1063 sdio_al_dev->card->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03001064 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001065 new_packet_size = check_pending_rx_packet(ch, eot_pipe);
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001066 } else {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001067 if ((thresh_pipe & (1<<ch->rx_pipe_index)) &&
1068 sdio_al_dev->print_after_interrupt) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001069 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME
1070 ":Interrupt on ch %s, "
1071 "card %d", ch->name,
1072 sdio_al_dev->card->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03001073 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001074 ch->read_avail = read_avail;
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001075 /* Restore default thresh for non packet channels */
1076 if ((ch->read_threshold != ch->def_read_threshold) &&
1077 (read_avail >= ch->threshold_change_cnt)) {
1078 ch->read_threshold = ch->def_read_threshold;
1079 set_pipe_threshold(sdio_al_dev,
1080 ch->rx_pipe_index,
1081 ch->read_threshold);
1082 }
1083 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001084
1085 if ((ch->is_packet_mode) && (new_packet_size > 0)) {
1086 rx_notify_bitmask |= (1<<ch->num);
1087 ch->statistics.total_notifs++;
1088 }
1089
1090 if ((!ch->is_packet_mode) && (ch->read_avail > 0) &&
1091 (old_read_avail == 0)) {
1092 rx_notify_bitmask |= (1<<ch->num);
1093 ch->statistics.total_notifs++;
1094 }
1095 }
Maya Erez7b1ebd22011-08-20 20:53:24 +03001096 sdio_al_dev->print_after_interrupt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001097
1098 /* Update Write available */
1099 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1100 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1101
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001102 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
1103 (ch->state != SDIO_CHANNEL_STATE_CLOSING))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001104 continue;
1105
1106 new_write_avail = mailbox->pipe_bytes_avail[ch->tx_pipe_index];
1107
1108 if (new_write_avail > INVALID_DATA_AVAILABLE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001109 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001110 ":Invalid write_avail 0x%x for pipe %d\n",
1111 new_write_avail, ch->tx_pipe_index);
1112 continue;
1113 }
1114
1115 old_write_avail = ch->write_avail;
1116 ch->write_avail = new_write_avail;
1117
1118 if ((old_write_avail <= ch->min_write_avail) &&
1119 (new_write_avail >= ch->min_write_avail))
1120 tx_notify_bitmask |= (1<<ch->num);
1121
1122 /* There is not enough write avail for this channel.
1123 We need to keep reading mailbox to wait for the appropriate
1124 write avail and cannot sleep. Ignore SMEM channel that has
1125 only one direction. */
1126 if (strcmp(ch->name, "SDIO_SMEM"))
1127 any_write_pending |=
1128 (new_write_avail < ch->ch_config.max_tx_threshold);
1129 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001130 /* notify clients */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001131 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1132 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1133
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001134 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) ||
1135 (ch->notify == NULL))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001136 continue;
1137
1138 if (rx_notify_bitmask & (1<<ch->num))
1139 ch->notify(ch->priv,
1140 SDIO_EVENT_DATA_READ_AVAIL);
1141
1142 if (tx_notify_bitmask & (1<<ch->num))
1143 ch->notify(ch->priv,
1144 SDIO_EVENT_DATA_WRITE_AVAIL);
1145 }
1146
1147
1148 if ((rx_notify_bitmask == 0) && (tx_notify_bitmask == 0) &&
1149 !any_read_avail && !any_write_pending) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001150 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Nothing to "
1151 "Notify for card %d, is_closing=%d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001152 sdio_al_dev->card->host->index, is_closing);
1153 if (is_closing)
1154 restart_inactive_time(sdio_al_dev);
1155 else if (is_inactive_time_expired(sdio_al_dev))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001156 sdio_al_sleep(sdio_al_dev, host);
1157 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001158 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Notify bitmask"
1159 " for card %d rx=0x%x, tx=0x%x.\n",
1160 sdio_al_dev->card->host->index,
1161 rx_notify_bitmask, tx_notify_bitmask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001162 /* Restart inactivity timer if any activity on the channel */
1163 restart_inactive_time(sdio_al_dev);
1164 }
1165
1166 pr_debug(MODULE_NAME ":end %s.\n", __func__);
1167
1168exit_err:
1169 return ret;
1170}
1171
1172/**
1173 * Check pending rx packet when reading the mailbox.
1174 */
1175static u32 check_pending_rx_packet(struct sdio_channel *ch, u32 eot)
1176{
1177 u32 rx_pending;
1178 u32 rx_avail;
1179 u32 new_packet_size = 0;
1180 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
1181
1182
1183 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001184 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
1185 " for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001186 return -EINVAL;
1187 }
1188
1189 mutex_lock(&ch->ch_lock);
1190
1191 rx_pending = ch->rx_pending_bytes;
1192 rx_avail = sdio_al_dev->mailbox->pipe_bytes_avail[ch->rx_pipe_index];
1193
1194 pr_debug(MODULE_NAME ":pipe %d of card %d rx_avail=0x%x, "
1195 "rx_pending=0x%x\n",
1196 ch->rx_pipe_index, sdio_al_dev->card->host->index, rx_avail,
1197 rx_pending);
1198
1199
1200 /* new packet detected */
1201 if (eot & (1<<ch->rx_pipe_index)) {
1202 struct rx_packet_size *p = NULL;
1203 new_packet_size = rx_avail - rx_pending;
1204
1205 if ((rx_avail <= rx_pending)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001206 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1207 ": Invalid new packet size."
1208 " rx_avail=%d.\n", rx_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001209 new_packet_size = 0;
1210 goto exit_err;
1211 }
1212
1213 p = kzalloc(sizeof(*p), GFP_KERNEL);
Maya Erezd9cc2292011-08-04 09:20:31 +03001214 if (p == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001215 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1216 ": failed to allocate item for "
1217 "rx_pending list. rx_avail=%d, "
1218 "rx_pending=%d.\n",
1219 rx_avail, rx_pending);
Maya Erezd9cc2292011-08-04 09:20:31 +03001220 new_packet_size = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001221 goto exit_err;
Maya Erezd9cc2292011-08-04 09:20:31 +03001222 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001223 p->size = new_packet_size;
1224 /* Add new packet as last */
1225 list_add_tail(&p->list, &ch->rx_size_list_head);
1226 ch->rx_pending_bytes += new_packet_size;
1227
1228 if (ch->read_avail == 0)
1229 ch->read_avail = new_packet_size;
1230 }
1231
1232exit_err:
1233 mutex_unlock(&ch->ch_lock);
1234
1235 return new_packet_size;
1236}
1237
1238
1239
1240/**
1241 * Remove first pending packet from the list.
1242 */
1243static u32 remove_handled_rx_packet(struct sdio_channel *ch)
1244{
1245 struct rx_packet_size *p = NULL;
1246
1247 mutex_lock(&ch->ch_lock);
1248
1249 ch->rx_pending_bytes -= ch->read_avail;
1250
1251 if (!list_empty(&ch->rx_size_list_head)) {
1252 p = list_first_entry(&ch->rx_size_list_head,
1253 struct rx_packet_size, list);
1254 list_del(&p->list);
1255 kfree(p);
Maya Erezd9cc2292011-08-04 09:20:31 +03001256 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001257 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: ch "
1258 "%s: unexpected empty list!!\n",
1259 __func__, ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001260 }
1261
1262 if (list_empty(&ch->rx_size_list_head)) {
1263 ch->read_avail = 0;
1264 } else {
1265 p = list_first_entry(&ch->rx_size_list_head,
1266 struct rx_packet_size, list);
1267 ch->read_avail = p->size;
1268 }
1269
1270 mutex_unlock(&ch->ch_lock);
1271
1272 return ch->read_avail;
1273}
1274
1275
1276/**
1277 * Bootloader worker function.
1278 *
1279 * @note: clear the bootloader_done flag only after reading the
1280 * mailbox, to ignore more requests while reading the mailbox.
1281 */
1282static void boot_worker(struct work_struct *work)
1283{
1284 int ret = 0;
1285 int func_num = 0;
1286 int i;
1287 struct sdio_al_device *sdio_al_dev = NULL;
1288 struct sdio_al_work *sdio_al_work = container_of(work,
1289 struct sdio_al_work,
1290 work);
1291
1292 if (sdio_al_work == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001293 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1294 "sdio_al_work\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001295 return;
1296 }
1297
1298 sdio_al_dev = sdio_al_work->sdio_al_dev;
1299 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001300 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1301 "sdio_al_dev\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001302 return;
1303 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07001304 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":Bootloader Worker Started"
1305 ", wait for bootloader_done event..\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001306 wait_event(sdio_al_dev->wait_mbox,
1307 sdio_al_dev->bootloader_done);
Krishna Kondaa7af6062011-09-01 18:34:38 -07001308 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":Got bootloader_done "
1309 "event..\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001310 /* Do polling until MDM is up */
1311 for (i = 0; i < 5000; ++i) {
1312 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1313 return;
1314 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
1315 if (is_user_irq_enabled(sdio_al_dev, func_num)) {
1316 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
1317 sdio_al_dev->bootloader_done = 0;
1318 ret = sdio_al_client_setup(sdio_al_dev);
1319 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001320 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1321 ": sdio_al_client_setup failed, "
1322 "for card %d ret=%d\n",
1323 sdio_al_dev->card->host->index, ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001324 sdio_al_get_into_err_state(sdio_al_dev);
1325 }
1326 goto done;
1327 }
1328 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
1329 msleep(100);
1330 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07001331 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Timeout waiting for "
1332 "user_irq for card %d\n",
1333 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001334 sdio_al_get_into_err_state(sdio_al_dev);
1335
1336done:
1337 pr_debug(MODULE_NAME ":Boot Worker for card %d Exit!\n",
1338 sdio_al_dev->card->host->index);
1339}
1340
1341/**
1342 * Worker function.
1343 *
1344 * @note: clear the ask_mbox flag only after
1345 * reading the mailbox, to ignore more requests while
1346 * reading the mailbox.
1347 */
1348static void worker(struct work_struct *work)
1349{
1350 int ret = 0;
1351 struct sdio_al_device *sdio_al_dev = NULL;
1352 struct sdio_al_work *sdio_al_work = container_of(work,
1353 struct sdio_al_work,
1354 work);
1355 if (sdio_al_work == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001356 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": worker: NULL "
1357 "sdio_al_work\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001358 return;
1359 }
1360
1361 sdio_al_dev = sdio_al_work->sdio_al_dev;
1362 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001363 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": worker: NULL "
1364 "sdio_al_dev\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001365 return;
1366 }
1367 pr_debug(MODULE_NAME ":Worker Started..\n");
1368 while ((sdio_al_dev->is_ready) && (ret == 0)) {
1369 pr_debug(MODULE_NAME ":Wait for read mailbox request..\n");
1370 wait_event(sdio_al_dev->wait_mbox, sdio_al_dev->ask_mbox);
1371 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1372 break;
1373 if (!sdio_al_dev->is_ready)
1374 break;
1375 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
1376 if (sdio_al_dev->is_ok_to_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03001377 ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001378 if (ret) {
1379 sdio_release_host(
1380 sdio_al_dev->card->sdio_func[0]);
1381 return;
1382 }
1383 }
1384 ret = read_mailbox(sdio_al_dev, false);
1385 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
1386 sdio_al_dev->ask_mbox = false;
1387 }
1388 pr_debug(MODULE_NAME ":Worker Exit!\n");
1389}
1390
1391/**
1392 * Write command using CMD54 rather than CMD53.
1393 * Writing with CMD54 generate EOT interrupt at the
1394 * SDIO-Client.
1395 * Based on mmc_io_rw_extended()
1396 */
1397static int sdio_write_cmd54(struct mmc_card *card, unsigned fn,
1398 unsigned addr, const u8 *buf,
1399 unsigned blocks, unsigned blksz)
1400{
1401 struct mmc_request mrq;
1402 struct mmc_command cmd;
1403 struct mmc_data data;
1404 struct scatterlist sg;
1405 int incr_addr = 1; /* MUST */
1406 int write = 1;
1407
1408 BUG_ON(!card);
1409 BUG_ON(fn > 7);
1410 BUG_ON(blocks == 1 && blksz > 512);
1411 WARN_ON(blocks == 0);
1412 WARN_ON(blksz == 0);
1413
1414 write = true;
1415 pr_debug(MODULE_NAME ":sdio_write_cmd54()"
1416 "fn=%d,buf=0x%x,blocks=%d,blksz=%d\n",
1417 fn, (u32) buf, blocks, blksz);
1418
1419 memset(&mrq, 0, sizeof(struct mmc_request));
1420 memset(&cmd, 0, sizeof(struct mmc_command));
1421 memset(&data, 0, sizeof(struct mmc_data));
1422
1423 mrq.cmd = &cmd;
1424 mrq.data = &data;
1425
1426 cmd.opcode = SD_IO_RW_EXTENDED_QCOM;
1427
1428 cmd.arg = write ? 0x80000000 : 0x00000000;
1429 cmd.arg |= fn << 28;
1430 cmd.arg |= incr_addr ? 0x04000000 : 0x00000000;
1431 cmd.arg |= addr << 9;
1432 if (blocks == 1 && blksz <= 512)
1433 cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */
1434 else
1435 cmd.arg |= 0x08000000 | blocks; /* block mode */
1436 cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
1437
1438 data.blksz = blksz;
1439 data.blocks = blocks;
1440 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
1441 data.sg = &sg;
1442 data.sg_len = 1;
1443
1444 sg_init_one(&sg, buf, blksz * blocks);
1445
1446 mmc_set_data_timeout(&data, card);
1447
1448 mmc_wait_for_req(card->host, &mrq);
1449
1450 if (cmd.error)
1451 return cmd.error;
1452 if (data.error)
1453 return data.error;
1454
1455 if (mmc_host_is_spi(card->host)) {
1456 /* host driver already reported errors */
1457 } else {
1458 if (cmd.resp[0] & R5_ERROR) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001459 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1460 ":%s: R5_ERROR for card %d",
1461 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001462 return -EIO;
1463 }
1464 if (cmd.resp[0] & R5_FUNCTION_NUMBER) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001465 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1466 ":%s: R5_FUNCTION_NUMBER for card %d",
1467 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001468 return -EINVAL;
1469 }
1470 if (cmd.resp[0] & R5_OUT_OF_RANGE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001471 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1472 ":%s: R5_OUT_OF_RANGE for card %d",
1473 __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001474 return -ERANGE;
1475 }
1476 }
1477
1478 return 0;
1479}
1480
1481
1482/**
1483 * Write data to channel.
1484 * Handle different data size types.
1485 *
1486 */
1487static int sdio_ch_write(struct sdio_channel *ch, const u8 *buf, u32 len)
1488{
1489 int ret = 0;
1490 unsigned blksz = ch->func->cur_blksize;
1491 int blocks = len / blksz;
1492 int remain_bytes = len % blksz;
1493 struct mmc_card *card = NULL;
1494 u32 fn = ch->func->num;
1495
Krishna Kondaa7af6062011-09-01 18:34:38 -07001496 if (!ch) {
1497 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1498 "channel\n", __func__);
1499 return -ENODEV;
1500 }
1501
1502 if (!ch->sdio_al_dev) {
1503 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
1504 "sdio_al_dev\n", __func__);
1505 return -ENODEV;
1506 }
1507
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001508 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001509 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":channel "
1510 "%s trying to write 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001511 return -EINVAL;
1512 }
1513
1514 card = ch->func->card;
1515
1516 if (remain_bytes) {
1517 /* CMD53 */
1518 if (blocks) {
1519 ret = sdio_memcpy_toio(ch->func, PIPE_TX_FIFO_ADDR,
1520 (void *) buf, blocks*blksz);
1521 if (ret != 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001522 sdio_al_loge(ch->sdio_al_dev->dev_log,
1523 MODULE_NAME ":%s: sdio_memcpy_toio "
1524 "failed for channel %s\n",
1525 __func__, ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001526 ch->sdio_al_dev->is_err = true;
1527 return ret;
1528 }
1529 }
1530
1531 buf += (blocks*blksz);
1532
1533 ret = sdio_write_cmd54(card, fn, PIPE_TX_FIFO_ADDR,
1534 buf, 1, remain_bytes);
1535 } else {
1536 ret = sdio_write_cmd54(card, fn, PIPE_TX_FIFO_ADDR,
1537 buf, blocks, blksz);
1538 }
1539
1540 if (ret != 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001541 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
1542 "sdio_write_cmd54 failed for channel %s\n",
1543 __func__, ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001544 ch->sdio_al_dev->is_err = true;
1545 return ret;
1546 }
1547
1548 return ret;
1549}
1550
1551static int sdio_al_bootloader_completed(void)
1552{
1553 int i;
1554
1555 pr_debug(MODULE_NAME ":sdio_al_bootloader_completed was called\n");
1556
1557 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
1558 struct sdio_al_device *dev = NULL;
1559 if (sdio_al->devices[i] == NULL)
1560 continue;
1561 dev = sdio_al->devices[i];
1562 dev->bootloader_done = 1;
1563 wake_up(&dev->wait_mbox);
1564 }
1565
1566 return 0;
1567}
1568
1569static int sdio_al_wait_for_bootloader_comp(struct sdio_al_device *sdio_al_dev)
1570{
1571 int ret = 0;
1572
1573 struct sdio_func *func1;
1574
1575 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1576 return -ENODEV;
1577 func1 = sdio_al_dev->card->sdio_func[0];
1578
1579 sdio_claim_host(func1);
1580 /*
1581 * Enable function 0 interrupt mask to allow 9k to raise this interrupt
1582 * in power-up. When sdio_downloader will notify its completion
1583 * we will poll on this interrupt to wait for 9k power-up
1584 */
1585 ret = enable_mask_irq(sdio_al_dev, 0, 1, 0);
1586 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001587 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1588 ": Enable_mask_irq for card %d failed, "
1589 "ret=%d\n",
1590 sdio_al_dev->card->host->index, ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001591 sdio_release_host(func1);
1592 return ret;
1593 }
1594
1595 sdio_release_host(func1);
1596
1597 /*
1598 * Start bootloader worker that will wait for the bootloader
1599 * completion
1600 */
1601 sdio_al_dev->boot_work.sdio_al_dev = sdio_al_dev;
1602 INIT_WORK(&sdio_al_dev->boot_work.work, boot_worker);
1603 sdio_al_dev->bootloader_done = 0;
1604 queue_work(sdio_al_dev->workqueue, &sdio_al_dev->boot_work.work);
1605
1606 return 0;
1607}
1608
1609static int sdio_al_bootloader_setup(void)
1610{
1611 int ret = 0;
1612 struct sdio_func *func1;
1613 struct sdio_al_device *bootloader_dev = sdio_al->bootloader_dev;
1614
1615 if (bootloader_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001616 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
1617 ": No bootloader_dev\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001618 return -ENODEV;
1619 }
1620
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001621 if (bootloader_dev->flashless_boot_on) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001622 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":Already "
1623 "in boot process.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001624 return 0;
1625 }
1626
1627 func1 = bootloader_dev->card->sdio_func[0];
1628 if (!func1) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001629 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
1630 ": %s: NULL func1\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001631 return -ENODEV;
1632 }
1633
1634 bootloader_dev->sdioc_boot_sw_header
1635 = kzalloc(sizeof(*bootloader_dev->sdioc_boot_sw_header),
1636 GFP_KERNEL);
1637 if (bootloader_dev->sdioc_boot_sw_header == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001638 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":fail to "
1639 "allocate sdioc boot sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001640 return -ENOMEM;
1641 }
1642
1643 sdio_claim_host(func1);
1644
1645 ret = sdio_memcpy_fromio(func1,
1646 bootloader_dev->sdioc_boot_sw_header,
1647 SDIOC_SW_HEADER_ADDR,
1648 sizeof(struct peer_sdioc_boot_sw_header));
1649 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001650 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":fail to "
1651 "read sdioc boot sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001652 sdio_release_host(func1);
1653 goto exit_err;
1654 }
1655
1656 if (bootloader_dev->sdioc_boot_sw_header->signature !=
1657 (u32) PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001658 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":invalid "
1659 "mailbox signature 0x%x.\n",
1660 bootloader_dev->sdioc_boot_sw_header->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001661 sdio_release_host(func1);
1662 ret = -EINVAL;
1663 goto exit_err;
1664 }
1665
1666 /* Upper byte has to be equal - no backward compatibility for unequal */
1667 if ((bootloader_dev->sdioc_boot_sw_header->version >> 16) !=
1668 (sdio_al->pdata->peer_sdioc_boot_version_major)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001669 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ": HOST(0x%x)"
1670 " and CLIENT(0x%x) SDIO_AL BOOT VERSION don't match\n",
1671 ((sdio_al->pdata->peer_sdioc_boot_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001672 sdio_al->pdata->peer_sdioc_boot_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001673 bootloader_dev->sdioc_boot_sw_header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001674 sdio_release_host(func1);
1675 ret = -EIO;
1676 goto exit_err;
1677 }
1678
Krishna Kondaa7af6062011-09-01 18:34:38 -07001679 sdio_al_logi(bootloader_dev->dev_log, MODULE_NAME ": SDIOC BOOT SW "
1680 "version 0x%x\n",
1681 bootloader_dev->sdioc_boot_sw_header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001682
1683 bootloader_dev->flashless_boot_on = true;
1684
1685 sdio_release_host(func1);
1686
1687 ret = sdio_al_wait_for_bootloader_comp(bootloader_dev);
1688 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001689 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
1690 ": sdio_al_wait_for_bootloader_comp failed, "
1691 "err=%d\n", ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001692 goto exit_err;
1693 }
1694
1695 ret = sdio_downloader_setup(bootloader_dev->card, 1,
1696 bootloader_dev->sdioc_boot_sw_header->boot_ch_num,
1697 sdio_al_bootloader_completed);
1698
1699 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001700 sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
1701 ": sdio_downloader_setup failed, err=%d\n", ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001702 goto exit_err;
1703 }
1704
Krishna Kondaa7af6062011-09-01 18:34:38 -07001705 sdio_al_logi(bootloader_dev->dev_log, MODULE_NAME ":In Flashless boot,"
1706 " waiting for its completion\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001707
1708
1709exit_err:
Krishna Kondaa7af6062011-09-01 18:34:38 -07001710 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":free "
1711 "sdioc_boot_sw_header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001712 kfree(bootloader_dev->sdioc_boot_sw_header);
1713 bootloader_dev->sdioc_boot_sw_header = NULL;
1714 bootloader_dev = NULL;
1715
1716 return ret;
1717}
1718
1719
1720/**
1721 * Read SDIO-Client software header
1722 *
1723 */
1724static int read_sdioc_software_header(struct sdio_al_device *sdio_al_dev,
1725 struct peer_sdioc_sw_header *header)
1726{
1727 int ret;
1728 int i;
1729 int test_version = 0;
1730 int sdioc_test_version = 0;
1731
1732 pr_debug(MODULE_NAME ":reading sdioc sw header.\n");
1733
1734 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1735 return -ENODEV;
1736
1737 ret = sdio_memcpy_fromio(sdio_al_dev->card->sdio_func[0], header,
1738 SDIOC_SW_HEADER_ADDR, sizeof(*header));
1739 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001740 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
1741 "sdioc sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001742 goto exit_err;
1743 }
1744
1745 if (header->signature == (u32)PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001746 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW "
1747 "unittest signature. 0x%x\n",
1748 header->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001749 sdio_al->unittest_mode = true;
1750 /* Verify test code compatibility with the modem */
1751 sdioc_test_version = (header->version & 0xFF00) >> 8;
1752 test_version = sdio_al->pdata->peer_sdioc_version_minor >> 8;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001753 if (test_version != sdioc_test_version) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001754 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1755 ": HOST(0x%x) and CLIENT(0x%x) "
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001756 "testing VERSION don't match\n",
Krishna Kondaa7af6062011-09-01 18:34:38 -07001757 test_version,
1758 sdioc_test_version);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001759 msleep(500);
1760 BUG();
1761 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001762 }
1763
1764 if ((header->signature != (u32) PEER_SDIOC_SW_MAILBOX_SIGNATURE) &&
1765 (header->signature != (u32) PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001766 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW "
1767 "invalid signature. 0x%x\n", header->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001768 goto exit_err;
1769 }
1770 /* Upper byte has to be equal - no backward compatibility for unequal */
1771 sdio_al->sdioc_major = header->version >> 16;
1772 if (sdio_al->pdata->allow_sdioc_version_major_2) {
1773 if ((sdio_al->sdioc_major !=
1774 sdio_al->pdata->peer_sdioc_version_major) &&
1775 (sdio_al->sdioc_major != PEER_SDIOC_OLD_VERSION_MAJOR)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001776 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1777 ": HOST(0x%x) and CLIENT(0x%x) "
1778 "SDIO_AL VERSION don't match\n",
1779 ((sdio_al->pdata->peer_sdioc_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001780 sdio_al->pdata->peer_sdioc_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001781 header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001782 goto exit_err;
1783 }
1784 } else {
1785 if (sdio_al->sdioc_major !=
1786 sdio_al->pdata->peer_sdioc_version_major) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001787 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
1788 ": HOST(0x%x) and CLIENT(0x%x) "
1789 "SDIO_AL VERSION don't match\n",
1790 ((sdio_al->pdata->peer_sdioc_version_major<<16)+
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001791 sdio_al->pdata->peer_sdioc_version_minor),
Krishna Kondaa7af6062011-09-01 18:34:38 -07001792 header->version);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001793 goto exit_err;
1794 }
1795 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001796 sdio_al_dev->ch_close_supported = (header->version & 0x000F) >=
1797 (sdio_al->pdata->peer_sdioc_version_minor & 0xF);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001798
Krishna Kondaa7af6062011-09-01 18:34:38 -07001799 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW version 0x%x,"
1800 " sdio_al major 0x%x minor 0x%x\n", header->version,
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001801 sdio_al->sdioc_major,
1802 sdio_al->pdata->peer_sdioc_version_minor);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001803
1804 sdio_al_dev->flashless_boot_on = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001805 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
1806 struct sdio_channel *ch = &sdio_al_dev->channel[i];
1807
1808 /* Set default values */
1809 ch->read_threshold = DEFAULT_READ_THRESHOLD;
1810 ch->write_threshold = DEFAULT_WRITE_THRESHOLD;
1811 ch->min_write_avail = DEFAULT_MIN_WRITE_THRESHOLD;
1812 ch->is_packet_mode = true;
1813 ch->peer_tx_buf_size = DEFAULT_PEER_TX_BUF_SIZE;
1814 ch->poll_delay_msec = 0;
1815
1816 ch->num = i;
1817
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001818 ch->func = sdio_al_dev->card->sdio_func[ch->num+1];
1819 ch->rx_pipe_index = ch->num*2;
1820 ch->tx_pipe_index = ch->num*2+1;
1821
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001822 memset(ch->name, 0, sizeof(ch->name));
1823
1824 if (header->channel_names[i][0]) {
1825 memcpy(ch->name, SDIO_PREFIX,
1826 strlen(SDIO_PREFIX));
1827 memcpy(ch->name + strlen(SDIO_PREFIX),
1828 header->channel_names[i],
1829 PEER_CHANNEL_NAME_SIZE);
1830
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001831 ch->state = SDIO_CHANNEL_STATE_IDLE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001832 ch->sdio_al_dev = sdio_al_dev;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001833 } else {
1834 ch->state = SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001835 }
1836
Krishna Kondaa7af6062011-09-01 18:34:38 -07001837 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":Channel=%s, "
1838 "state=%d\n", ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001839 }
1840
1841 return 0;
1842
1843exit_err:
1844 sdio_al_get_into_err_state(sdio_al_dev);
1845 memset(header, 0, sizeof(*header));
1846
1847 return -EIO;
1848}
1849
1850/**
1851 * Read SDIO-Client channel configuration
1852 *
1853 */
1854static int read_sdioc_channel_config(struct sdio_channel *ch)
1855{
1856 int ret;
1857 struct peer_sdioc_sw_mailbox *sw_mailbox = NULL;
1858 struct peer_sdioc_channel_config *ch_config = NULL;
1859 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
1860
1861 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001862 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
1863 " for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001864 return -EINVAL;
1865 }
1866
1867 if (sdio_al_dev->sdioc_sw_header->version == 0)
1868 return -1;
1869
1870 pr_debug(MODULE_NAME ":reading sw mailbox %s channel.\n", ch->name);
1871
1872 sw_mailbox = kzalloc(sizeof(*sw_mailbox), GFP_KERNEL);
1873 if (sw_mailbox == NULL)
1874 return -ENOMEM;
1875
1876 ret = sdio_memcpy_fromio(ch->func, sw_mailbox,
1877 SDIOC_SW_MAILBOX_ADDR, sizeof(*sw_mailbox));
1878 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001879 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
1880 "sw mailbox.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001881 goto exit_err;
1882 }
1883
1884 ch_config = &sw_mailbox->ch_config[ch->num];
1885 memcpy(&ch->ch_config, ch_config,
1886 sizeof(struct peer_sdioc_channel_config));
1887
1888 if (!ch_config->is_ready) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07001889 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sw mailbox "
1890 "channel not ready.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001891 goto exit_err;
1892 }
1893
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001894 /* Aggregation up to 90% of the maximum size */
1895 ch->read_threshold = (ch_config->max_rx_threshold * 9) / 10;
1896 /* Threshold on 50% of the maximum size , sdioc uses double-buffer */
1897 ch->write_threshold = (ch_config->max_tx_threshold * 5) / 10;
Maya Erez8ed0a9a2011-07-19 14:46:53 +03001898 ch->threshold_change_cnt = ch->ch_config.max_rx_threshold -
1899 ch->read_threshold + THRESHOLD_CHANGE_EXTRA_BYTES;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001900
1901 ch->def_read_threshold = ch->read_threshold;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001902 ch->is_packet_mode = ch_config->is_packet_mode;
1903 if (!ch->is_packet_mode) {
1904 ch->poll_delay_msec = DEFAULT_POLL_DELAY_NOPACKET_MSEC;
1905 ch->min_write_avail = DEFAULT_MIN_WRITE_THRESHOLD_STREAMING;
1906 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001907 /* The max_packet_size is set by the modem in version 3 and on */
1908 if (sdio_al->sdioc_major > PEER_SDIOC_OLD_VERSION_MAJOR)
1909 ch->min_write_avail = ch_config->max_packet_size;
1910
1911 if (ch->min_write_avail > ch->write_threshold)
1912 ch->min_write_avail = ch->write_threshold;
1913
Krishna Kondaa7af6062011-09-01 18:34:38 -07001914 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":ch %s "
1915 "read_threshold=%d, write_threshold=%d,"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03001916 " min_write_avail=%d, max_rx_threshold=%d,"
1917 " max_tx_threshold=%d\n", ch->name, ch->read_threshold,
1918 ch->write_threshold, ch->min_write_avail,
1919 ch_config->max_rx_threshold,
1920 ch_config->max_tx_threshold);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001921
1922 ch->peer_tx_buf_size = ch_config->tx_buf_size;
1923
1924 kfree(sw_mailbox);
1925
1926 return 0;
1927
1928exit_err:
Krishna Kondaa7af6062011-09-01 18:34:38 -07001929 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":Reading SW Mailbox "
1930 "error.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001931 kfree(sw_mailbox);
1932
1933 return -1;
1934}
1935
1936
1937/**
1938 * Enable/Disable EOT interrupt of a pipe.
1939 *
1940 */
1941static int enable_eot_interrupt(struct sdio_al_device *sdio_al_dev,
1942 int pipe_index, int enable)
1943{
1944 int ret = 0;
1945 struct sdio_func *func1;
1946 u32 mask;
1947 u32 pipe_mask;
1948 u32 addr;
1949
1950 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1951 return -ENODEV;
1952 func1 = sdio_al_dev->card->sdio_func[0];
1953
1954 if (pipe_index < 8) {
1955 addr = PIPES_0_7_IRQ_MASK_ADDR;
1956 pipe_mask = (1<<pipe_index);
1957 } else {
1958 addr = PIPES_8_15_IRQ_MASK_ADDR;
1959 pipe_mask = (1<<(pipe_index-8));
1960 }
1961
1962 mask = sdio_readl(func1, addr, &ret);
1963 if (ret) {
1964 pr_debug(MODULE_NAME ":enable_eot_interrupt fail\n");
1965 goto exit_err;
1966 }
1967
1968 if (enable)
1969 mask &= (~pipe_mask); /* 0 = enable */
1970 else
1971 mask |= (pipe_mask); /* 1 = disable */
1972
1973 sdio_writel(func1, mask, addr, &ret);
1974
1975exit_err:
1976 return ret;
1977}
1978
1979
1980/**
1981 * Enable/Disable mask interrupt of a function.
1982 *
1983 */
1984static int enable_mask_irq(struct sdio_al_device *sdio_al_dev,
1985 int func_num, int enable, u8 bit_offset)
1986{
1987 int ret = 0;
1988 struct sdio_func *func1 = NULL;
1989 u32 mask = 0;
1990 u32 func_mask = 0;
1991 u32 addr = 0;
1992 u32 offset = 0;
1993
1994 if (sdio_al_verify_dev(sdio_al_dev, __func__))
1995 return -ENODEV;
1996 func1 = sdio_al_dev->card->sdio_func[0];
1997
1998 if (func_num < 4) {
1999 addr = FUNC_1_4_MASK_IRQ_ADDR;
2000 offset = func_num * 8 + bit_offset;
2001 } else {
2002 addr = FUNC_5_7_MASK_IRQ_ADDR;
2003 offset = (func_num - 4) * 8 + bit_offset;
2004 }
2005
2006 func_mask = 1<<offset;
2007
2008 mask = sdio_readl(func1, addr, &ret);
2009 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002010 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2011 "enable_mask_irq fail\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002012 goto exit_err;
2013 }
2014
2015 if (enable)
2016 mask &= (~func_mask); /* 0 = enable */
2017 else
2018 mask |= (func_mask); /* 1 = disable */
2019
2020 pr_debug(MODULE_NAME ":enable_mask_irq, writing mask = 0x%x\n", mask);
2021
2022 sdio_writel(func1, mask, addr, &ret);
2023
2024exit_err:
2025 return ret;
2026}
2027
2028/**
2029 * Enable/Disable Threshold interrupt of a pipe.
2030 *
2031 */
2032static int enable_threshold_interrupt(struct sdio_al_device *sdio_al_dev,
2033 int pipe_index, int enable)
2034{
2035 int ret = 0;
2036 struct sdio_func *func1;
2037 u32 mask;
2038 u32 pipe_mask;
2039 u32 addr;
2040
2041 if (sdio_al_verify_dev(sdio_al_dev, __func__))
2042 return -ENODEV;
2043 func1 = sdio_al_dev->card->sdio_func[0];
2044
2045 if (pipe_index < 8) {
2046 addr = PIPES_0_7_IRQ_MASK_ADDR;
2047 pipe_mask = (1<<pipe_index);
2048 } else {
2049 addr = PIPES_8_15_IRQ_MASK_ADDR;
2050 pipe_mask = (1<<(pipe_index-8));
2051 }
2052
2053 mask = sdio_readl(func1, addr, &ret);
2054 if (ret) {
2055 pr_debug(MODULE_NAME ":enable_threshold_interrupt fail\n");
2056 goto exit_err;
2057 }
2058
2059 pipe_mask = pipe_mask<<8; /* Threshold bits 8..15 */
2060 if (enable)
2061 mask &= (~pipe_mask); /* 0 = enable */
2062 else
2063 mask |= (pipe_mask); /* 1 = disable */
2064
2065 sdio_writel(func1, mask, addr, &ret);
2066
2067exit_err:
2068 return ret;
2069}
2070
2071/**
2072 * Set the threshold to trigger interrupt from SDIO-Card on
2073 * pipe available bytes.
2074 *
2075 */
2076static int set_pipe_threshold(struct sdio_al_device *sdio_al_dev,
2077 int pipe_index, int threshold)
2078{
2079 int ret = 0;
2080 struct sdio_func *func1;
2081
2082 if (sdio_al_verify_dev(sdio_al_dev, __func__))
2083 return -ENODEV;
2084 func1 = sdio_al_dev->card->sdio_func[0];
2085
2086 sdio_writel(func1, threshold,
2087 PIPES_THRESHOLD_ADDR+pipe_index*4, &ret);
2088 if (ret)
Krishna Kondaa7af6062011-09-01 18:34:38 -07002089 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2090 "set_pipe_threshold err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002091
2092 return ret;
2093}
2094
2095/**
2096 * Enable func w/ retries
2097 *
2098 */
2099static int sdio_al_enable_func_retry(struct sdio_func *func, const char *name)
2100{
2101 int ret, i;
2102 for (i = 0; i < 200; i++) {
2103 ret = sdio_enable_func(func);
2104 if (ret) {
2105 pr_debug(MODULE_NAME ":retry enable %s func#%d "
2106 "ret=%d\n",
2107 name, func->num, ret);
2108 msleep(10);
2109 } else
2110 break;
2111 }
2112
2113 return ret;
2114}
2115
2116/**
2117 * Open Channel
2118 *
2119 * 1. Init Channel Context.
2120 * 2. Init the Channel SDIO-Function.
2121 * 3. Init the Channel Pipes on Mailbox.
2122 */
2123static int open_channel(struct sdio_channel *ch)
2124{
2125 int ret = 0;
2126 struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
2127
2128 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002129 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL "
2130 "sdio_al_dev for channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002131 return -EINVAL;
2132 }
2133
2134 /* Init channel Context */
2135 /** Func#1 is reserved for mailbox */
2136 ch->func = sdio_al_dev->card->sdio_func[ch->num+1];
2137 ch->rx_pipe_index = ch->num*2;
2138 ch->tx_pipe_index = ch->num*2+1;
2139 ch->signature = SDIO_AL_SIGNATURE;
2140
2141 ch->total_rx_bytes = 0;
2142 ch->total_tx_bytes = 0;
2143
2144 ch->write_avail = 0;
2145 ch->read_avail = 0;
2146 ch->rx_pending_bytes = 0;
2147
2148 mutex_init(&ch->ch_lock);
2149
2150 pr_debug(MODULE_NAME ":open_channel %s func#%d\n",
2151 ch->name, ch->func->num);
2152
2153 INIT_LIST_HEAD(&(ch->rx_size_list_head));
2154
2155 /* Init SDIO Function */
2156 ret = sdio_al_enable_func_retry(ch->func, ch->name);
2157 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002158 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2159 "sdio_enable_func() err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002160 goto exit_err;
2161 }
2162
2163 /* Note: Patch Func CIS tuple issue */
2164 ret = sdio_set_block_size(ch->func, SDIO_AL_BLOCK_SIZE);
2165 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002166 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2167 "sdio_set_block_size()failed, err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002168 goto exit_err;
2169 }
2170
2171 ch->func->max_blksize = SDIO_AL_BLOCK_SIZE;
2172
2173 sdio_set_drvdata(ch->func, ch);
2174
2175 /* Get channel parameters from the peer SDIO-Client */
2176 read_sdioc_channel_config(ch);
2177
2178 /* Set Pipes Threshold on Mailbox */
2179 ret = set_pipe_threshold(sdio_al_dev,
2180 ch->rx_pipe_index, ch->read_threshold);
2181 if (ret)
2182 goto exit_err;
2183 ret = set_pipe_threshold(sdio_al_dev,
2184 ch->tx_pipe_index, ch->write_threshold);
2185 if (ret)
2186 goto exit_err;
2187
2188 /* Set flag before interrupts are enabled to allow notify */
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002189 ch->state = SDIO_CHANNEL_STATE_OPEN;
2190 pr_debug(MODULE_NAME ":channel %s is in OPEN state now\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002191
2192 sdio_al_dev->poll_delay_msec = get_min_poll_time_msec(sdio_al_dev);
2193
2194 /* lpm mechanism lives under the assumption there is always a timer */
2195 /* Check if need to start the timer */
2196 if ((sdio_al_dev->poll_delay_msec) &&
2197 (sdio_al_dev->is_timer_initialized == false)) {
2198
2199 init_timer(&sdio_al_dev->timer);
2200 sdio_al_dev->timer.data = (unsigned long) sdio_al_dev;
2201 sdio_al_dev->timer.function = sdio_al_timer_handler;
2202 sdio_al_dev->timer.expires = jiffies +
2203 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2204 add_timer(&sdio_al_dev->timer);
2205 sdio_al_dev->is_timer_initialized = true;
2206 }
2207
2208 /* Enable Pipes Interrupts */
2209 enable_eot_interrupt(sdio_al_dev, ch->rx_pipe_index, true);
2210 enable_eot_interrupt(sdio_al_dev, ch->tx_pipe_index, true);
2211
2212 enable_threshold_interrupt(sdio_al_dev, ch->rx_pipe_index, true);
2213 enable_threshold_interrupt(sdio_al_dev, ch->tx_pipe_index, true);
2214
2215exit_err:
2216
2217 return ret;
2218}
2219
2220/**
2221 * Ask the worker to read the mailbox.
2222 */
2223static void ask_reading_mailbox(struct sdio_al_device *sdio_al_dev)
2224{
2225 if (!sdio_al_dev->ask_mbox) {
2226 pr_debug(MODULE_NAME ":ask_reading_mailbox for card %d\n",
2227 sdio_al_dev->card->host->index);
2228 sdio_al_dev->ask_mbox = true;
2229 wake_up(&sdio_al_dev->wait_mbox);
2230 }
2231}
2232
2233/**
2234 * Start the timer
2235 */
2236static void start_timer(struct sdio_al_device *sdio_al_dev)
2237{
2238 if ((sdio_al_dev->poll_delay_msec) &&
2239 (sdio_al_dev->state == CARD_INSERTED)) {
2240 sdio_al_dev->timer.expires = jiffies +
2241 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2242 add_timer(&sdio_al_dev->timer);
2243 }
2244}
2245
2246/**
2247 * Restart(postpone) the already working timer
2248 */
2249static void restart_timer(struct sdio_al_device *sdio_al_dev)
2250{
2251 if ((sdio_al_dev->poll_delay_msec) &&
2252 (sdio_al_dev->state == CARD_INSERTED)) {
2253 ulong expires = jiffies +
2254 msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
2255 mod_timer(&sdio_al_dev->timer, expires);
2256 }
2257}
2258
2259/**
2260 * Do the wakup sequence.
2261 * This function should be called after claiming the host!
2262 * The caller is responsible for releasing the host.
2263 *
2264 * Wake up sequence
2265 * 1. Get lock
2266 * 2. Enable wake up function if needed
2267 * 3. Mark NOT OK to sleep and write it
2268 * 4. Restore default thresholds
2269 * 5. Start the mailbox and inactivity timer again
2270 */
2271static int sdio_al_wake_up(struct sdio_al_device *sdio_al_dev,
Maya Erez7b1ebd22011-08-20 20:53:24 +03002272 u32 not_from_int, struct sdio_channel *ch)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002273{
Maya Erez8ed0a9a2011-07-19 14:46:53 +03002274 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002275 struct sdio_func *wk_func =
2276 sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
2277 unsigned long time_to_wait;
2278 struct mmc_host *host = wk_func->card->host;
2279
2280 if (sdio_al_dev->is_err) {
2281 SDIO_AL_ERR(__func__);
2282 return -ENODEV;
2283 }
2284
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002285 if (!sdio_al_dev->is_ok_to_sleep) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002286 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":card %d already"
2287 " awake, no need to wake up\n",
2288 sdio_al_dev->card->host->index);
2289 return 0;
2290 }
2291
2292 if (!sdio_al_dev->is_ok_to_sleep) {
2293 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":card %d "
2294 "already awake, no need to wake up\n",
2295 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002296 return 0;
2297 }
Maya Erez7b1ebd22011-08-20 20:53:24 +03002298
2299 /* Wake up sequence */
2300 if (not_from_int) {
2301 if (ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002302 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up"
2303 " card %d (not by interrupt), ch %s",
2304 sdio_al_dev->card->host->index,
2305 ch->name);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002306 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002307 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up"
2308 " card %d (not by interrupt)",
2309 sdio_al_dev->card->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002310 }
2311 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002312 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up card "
2313 "%d by interrupt",
2314 sdio_al_dev->card->host->index);
Maya Erez7b1ebd22011-08-20 20:53:24 +03002315 sdio_al_dev->print_after_interrupt = 1;
2316 }
2317
Yaniv Gardi3e327762011-07-27 11:11:04 +03002318 sdio_al_vote_for_sleep(sdio_al_dev, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002319
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002320 msmsdcc_lpm_disable(host);
2321 msmsdcc_set_pwrsave(sdio_al_dev->card->host, 0);
2322 /* Poll the GPIO */
2323 time_to_wait = jiffies + msecs_to_jiffies(1000);
2324 while (time_before(jiffies, time_to_wait)) {
2325 if (sdio_al->pdata->get_mdm2ap_status())
2326 break;
2327 udelay(TIME_TO_WAIT_US);
2328 }
Yaniv Gardi3e327762011-07-27 11:11:04 +03002329
Maya Erez7b1ebd22011-08-20 20:53:24 +03002330 pr_debug(MODULE_NAME ":GPIO mdm2ap_status=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002331 sdio_al->pdata->get_mdm2ap_status());
2332
2333 /* Here get_mdm2ap_status() returning 0 is not an error condition */
2334 if (sdio_al->pdata->get_mdm2ap_status() == 0)
Krishna Kondaa7af6062011-09-01 18:34:38 -07002335 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": "
2336 "get_mdm2ap_status() is 0\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002337
2338 /* Enable Wake up Function */
2339 ret = sdio_al_enable_func_retry(wk_func, "wakeup func");
2340 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002341 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2342 "sdio_enable_func() err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002343 goto error_exit;
2344 }
2345 /* Mark NOT OK_TOSLEEP */
2346 sdio_al_dev->is_ok_to_sleep = 0;
2347 ret = write_lpm_info(sdio_al_dev);
2348 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002349 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2350 "write_lpm_info() failed, err=%d\n", -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002351 sdio_al_dev->is_ok_to_sleep = 1;
2352 sdio_disable_func(wk_func);
2353 goto error_exit;
2354 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002355 sdio_disable_func(wk_func);
2356
2357 /* Start the timer again*/
2358 restart_inactive_time(sdio_al_dev);
2359 sdio_al_dev->poll_delay_msec = get_min_poll_time_msec(sdio_al_dev);
2360 start_timer(sdio_al_dev);
2361
Krishna Kondaa7af6062011-09-01 18:34:38 -07002362 LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME "Finished Wake up sequence"
2363 " for card %d", sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002364
2365 msmsdcc_set_pwrsave(sdio_al_dev->card->host, 1);
2366 pr_debug(MODULE_NAME ":Turn clock off\n");
2367
2368 return ret;
2369error_exit:
2370 sdio_al_vote_for_sleep(sdio_al_dev, 1);
2371 msmsdcc_set_pwrsave(sdio_al_dev->card->host, 1);
2372 WARN_ON(ret);
2373 sdio_al_get_into_err_state(sdio_al_dev);
2374 return ret;
2375}
2376
2377
2378/**
2379 * SDIO Function Interrupt handler.
2380 *
2381 * Interrupt shall be triggered by SDIO-Client when:
2382 * 1. End-Of-Transfer (EOT) detected in packet mode.
2383 * 2. Bytes-available reached the threshold.
2384 *
2385 * Reading the mailbox clears the EOT/Threshold interrupt
2386 * source.
2387 * The interrupt source should be cleared before this ISR
2388 * returns. This ISR is called from IRQ Thread and not
2389 * interrupt, so it may sleep.
2390 *
2391 */
2392static void sdio_func_irq(struct sdio_func *func)
2393{
2394 struct sdio_al_device *sdio_al_dev = sdio_get_drvdata(func);
2395
2396 pr_debug(MODULE_NAME ":start %s.\n", __func__);
2397
2398 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002399 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
2400 " for card %d\n", func->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002401 return;
2402 }
2403
2404 if (sdio_al_dev->is_ok_to_sleep)
Maya Erez7b1ebd22011-08-20 20:53:24 +03002405 sdio_al_wake_up(sdio_al_dev, 0, NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002406 else
2407 restart_timer(sdio_al_dev);
2408
2409 read_mailbox(sdio_al_dev, true);
2410
2411 pr_debug(MODULE_NAME ":end %s.\n", __func__);
2412}
2413
2414/**
2415 * Timer Expire Handler
2416 *
2417 */
2418static void sdio_al_timer_handler(unsigned long data)
2419{
2420 struct sdio_al_device *sdio_al_dev = (struct sdio_al_device *)data;
2421 if (sdio_al_dev == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002422 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": NULL "
2423 "sdio_al_dev for data %lu\n", data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002424 return;
2425 }
2426 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002427 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": sdio_al_dev "
2428 "is in invalid state %d\n", sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002429 return;
2430 }
2431 pr_debug(MODULE_NAME " Timer Expired\n");
2432
2433 ask_reading_mailbox(sdio_al_dev);
2434
2435 restart_timer(sdio_al_dev);
2436}
2437
2438/**
2439 * Driver Setup.
2440 *
2441 */
2442static int sdio_al_setup(struct sdio_al_device *sdio_al_dev)
2443{
2444 int ret = 0;
2445 struct mmc_card *card = sdio_al_dev->card;
2446 struct sdio_func *func1 = NULL;
2447 int i = 0;
2448 int fn = 0;
2449
2450 if (card == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002451 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
2452 "sdio_al_setup: No Card detected\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002453 return -ENODEV;
2454 }
2455
2456
Krishna Kondaa7af6062011-09-01 18:34:38 -07002457 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_setup for "
2458 "card %d\n", sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002459
2460 func1 = card->sdio_func[0];
2461
2462 ret = sdio_al->pdata->config_mdm2ap_status(1);
2463 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002464 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME "Could not "
2465 "request GPIO\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002466 return ret;
2467 }
2468
2469 INIT_WORK(&sdio_al_dev->sdio_al_work.work, worker);
2470 /* disable all pipes interrupts before claim irq.
2471 since all are enabled by default. */
2472 for (i = 0 ; i < SDIO_AL_MAX_PIPES; i++) {
2473 enable_eot_interrupt(sdio_al_dev, i, false);
2474 enable_threshold_interrupt(sdio_al_dev, i, false);
2475 }
2476
2477 /* Disable all SDIO Functions before claim irq. */
2478 for (fn = 1 ; fn <= card->sdio_funcs; fn++)
2479 sdio_disable_func(card->sdio_func[fn-1]);
2480
2481 sdio_set_drvdata(func1, sdio_al_dev);
Krishna Kondaa7af6062011-09-01 18:34:38 -07002482 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":claim IRQ for card "
2483 "%d\n", card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002484
2485 ret = sdio_claim_irq(func1, sdio_func_irq);
2486 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002487 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to claim"
2488 " IRQ for card %d\n",
2489 card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002490 goto exit_err;
2491 }
2492
2493 sdio_al_dev->is_ready = true;
2494
2495 /* Start worker before interrupt might happen */
2496 queue_work(sdio_al_dev->workqueue, &sdio_al_dev->sdio_al_work.work);
2497
2498 start_inactive_time(sdio_al_dev);
2499
2500 pr_debug(MODULE_NAME ":Ready.\n");
2501
2502 return 0;
2503
2504exit_err:
2505 sdio_release_host(func1);
Krishna Kondaa7af6062011-09-01 18:34:38 -07002506 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Setup Failure.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002507
2508 return ret;
2509}
2510
2511/**
2512 * Driver Tear-Down.
2513 *
2514 */
2515static void sdio_al_tear_down(void)
2516{
2517 int i;
2518 struct sdio_al_device *sdio_al_dev = NULL;
2519 struct sdio_func *func1;
2520
2521 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
2522 if (sdio_al->devices[i] == NULL)
2523 continue;
2524 sdio_al_dev = sdio_al->devices[i];
2525
2526 if (sdio_al_dev->is_ready) {
2527 sdio_al_dev->is_ready = false; /* Flag worker to exit */
2528 sdio_al_dev->ask_mbox = false;
2529 ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
2530 /* allow gracefully exit of the worker thread */
2531 msleep(100);
2532
2533 flush_workqueue(sdio_al_dev->workqueue);
2534 destroy_workqueue(sdio_al_dev->workqueue);
2535
2536 sdio_al_vote_for_sleep(sdio_al_dev, 1);
2537
2538 if (sdio_al_verify_func1(sdio_al_dev, __func__)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002539 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2540 ": %s: Invalid func1",
2541 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002542 return;
2543 }
2544 func1 = sdio_al_dev->card->sdio_func[0];
2545
2546 sdio_claim_host(func1);
2547 sdio_release_irq(func1);
2548 sdio_disable_func(func1);
2549 sdio_release_host(func1);
2550 }
2551 }
2552
2553 sdio_al->pdata->config_mdm2ap_status(0);
2554}
2555
2556/**
2557 * Find channel by name.
2558 *
2559 */
2560static struct sdio_channel *find_channel_by_name(const char *name)
2561{
2562 struct sdio_channel *ch = NULL;
2563 int i, j;
2564 struct sdio_al_device *sdio_al_dev = NULL;
2565
2566 for (j = 0; j < MAX_NUM_OF_SDIO_DEVICES; ++j) {
2567 if (sdio_al->devices[j] == NULL)
2568 continue;
2569 sdio_al_dev = sdio_al->devices[j];
2570 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002571 if (sdio_al_dev->channel[i].state ==
2572 SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002573 continue;
2574 if (strcmp(sdio_al_dev->channel[i].name, name) == 0) {
2575 ch = &sdio_al_dev->channel[i];
2576 break;
2577 }
2578 }
2579 if (ch != NULL)
2580 break;
2581 }
2582
2583 return ch;
2584}
2585
2586/**
2587 * Find the minimal poll time.
2588 *
2589 */
2590static int get_min_poll_time_msec(struct sdio_al_device *sdio_sl_dev)
2591{
2592 int i;
2593 int poll_delay_msec = 0x0FFFFFFF;
2594
2595 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++)
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002596 if ((sdio_sl_dev->channel[i].state ==
2597 SDIO_CHANNEL_STATE_OPEN) &&
2598 (sdio_sl_dev->channel[i].poll_delay_msec > 0) &&
2599 (sdio_sl_dev->channel[i].poll_delay_msec < poll_delay_msec))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002600 poll_delay_msec =
2601 sdio_sl_dev->channel[i].poll_delay_msec;
2602
2603 if (poll_delay_msec == 0x0FFFFFFF)
2604 poll_delay_msec = SDIO_AL_POLL_TIME_NO_STREAMING;
2605
2606 pr_debug(MODULE_NAME ":poll delay time is %d msec\n", poll_delay_msec);
2607
2608 return poll_delay_msec;
2609}
2610
2611/**
2612 * Open SDIO Channel.
2613 *
2614 * Enable the channel.
2615 * Set the channel context.
2616 * Trigger reading the mailbox to check available bytes.
2617 *
2618 */
2619int sdio_open(const char *name, struct sdio_channel **ret_ch, void *priv,
2620 void (*notify)(void *priv, unsigned ch_event))
2621{
2622 int ret = 0;
2623 struct sdio_channel *ch = NULL;
2624 struct sdio_al_device *sdio_al_dev = NULL;
2625
2626 *ret_ch = NULL; /* default */
2627
2628 ch = find_channel_by_name(name);
2629 if (ch == NULL) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002630 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":Can't find "
2631 "channel name %s\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002632 return -EINVAL;
2633 }
2634
2635 sdio_al_dev = ch->sdio_al_dev;
2636 if (sdio_al_verify_dev(sdio_al_dev, __func__))
2637 return -ENODEV;
2638
2639 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
2640
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002641 if ((ch->state != SDIO_CHANNEL_STATE_IDLE) &&
2642 (ch->state != SDIO_CHANNEL_STATE_CLOSED)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002643 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Wrong ch %s "
2644 "state %d\n", name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002645 ret = -EPERM;
2646 goto exit_err;
2647 }
2648
2649 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002650 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2651 "sdio_al_dev is in invalid state %d\n",
2652 __func__, sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002653 ret = -ENODEV;
2654 goto exit_err;
2655 }
2656
2657 if (sdio_al_dev->is_err) {
2658 SDIO_AL_ERR(__func__);
2659 ret = -ENODEV;
2660 goto exit_err;
2661 }
2662
Maya Erez7b1ebd22011-08-20 20:53:24 +03002663 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002664 if (ret)
2665 goto exit_err;
2666
2667 ch->notify = notify;
2668 ch->priv = priv;
2669
2670 /* Note: Set caller returned context before interrupts are enabled */
2671 *ret_ch = ch;
2672
2673 ret = open_channel(ch);
2674 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002675 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_open %s "
2676 "err=%d\n", name, -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002677 goto exit_err;
2678 }
2679
Krishna Kondaa7af6062011-09-01 18:34:38 -07002680 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":sdio_open %s "
2681 "completed OK\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002682 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
2683 if (sdio_al->sdioc_major == PEER_SDIOC_OLD_VERSION_MAJOR) {
2684 if (!ch->is_packet_mode) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002685 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME
2686 ":setting channel %s as "
2687 "lpm_chan\n", name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002688 sdio_al_dev->lpm_chan = ch->num;
2689 }
2690 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002691 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": "
2692 "setting channel %s as lpm_chan\n",
2693 name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002694 sdio_al_dev->lpm_chan = ch->num;
2695 }
2696 }
2697
2698exit_err:
2699 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2700 return ret;
2701}
2702EXPORT_SYMBOL(sdio_open);
2703
2704/**
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002705 * Request peer operation
2706 * note: sanity checks of parameters done by caller
2707 * called under bus locked
2708 */
2709static int peer_set_operation(u32 opcode,
2710 struct sdio_al_device *sdio_al_dev,
2711 struct sdio_channel *ch)
2712{
2713 int ret;
2714 int offset;
2715 struct sdio_func *wk_func;
2716 u32 peer_operation;
2717 int loop_count = 0;
2718
2719 wk_func = sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
2720 if (!wk_func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002721 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: NULL "
2722 "wakeup func:%d\n", __func__,
2723 SDIO_AL_WAKEUP_FUNC);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002724 ret = -ENODEV;
2725 goto exit;
2726 }
2727 /* calculate offset of peer_operation field in sw mailbox struct */
2728 offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config) +
2729 sizeof(struct peer_sdioc_channel_config) * ch->num +
2730 offsetof(struct peer_sdioc_channel_config, peer_operation);
2731
Maya Erez7b1ebd22011-08-20 20:53:24 +03002732 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002733 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002734 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
2735 "wake up\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002736 goto exit;
2737 }
2738 /* request operation from MDM peer */
2739 peer_operation = PEER_OPERATION(opcode, PEER_OP_STATE_INIT);
2740 ret = sdio_memcpy_toio(ch->func, SDIOC_SW_MAILBOX_ADDR+offset,
2741 &peer_operation, sizeof(u32));
2742 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002743 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
2744 "request close operation\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002745 goto exit;
2746 }
2747 ret = sdio_al_enable_func_retry(wk_func, "wk_func");
2748 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002749 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to enable"
2750 " Func#%d\n", wk_func->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002751 goto exit;
2752 }
2753 pr_debug(MODULE_NAME ":%s: wk_func enabled on ch %s\n",
2754 __func__, ch->name);
2755 /* send "start" operation to MDM */
2756 peer_operation = PEER_OPERATION(opcode, PEER_OP_STATE_START);
2757 ret = sdio_memcpy_toio(ch->func, SDIOC_SW_MAILBOX_ADDR+offset,
2758 &peer_operation, sizeof(u32));
2759 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002760 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
2761 "send start close operation\n");
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002762 goto exit;
2763 }
2764 ret = sdio_disable_func(wk_func);
2765 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002766 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
2767 "disable Func#%d\n", wk_func->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002768 goto exit;
2769 }
2770 /* poll for peer operation ack */
2771 while (peer_operation != 0) {
2772 ret = sdio_memcpy_fromio(ch->func,
2773 &peer_operation,
2774 SDIOC_SW_MAILBOX_ADDR+offset,
2775 sizeof(u32));
2776 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002777 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2778 ":failed to request ack on close"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002779 " operation, loop_count = %d\n",
2780 loop_count);
2781 goto exit;
2782 }
2783 loop_count++;
2784 if (loop_count > 10) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002785 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2786 "peer_operation=0x%x wait loop"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002787 " %d on ch %s\n", __func__,
2788 peer_operation, loop_count, ch->name);
2789 }
2790 }
2791exit:
2792 return ret;
2793}
2794
2795/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002796 * Close SDIO Channel.
2797 *
2798 */
2799int sdio_close(struct sdio_channel *ch)
2800{
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002801 int ret;
2802 struct sdio_al_device *sdio_al_dev = NULL;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002803 int flush_len;
2804 ulong flush_expires;
2805
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002806 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002807 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
2808 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002809 return -ENODEV;
2810 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002811 sdio_al_dev = ch->sdio_al_dev;
2812 if (sdio_al_verify_dev(sdio_al_dev, __func__))
2813 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002814
Maya Erezc29f2912011-08-22 14:32:13 +03002815 if (!sdio_al_dev->ch_close_supported) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002816 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: Not "
2817 "supported by mdm, ch %s\n",
2818 __func__, ch->name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002819 return -ENOTSUPP;
2820 }
2821
2822 if (!ch->func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002823 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: NULL func"
2824 " on channel:%d\n", __func__, ch->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002825 return -ENODEV;
2826 }
2827 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
2828
2829 if (sdio_al_dev->is_err) {
2830 SDIO_AL_ERR(__func__);
2831 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2832 return -ENODEV;
2833 }
2834 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002835 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2836 "sdio_al_dev is in invalid state %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002837 __func__, sdio_al_dev->state);
2838 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2839 return -ENODEV;
2840 }
2841 ch->state = SDIO_CHANNEL_STATE_CLOSING;
2842 ret = peer_set_operation(PEER_OP_CODE_CLOSE, sdio_al_dev, ch);
2843 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002844 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2845 "peer_set_operation() failed: %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002846 __func__, ret);
2847 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2848 return -ENODEV;
2849 }
2850 /* udate poll time for opened channels */
2851 if (ch->poll_delay_msec > 0) {
2852 sdio_al_dev->poll_delay_msec =
2853 get_min_poll_time_msec(sdio_al_dev);
2854 }
2855 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2856
2857 flush_expires = jiffies +
2858 msecs_to_jiffies(SDIO_CLOSE_FLUSH_TIMEOUT_MSEC);
2859 /* flush rx packets of the channel */
2860 do {
2861 while (ch->read_avail > 0) {
2862 flush_len = ch->read_avail;
Maya Erez5795e0d2011-09-12 20:20:06 +03002863 ret = sdio_read_internal(ch, sdio_al_dev->rx_flush_buf,
2864 flush_len);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002865 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002866 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2867 ":%s failed to sdio_read: %d, ch %s\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002868 __func__, ret, ch->name);
2869 return ret;
2870 }
Yaniv Gardic4663632011-08-31 19:55:38 +03002871
2872 if (time_after(jiffies, flush_expires) != 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002873 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
2874 ":%s flush rx packets"
2875 " timeout: ch %s\n",
2876 __func__, ch->name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002877 sdio_al_get_into_err_state(sdio_al_dev);
2878 return -EBUSY;
2879 }
2880 }
2881 msleep(100);
2882 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002883 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
2884 "after sleep, invalid signature"
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002885 " 0x%x\n", __func__, ch->signature);
2886 return -ENODEV;
2887 }
Maya Erezd913f6c2011-09-07 13:12:10 +03002888 if (sdio_al_verify_dev(ch->sdio_al_dev, __func__))
2889 return -ENODEV;
2890 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
2891 ret = read_mailbox(sdio_al_dev, false);
2892 if (ret) {
2893 pr_err(MODULE_NAME ":%s: failed to read mailbox",
2894 __func__);
2895 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2896 return -ENODEV;
2897 }
2898 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002899 } while (ch->read_avail > 0);
2900
2901 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002902 /* disable function to be able to open the channel again */
2903 ret = sdio_disable_func(ch->func);
2904 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002905 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
2906 "disable Func#%d\n", ch->func->num);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002907 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2908 return ret;
2909 }
2910 ch->state = SDIO_CHANNEL_STATE_CLOSED;
2911 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2912
2913 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002914}
2915EXPORT_SYMBOL(sdio_close);
2916
2917/**
2918 * Get the number of available bytes to write.
2919 *
2920 */
2921int sdio_write_avail(struct sdio_channel *ch)
2922{
2923 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002924 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
2925 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002926 return -ENODEV;
2927 }
2928 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002929 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
2930 "Invalid signature 0x%x\n", __func__,
2931 ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002932 return -ENODEV;
2933 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002934 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002935 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2936 "channel %s state is not open (%d)\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002937 __func__, ch->name, ch->state);
2938 return -ENODEV;
2939 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002940 pr_debug(MODULE_NAME ":sdio_write_avail %s 0x%x\n",
2941 ch->name, ch->write_avail);
2942
2943 return ch->write_avail;
2944}
2945EXPORT_SYMBOL(sdio_write_avail);
2946
2947/**
2948 * Get the number of available bytes to read.
2949 *
2950 */
2951int sdio_read_avail(struct sdio_channel *ch)
2952{
2953 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002954 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
2955 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002956 return -ENODEV;
2957 }
2958 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002959 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
2960 "Invalid signature 0x%x\n", __func__,
2961 ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002962 return -ENODEV;
2963 }
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002964 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07002965 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
2966 "channel %s state is not open (%d)\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03002967 __func__, ch->name, ch->state);
2968 return -ENODEV;
2969 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002970 pr_debug(MODULE_NAME ":sdio_read_avail %s 0x%x\n",
2971 ch->name, ch->read_avail);
2972
2973 return ch->read_avail;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002974}
2975EXPORT_SYMBOL(sdio_read_avail);
2976
Maya Erez5795e0d2011-09-12 20:20:06 +03002977static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len)
2978{
2979 int ret = 0;
2980 struct sdio_al_device *sdio_al_dev = NULL;
2981
2982 if (!ch) {
2983 pr_err(MODULE_NAME ":%s: NULL channel\n", __func__);
2984 return -ENODEV;
2985 }
2986
2987 sdio_al_dev = ch->sdio_al_dev;
2988
2989 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
2990
2991 ret = sdio_memcpy_fromio(ch->func, sdio_al_dev->rx_flush_buf,
2992 PIPE_RX_FIFO_ADDR, len);
2993
2994 if (ret) {
2995 pr_err(MODULE_NAME ":ch %s: %s err=%d, len=%d\n",
2996 ch->name, __func__, -ret, len);
2997 sdio_al_dev->is_err = true;
2998 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
2999 return ret;
3000 }
3001
3002 restart_inactive_time(sdio_al_dev);
3003
3004 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3005
3006 return 0;
3007}
3008
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003009/**
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003010 * Internal read from SDIO Channel.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003011 *
3012 * Reading from the pipe will trigger interrupt if there are
3013 * other pending packets on the SDIO-Client.
3014 *
3015 */
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003016static int sdio_read_internal(struct sdio_channel *ch, void *data, int len)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003017{
3018 int ret = 0;
3019 struct sdio_al_device *sdio_al_dev = NULL;
3020
3021 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003022 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3023 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003024 return -ENODEV;
3025 }
3026 if (!data) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003027 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
3028 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003029 return -ENODEV;
3030 }
3031 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003032 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
3033 " to read 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003034 return -EINVAL;
3035 }
3036
3037 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003038 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
3039 "signature 0x%x\n", __func__, ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003040 return -ENODEV;
3041 }
3042
3043 sdio_al_dev = ch->sdio_al_dev;
3044 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3045 return -ENODEV;
3046
3047 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3048
3049 if (sdio_al_dev->is_err) {
3050 SDIO_AL_ERR(__func__);
3051 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3052 return -ENODEV;
3053 }
3054
3055 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003056 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
3057 "sdio_al_dev is in invalid state %d\n",
3058 __func__, sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003059 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3060 return -ENODEV;
3061 }
3062
3063 /* lpm policy says we can't go to sleep when we have pending rx data,
3064 so either we had rx interrupt and woken up, or we never went to
3065 sleep */
3066 if (sdio_al_dev->is_ok_to_sleep) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003067 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: called "
3068 "when is_ok_to_sleep is set for ch %s, len=%d,"
3069 " last_any_read_avail=%d, last_read_avail=%d, "
3070 "last_old_read_avail=%d", __func__, ch->name,
3071 len, ch->statistics.last_any_read_avail,
3072 ch->statistics.last_read_avail,
3073 ch->statistics.last_old_read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003074 }
3075 BUG_ON(sdio_al_dev->is_ok_to_sleep);
3076
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003077 if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
3078 (ch->state != SDIO_CHANNEL_STATE_CLOSING)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003079 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s wrong "
3080 "channel %s state %d\n",
3081 __func__, ch->name, ch->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003082 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3083 return -EINVAL;
3084 }
3085
Krishna Kondaa7af6062011-09-01 18:34:38 -07003086 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s read %d "
3087 "avail %d.\n", ch->name, len, ch->read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003088
3089 restart_inactive_time(sdio_al_dev);
3090
3091 if ((ch->is_packet_mode) && (len != ch->read_avail)) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003092 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_read ch "
3093 "%s len != read_avail\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003094 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3095 return -EINVAL;
3096 }
3097
3098 if (len > ch->read_avail) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003099 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
3100 "reading more bytes (%d) than the avail(%d).\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003101 ch->name, len, ch->read_avail);
3102 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3103 return -ENOMEM;
3104 }
3105
3106 ret = sdio_memcpy_fromio(ch->func, data, PIPE_RX_FIFO_ADDR, len);
3107
3108 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003109 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ch %s: "
3110 "sdio_read err=%d, len=%d, read_avail=%d, "
3111 "last_read_avail=%d, last_old_read_avail=%d\n",
Maya Erezd9cc2292011-08-04 09:20:31 +03003112 ch->name, -ret, len, ch->read_avail,
3113 ch->statistics.last_read_avail,
3114 ch->statistics.last_old_read_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003115 sdio_al_dev->is_err = true;
3116 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3117 return ret;
3118 }
3119
3120 ch->statistics.total_read_times++;
3121
3122 /* Remove handled packet from the list regardless if ret is ok */
3123 if (ch->is_packet_mode)
3124 remove_handled_rx_packet(ch);
3125 else
3126 ch->read_avail -= len;
3127
3128 ch->total_rx_bytes += len;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003129 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s read %d "
3130 "avail %d total %d.\n", ch->name, len,
3131 ch->read_avail, ch->total_rx_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003132
3133 if ((ch->read_avail == 0) && !(ch->is_packet_mode))
3134 ask_reading_mailbox(sdio_al_dev);
3135
3136 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3137
3138 return ret;
3139}
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003140
3141/**
3142 * Read from SDIO Channel.
3143 *
3144 * Reading from the pipe will trigger interrupt if there are
3145 * other pending packets on the SDIO-Client.
3146 *
3147 */
3148int sdio_read(struct sdio_channel *ch, void *data, int len)
3149{
3150 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003151 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3152 "channel\n", __func__);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003153 return -ENODEV;
3154 }
3155 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003156 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
3157 "Invalid signature 0x%x\n", __func__, ch->signature);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003158 return -ENODEV;
3159 }
3160 if (ch->state == SDIO_CHANNEL_STATE_OPEN) {
3161 return sdio_read_internal(ch, data, len);
3162 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003163 sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME
3164 ":%s: Invalid channel %s state %d\n",
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003165 __func__, ch->name, ch->state);
3166 }
3167 return -ENODEV;
3168}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003169EXPORT_SYMBOL(sdio_read);
3170
3171/**
3172 * Write to SDIO Channel.
3173 *
3174 */
3175int sdio_write(struct sdio_channel *ch, const void *data, int len)
3176{
3177 int ret = 0;
3178 struct sdio_al_device *sdio_al_dev = NULL;
3179
3180 if (!ch) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003181 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
3182 "channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003183 return -ENODEV;
3184 }
3185 if (!data) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003186 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
3187 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003188 return -ENODEV;
3189 }
3190 if (len == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003191 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
3192 " to write 0 bytes\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003193 return -EINVAL;
3194 }
3195
3196 if (ch->signature != SDIO_AL_SIGNATURE) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003197 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
3198 "signature 0x%x\n", __func__, ch->signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003199 return -ENODEV;
3200 }
3201
3202 sdio_al_dev = ch->sdio_al_dev;
3203 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3204 return -ENODEV;
3205
3206 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3207
3208
3209 if (sdio_al_dev->state != CARD_INSERTED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003210 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3211 ":%s: sdio_al_dev is in invalid state %d\n",
3212 __func__, sdio_al_dev->state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003213 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3214 return -ENODEV;
3215 }
3216 WARN_ON(len > ch->write_avail);
3217
3218 if (sdio_al_dev->is_err) {
3219 SDIO_AL_ERR(__func__);
3220 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3221 return -ENODEV;
3222 }
3223
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003224 if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003225 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":writing to "
3226 "closed channel %s\n", ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003227 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3228 return -EINVAL;
3229 }
3230
3231 if (sdio_al_dev->is_ok_to_sleep) {
Maya Erez7b1ebd22011-08-20 20:53:24 +03003232 ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003233 if (ret) {
3234 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3235 return ret;
3236 }
3237 } else {
3238 restart_inactive_time(sdio_al_dev);
3239 }
3240
Krishna Kondaa7af6062011-09-01 18:34:38 -07003241 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s write %d "
3242 "avail %d.\n", ch->name, len, ch->write_avail);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003243
3244 if (len > ch->write_avail) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003245 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
3246 "write more bytes (%d) than available %d.\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003247 ch->name, len, ch->write_avail);
3248 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3249 return -ENOMEM;
3250 }
3251
3252 ret = sdio_ch_write(ch, data, len);
3253 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003254 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_write "
3255 "on channel %s err=%d\n", ch->name, -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003256 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3257 return ret;
3258 }
3259
3260 ch->total_tx_bytes += len;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003261 DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s write %d "
3262 "avail %d total %d.\n", ch->name, len,
3263 ch->write_avail, ch->total_tx_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003264
3265 /* Round up to whole buffer size */
3266 len = ROUND_UP(len, ch->peer_tx_buf_size);
3267 /* Protect from wraparound */
3268 len = min(len, (int) ch->write_avail);
3269 ch->write_avail -= len;
3270
3271 if (ch->write_avail < ch->min_write_avail)
3272 ask_reading_mailbox(sdio_al_dev);
3273
3274 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3275
3276 return ret;
3277}
3278EXPORT_SYMBOL(sdio_write);
3279
3280static int __devinit msm_sdio_al_probe(struct platform_device *pdev)
3281{
3282 if (!sdio_al) {
3283 pr_err(MODULE_NAME ": %s: NULL sdio_al\n", __func__);
3284 return -ENODEV;
3285 }
3286
3287 sdio_al->pdata = pdev->dev.platform_data;
3288 return 0;
3289}
3290
3291static int __devexit msm_sdio_al_remove(struct platform_device *pdev)
3292{
3293 return 0;
3294}
3295
Maya Erez6862b142011-08-22 09:07:07 +03003296static void msm_sdio_al_shutdown(struct platform_device *pdev)
3297{
3298 int i, j;
3299 struct sdio_func *func1 = NULL;
3300 int ret;
3301
Krishna Kondaa7af6062011-09-01 18:34:38 -07003302 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Initiating "
3303 "msm_sdio_al_shutdown...", __func__);
Maya Erez6862b142011-08-22 09:07:07 +03003304
3305 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
3306 struct sdio_al_device *sdio_al_dev = NULL;
3307 if (sdio_al->devices[i] == NULL) {
3308 pr_debug(MODULE_NAME ": %s: NULL device in index %d",
3309 __func__, i);
3310 continue;
3311 }
3312 sdio_al_dev = sdio_al->devices[i];
3313 if (sdio_al_dev->state == CARD_REMOVED) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003314 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: "
3315 "card %d is already removed", __func__,
3316 sdio_al_dev->card->host->index);
Maya Erez6862b142011-08-22 09:07:07 +03003317 continue;
3318 }
3319 if (sdio_al_dev->state == MODEM_RESTART) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003320 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: "
3321 "card %d was already notified for modem reset",
Maya Erez6862b142011-08-22 09:07:07 +03003322 __func__, sdio_al_dev->card->host->index);
3323 continue;
3324 }
3325
Krishna Kondaa7af6062011-09-01 18:34:38 -07003326 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: Set the "
3327 "state to MODEM_RESTART for card %d",
Maya Erez6862b142011-08-22 09:07:07 +03003328 __func__, sdio_al_dev->card->host->index);
3329 sdio_al_dev->state = MODEM_RESTART;
3330 sdio_al_dev->is_ready = false;
3331
3332 /* Stop mailbox timer */
3333 if (sdio_al_dev->is_timer_initialized) {
3334 pr_debug(MODULE_NAME ": %s: Stop timer for card %d",
3335 __func__, sdio_al_dev->card->host->index);
3336 sdio_al_dev->poll_delay_msec = 0;
3337 del_timer_sync(&sdio_al_dev->timer);
3338 }
3339 }
3340
3341 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
3342 struct sdio_al_device *sdio_al_dev;
3343 if (sdio_al->devices[i] == NULL) {
3344 pr_debug(MODULE_NAME ": %s: NULL device in index %d",
3345 __func__, i);
3346 continue;
3347 }
3348 sdio_al_dev = sdio_al->devices[i];
3349
3350 if (!sdio_al_verify_func1(sdio_al_dev, __func__)) {
3351 func1 = sdio_al_dev->card->sdio_func[0];
3352 sdio_claim_host(func1);
3353
3354 if ((sdio_al_dev->is_ok_to_sleep) &&
3355 (!sdio_al_dev->is_err)) {
3356 pr_debug(MODULE_NAME ": %s: wakeup modem for "
3357 "card %d", __func__,
3358 sdio_al_dev->card->host->index);
3359 ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
3360 if (ret == 0) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003361 sdio_al_logi(sdio_al_dev->dev_log,
3362 MODULE_NAME ": %s: "
3363 "sdio_release_irq for card %d",
Maya Erez6862b142011-08-22 09:07:07 +03003364 __func__,
3365 sdio_al_dev->card->host->index);
3366 sdio_release_irq(func1);
3367 }
3368 } else {
3369 pr_debug(MODULE_NAME ": %s: sdio_release_irq"
3370 " for card %d",
3371 __func__,
3372 sdio_al_dev->card->host->index);
3373 sdio_release_irq(func1);
3374 }
3375 }
3376
3377 pr_debug(MODULE_NAME ": %s: Notifying SDIO clients for card %d",
3378 __func__, sdio_al_dev->card->host->index);
Maya Erez8afd5642011-08-24 15:57:06 +03003379 for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++) {
3380 if (sdio_al_dev->channel[j].state ==
3381 SDIO_CHANNEL_STATE_INVALID)
3382 continue;
3383 platform_device_unregister(
3384 sdio_al_dev->channel[j].pdev);
3385 sdio_al_dev->channel[i].signature = 0x0;
3386 }
Maya Erez6862b142011-08-22 09:07:07 +03003387
3388 if (!sdio_al_verify_func1(sdio_al_dev, __func__))
3389 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3390
3391 pr_debug(MODULE_NAME ": %s: Allows sleep for card %d", __func__,
3392 sdio_al_dev->card->host->index);
3393 sdio_al_vote_for_sleep(sdio_al_dev, 1);
3394 }
Krishna Kondaa7af6062011-09-01 18:34:38 -07003395 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: "
3396 "msm_sdio_al_shutdown complete.", __func__);
Maya Erez6862b142011-08-22 09:07:07 +03003397}
3398
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003399static struct platform_driver msm_sdio_al_driver = {
3400 .probe = msm_sdio_al_probe,
3401 .remove = __exit_p(msm_sdio_al_remove),
Maya Erez6862b142011-08-22 09:07:07 +03003402 .shutdown = msm_sdio_al_shutdown,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003403 .driver = {
3404 .name = "msm_sdio_al",
3405 },
3406};
3407
3408/**
3409 * Initialize SDIO_AL channels.
3410 *
3411 */
3412static int init_channels(struct sdio_al_device *sdio_al_dev)
3413{
3414 int ret = 0;
3415 int i;
3416
3417 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3418 return -ENODEV;
3419
3420 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3421
3422 ret = read_sdioc_software_header(sdio_al_dev,
3423 sdio_al_dev->sdioc_sw_header);
3424 if (ret)
3425 goto exit;
3426
3427 ret = sdio_al_setup(sdio_al_dev);
3428 if (ret)
3429 goto exit;
3430
3431 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
3432 int ch_name_size;
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003433 if (sdio_al_dev->channel[i].state == SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003434 continue;
3435 if (sdio_al->unittest_mode) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003436 memset(sdio_al_dev->channel[i].ch_test_name, 0,
3437 sizeof(sdio_al_dev->channel[i].ch_test_name));
3438 ch_name_size = strnlen(sdio_al_dev->channel[i].name,
3439 CHANNEL_NAME_SIZE);
3440 strncpy(sdio_al_dev->channel[i].ch_test_name,
3441 sdio_al_dev->channel[i].name,
3442 ch_name_size);
3443 strncat(sdio_al_dev->channel[i].ch_test_name +
3444 ch_name_size,
3445 SDIO_TEST_POSTFIX,
3446 SDIO_TEST_POSTFIX_SIZE);
3447 pr_debug(MODULE_NAME ":pdev.name = %s\n",
3448 sdio_al_dev->channel[i].ch_test_name);
3449 sdio_al_dev->channel[i].pdev = platform_device_alloc(
3450 sdio_al_dev->channel[i].ch_test_name, -1);
3451 } else {
3452 pr_debug(MODULE_NAME ":pdev.name = %s\n",
3453 sdio_al_dev->channel[i].name);
3454 sdio_al_dev->channel[i].pdev = platform_device_alloc(
3455 sdio_al_dev->channel[i].name, -1);
3456 }
3457 if (!sdio_al_dev->channel[i].pdev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003458 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3459 ":NULL platform device for ch %s",
3460 sdio_al_dev->channel[i].name);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003461 sdio_al_dev->channel[i].state =
3462 SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003463 continue;
3464 }
3465 ret = platform_device_add(sdio_al_dev->channel[i].pdev);
3466 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003467 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3468 ":platform_device_add failed, "
3469 "ret=%d\n", ret);
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003470 sdio_al_dev->channel[i].state =
3471 SDIO_CHANNEL_STATE_INVALID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003472 }
3473 }
3474
3475exit:
3476 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3477 return ret;
3478}
3479
3480/**
3481 * Initialize SDIO_AL channels according to the client setup.
3482 * This function also check if the client is in boot mode and
3483 * flashless boot is required to be activated or the client is
3484 * up and running.
3485 *
3486 */
3487static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev)
3488{
3489 int ret = 0;
3490 struct sdio_func *func1;
3491 int signature = 0;
3492
3493 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3494 return -ENODEV;
3495 func1 = sdio_al_dev->card->sdio_func[0];
3496
3497 sdio_claim_host(func1);
3498
3499 /* Read the header signature to determine the status of the MDM
3500 * SDIO Client
3501 */
3502 signature = sdio_readl(func1, SDIOC_SW_HEADER_ADDR, &ret);
3503 sdio_release_host(func1);
3504 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003505 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
3506 "signature from sw header.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003507 return ret;
3508 }
3509
3510 switch (signature) {
3511 case PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE:
3512 if (sdio_al_dev == sdio_al->bootloader_dev) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003513 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":setup "
3514 "bootloader on card %d\n",
3515 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003516 return sdio_al_bootloader_setup();
3517 } else {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003518 sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":wait "
3519 "for bootloader completion "
3520 "on card %d\n",
3521 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003522 return sdio_al_wait_for_bootloader_comp(sdio_al_dev);
3523 }
3524 case PEER_SDIOC_SW_MAILBOX_SIGNATURE:
3525 case PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE:
3526 return init_channels(sdio_al_dev);
3527 default:
Krishna Kondaa7af6062011-09-01 18:34:38 -07003528 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
3529 "signature 0x%x\n", signature);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003530 return -EINVAL;
3531 }
3532
3533 return 0;
3534}
3535
3536/*
3537 * SDIO driver functions
3538 */
3539static int sdio_al_sdio_probe(struct sdio_func *func,
3540 const struct sdio_device_id *sdio_dev_id)
3541{
3542 int ret = 0;
3543 struct sdio_al_device *sdio_al_dev = NULL;
3544 int i;
3545 struct mmc_card *card = NULL;
3546
3547 if (!func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003548 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
3549 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003550 return -ENODEV;
3551 }
3552 card = func->card;
3553
3554 if (!card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003555 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
3556 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003557 return -ENODEV;
3558 }
3559
3560 if (card->sdio_funcs < SDIO_AL_MAX_FUNCS) {
3561 dev_info(&card->dev,
3562 "SDIO-functions# %d less than expected.\n",
3563 card->sdio_funcs);
3564 return -ENODEV;
3565 }
3566
3567 /* Check if there is already a device for this card */
3568 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
3569 if (sdio_al->devices[i] == NULL)
3570 continue;
3571 if (sdio_al->devices[i]->card == card)
3572 return 0;
3573 }
3574
3575 dev_info(&card->dev, "SDIO Card claimed.\n");
3576
3577 sdio_al_dev = kzalloc(sizeof(struct sdio_al_device), GFP_KERNEL);
3578 if (sdio_al_dev == NULL)
3579 return -ENOMEM;
3580
3581 sdio_al_dev->state = CARD_INSERTED;
3582
3583 if (card->host->index == SDIO_BOOTLOADER_CARD_INDEX)
3584 sdio_al->bootloader_dev = sdio_al_dev;
3585
3586 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
3587 if (sdio_al->devices[i] == NULL) {
3588 sdio_al->devices[i] = sdio_al_dev;
Krishna Kondaa7af6062011-09-01 18:34:38 -07003589 sdio_al_dev->dev_log = &sdio_al->device_log[i];
3590 spin_lock_init(&sdio_al_dev->dev_log->log_lock);
3591#ifdef CONFIG_DEBUG_FS
3592 sdio_al_dbgfs_log[i].data =
3593 sdio_al_dev->dev_log->buffer;
3594 sdio_al_dbgfs_log[i].size = SDIO_AL_DEBUG_LOG_SIZE;
3595#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003596 break;
3597 }
3598 if (i == MAX_NUM_OF_SDIO_DEVICES) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003599 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":No space in "
3600 "devices array for the device\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003601 return -ENOMEM;
3602 }
3603
3604 sdio_al_dev->is_ready = false;
3605
3606 sdio_al_dev->signature = SDIO_AL_SIGNATURE;
3607
3608 sdio_al_dev->is_suspended = 0;
3609 sdio_al_dev->is_timer_initialized = false;
3610
3611 sdio_al_dev->lpm_chan = INVALID_SDIO_CHAN;
3612
3613 sdio_al_dev->card = card;
3614
3615 sdio_al_dev->mailbox = kzalloc(sizeof(struct sdio_mailbox), GFP_KERNEL);
3616 if (sdio_al_dev->mailbox == NULL)
3617 return -ENOMEM;
3618
3619 sdio_al_dev->sdioc_sw_header
3620 = kzalloc(sizeof(*sdio_al_dev->sdioc_sw_header), GFP_KERNEL);
3621 if (sdio_al_dev->sdioc_sw_header == NULL)
3622 return -ENOMEM;
3623
Maya Erez5795e0d2011-09-12 20:20:06 +03003624
3625 sdio_al_dev->rx_flush_buf = kzalloc(RX_FLUSH_BUFFER_SIZE, GFP_KERNEL);
3626 if (sdio_al_dev->rx_flush_buf == NULL) {
3627 pr_err(MODULE_NAME ":Fail to allocate rx_flush_buf "
3628 "for card %d\n",
3629 card->host->index);
3630 return -ENOMEM;
3631 }
3632
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003633 sdio_al_dev->timer.data = (unsigned long)sdio_al_dev;
3634
3635 wake_lock_init(&sdio_al_dev->wake_lock, WAKE_LOCK_SUSPEND, MODULE_NAME);
3636 /* Don't allow sleep until all required clients register */
3637 sdio_al_vote_for_sleep(sdio_al_dev, 0);
3638
3639 sdio_claim_host(card->sdio_func[0]);
3640
3641 /* Init Func#1 */
Yaniv Gardi9a952d92011-09-06 13:46:30 +03003642 ret = sdio_al_enable_func_retry(card->sdio_func[0], "Init Func#1");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003643 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003644 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
3645 "enable Func#%d\n", card->sdio_func[0]->num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003646 goto exit;
3647 }
3648
3649 /* Patch Func CIS tuple issue */
3650 ret = sdio_set_block_size(card->sdio_func[0], SDIO_AL_BLOCK_SIZE);
3651 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003652 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to set "
3653 "block size, Func#%d\n", card->sdio_func[0]->num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003654 goto exit;
3655 }
3656 sdio_al_dev->card->sdio_func[0]->max_blksize = SDIO_AL_BLOCK_SIZE;
3657
3658 sdio_al_dev->workqueue = create_singlethread_workqueue("sdio_al_wq");
3659 sdio_al_dev->sdio_al_work.sdio_al_dev = sdio_al_dev;
3660 init_waitqueue_head(&sdio_al_dev->wait_mbox);
3661
3662 ret = sdio_al_client_setup(sdio_al_dev);
3663
3664exit:
3665 sdio_release_host(card->sdio_func[0]);
3666 return ret;
3667}
3668
3669static void sdio_al_sdio_remove(struct sdio_func *func)
3670{
3671 struct sdio_al_device *sdio_al_dev = NULL;
3672 int i;
3673 int state;
3674 struct mmc_card *card = NULL;
3675
3676 if (!func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003677 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
3678 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003679 return;
3680 }
3681 card = func->card;
3682
3683 if (!card) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003684 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
3685 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003686 return;
3687 }
3688
3689 /* Find the sdio_al_device of this card */
3690 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
3691 if (sdio_al->devices[i] == NULL)
3692 continue;
3693 if (sdio_al->devices[i]->card == card) {
3694 sdio_al_dev = sdio_al->devices[i];
3695 sdio_al->devices[i] = NULL;
3696 break;
3697 }
3698 }
3699 if (sdio_al_dev == NULL) {
3700 pr_debug(MODULE_NAME ":%s :NULL sdio_al_dev for card %d\n",
3701 __func__, card->host->index);
3702 return;
3703 }
3704
Krishna Kondaa7af6062011-09-01 18:34:38 -07003705 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s for card %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003706 __func__, card->host->index);
3707
3708 if (card->sdio_func[0])
3709 sdio_claim_host(card->sdio_func[0]);
3710 else
Krishna Kondaa7af6062011-09-01 18:34:38 -07003711 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL func1 "
3712 "for card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003713
3714 if (sdio_al_dev->state == CARD_REMOVED)
3715 return;
3716
3717 state = sdio_al_dev->state;
3718 sdio_al_dev->state = CARD_REMOVED;
3719
3720 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++)
3721 sdio_al_dev->channel[i].signature = 0x0;
3722
Krishna Kondaa7af6062011-09-01 18:34:38 -07003723 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: ask_reading_mailbox "
3724 "for card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003725 sdio_al_dev->is_ready = false; /* Flag worker to exit */
3726 sdio_al_dev->ask_mbox = false;
3727 ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
3728
3729 if (state != MODEM_RESTART) {
3730 if (sdio_al_dev->is_timer_initialized) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003731 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Stop"
3732 " timer for card %d", __func__,
3733 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003734 sdio_al_dev->poll_delay_msec = 0;
3735 del_timer_sync(&sdio_al_dev->timer);
3736 }
3737
Krishna Kondaa7af6062011-09-01 18:34:38 -07003738 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: "
3739 "notifying clients for card %d\n",
Maya Erez8afd5642011-08-24 15:57:06 +03003740 __func__, card->host->index);
3741 for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
3742 if (sdio_al_dev->channel[i].state ==
3743 SDIO_CHANNEL_STATE_INVALID)
3744 continue;
3745 platform_device_unregister(
3746 sdio_al_dev->channel[i].pdev);
3747 sdio_al_dev->channel[i].signature = 0x0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003748 }
3749 }
3750 if (card->sdio_func[0])
3751 sdio_release_host(card->sdio_func[0]);
3752
Krishna Kondaa7af6062011-09-01 18:34:38 -07003753 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: vote for sleep for "
3754 "card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003755 sdio_al_vote_for_sleep(sdio_al_dev, 1);
3756
Krishna Kondaa7af6062011-09-01 18:34:38 -07003757 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: flush_workqueue for "
3758 "card %d\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003759 flush_workqueue(sdio_al_dev->workqueue);
3760 destroy_workqueue(sdio_al_dev->workqueue);
3761 wake_lock_destroy(&sdio_al_dev->wake_lock);
3762
Krishna Kondaa7af6062011-09-01 18:34:38 -07003763 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: delete data "
3764 "structures for card %d\n", __func__,
3765 card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003766 kfree(sdio_al_dev->sdioc_sw_header);
3767 kfree(sdio_al_dev->mailbox);
Maya Erez5795e0d2011-09-12 20:20:06 +03003768 kfree(sdio_al_dev->rx_flush_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003769 kfree(sdio_al_dev);
3770
Krishna Kondaa7af6062011-09-01 18:34:38 -07003771 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: sdio card %d removed."
3772 "\n", __func__, card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003773}
3774
3775static void sdio_print_mailbox(char *prefix_str, struct sdio_mailbox *mailbox)
3776{
3777 int k = 0;
3778 char buf[256];
3779 char buf1[10];
3780
3781 if (!mailbox) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003782 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": mailbox is "
3783 "NULL\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003784 return;
3785 }
3786
Krishna Kondaa7af6062011-09-01 18:34:38 -07003787 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: pipes 0_7: eot=0x%x,"
3788 " thresh=0x%x, overflow=0x%x, "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003789 "underflow=0x%x, mask_thresh=0x%x\n",
3790 prefix_str, mailbox->eot_pipe_0_7,
3791 mailbox->thresh_above_limit_pipe_0_7,
3792 mailbox->overflow_pipe_0_7,
3793 mailbox->underflow_pipe_0_7,
3794 mailbox->mask_thresh_above_limit_pipe_0_7);
3795
3796 memset(buf, 0, sizeof(buf));
3797 strncat(buf, ": bytes_avail:", sizeof(buf));
3798
3799 for (k = 0 ; k < SDIO_AL_ACTIVE_PIPES ; ++k) {
3800 snprintf(buf1, sizeof(buf1), "%d, ",
3801 mailbox->pipe_bytes_avail[k]);
3802 strncat(buf, buf1, sizeof(buf));
3803 }
3804
Krishna Kondaa7af6062011-09-01 18:34:38 -07003805 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME "%s", buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003806}
3807
3808static void sdio_al_print_info(void)
3809{
3810 int i = 0;
3811 int j = 0;
3812 int ret = 0;
3813 struct sdio_mailbox *mailbox = NULL;
3814 struct sdio_mailbox *hw_mailbox = NULL;
3815 struct peer_sdioc_channel_config *ch_config = NULL;
3816 struct sdio_func *func1 = NULL;
3817 struct sdio_func *lpm_func = NULL;
3818 int offset = 0;
3819 int is_ok_to_sleep = 0;
3820 static atomic_t first_time;
3821 char buf[50];
3822
3823 if (atomic_read(&first_time) == 1)
3824 return;
3825
3826 atomic_set(&first_time, 1);
3827
Krishna Kondaa7af6062011-09-01 18:34:38 -07003828 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - SDIO DEBUG INFO\n",
3829 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003830
3831 if (!sdio_al) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003832 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - ERROR - "
3833 "sdio_al is NULL\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003834 return;
3835 }
3836
Krishna Kondaa7af6062011-09-01 18:34:38 -07003837 sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": GPIO mdm2ap_status=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003838 sdio_al->pdata->get_mdm2ap_status());
3839
3840 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
3841 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
3842
3843 if (sdio_al_dev == NULL) {
3844 continue;
3845 }
3846
3847 if (!sdio_al_dev->card && !sdio_al_dev->card->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003848 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card"
3849 " or Host fields are NULL\n);");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003850 continue;
3851 }
3852
3853 snprintf(buf, sizeof(buf), "Card#%d: Shadow HW MB",
3854 sdio_al_dev->card->host->index);
3855
3856 /* printing Shadowing HW Mailbox*/
3857 mailbox = sdio_al_dev->mailbox;
3858 sdio_print_mailbox(buf, mailbox);
3859
Krishna Kondaa7af6062011-09-01 18:34:38 -07003860 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003861 "is_ok_to_sleep=%d\n",
3862 sdio_al_dev->card->host->index,
3863 sdio_al_dev->is_ok_to_sleep);
3864
3865
Krishna Kondaa7af6062011-09-01 18:34:38 -07003866 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003867 "Shadow channels SW MB:",
3868 sdio_al_dev->card->host->index);
3869
3870 /* printing Shadowing SW Mailbox per channel*/
3871 for (i = 0 ; i < SDIO_AL_MAX_CHANNELS ; ++i) {
3872 struct sdio_channel *ch = &sdio_al_dev->channel[i];
3873
3874 if (ch == NULL) {
3875 continue;
3876 }
3877
Konstantin Dorfmanee2e3082011-08-16 15:12:01 +03003878 if (ch->state == SDIO_CHANNEL_STATE_INVALID)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003879 continue;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003880
3881 ch_config = &sdio_al_dev->channel[i].ch_config;
3882
Krishna Kondaa7af6062011-09-01 18:34:38 -07003883 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3884 ": Ch %s: max_rx_thres=0x%x, "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003885 "max_tx_thres=0x%x, tx_buf=0x%x, "
3886 "is_packet_mode=%d, "
3887 "max_packet=0x%x, min_write=0x%x",
3888 ch->name, ch_config->max_rx_threshold,
3889 ch_config->max_tx_threshold,
3890 ch_config->tx_buf_size,
3891 ch_config->is_packet_mode,
3892 ch_config->max_packet_size,
3893 ch->min_write_avail);
3894
Krishna Kondaa7af6062011-09-01 18:34:38 -07003895 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3896 ": total_rx=0x%x, total_tx=0x%x, "
3897 "read_avail=0x%x, write_avail=0x%x, "
3898 "rx_pending=0x%x, num_reads=0x%x, "
3899 "num_notifs=0x%x", ch->total_rx_bytes,
3900 ch->total_tx_bytes, ch->read_avail,
3901 ch->write_avail, ch->rx_pending_bytes,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003902 ch->statistics.total_read_times,
3903 ch->statistics.total_notifs);
3904 } /* end loop over all channels */
3905
3906 } /* end loop over all devices */
3907
3908 /* reading from client and printing is_host_ok_to_sleep per device */
3909 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
3910 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
3911
3912 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3913 return;
3914
3915 if (!sdio_al_dev->card->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003916 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3917 ": Host is NULL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003918 continue;
3919 }
3920
3921 if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003922 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3923 ": %s - for Card#%d, is lpm_chan=="
3924 "INVALID_SDIO_CHAN. continuing...",
3925 __func__, sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003926 continue;
3927 }
3928
3929 offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
3930 sizeof(struct peer_sdioc_channel_config) *
3931 sdio_al_dev->lpm_chan+
3932 offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
3933
3934 lpm_func = sdio_al_dev->card->sdio_func[sdio_al_dev->
3935 lpm_chan+1];
3936 if (!lpm_func) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003937 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3938 ": %s - lpm_func is NULL for card#%d"
3939 " continuing...\n", __func__,
3940 sdio_al_dev->card->host->index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003941 continue;
3942 }
3943
3944 sdio_claim_host(sdio_al_dev->card->sdio_func[0]);
3945 ret = sdio_memcpy_fromio(lpm_func,
3946 &is_ok_to_sleep,
3947 SDIOC_SW_MAILBOX_ADDR+offset,
3948 sizeof(int));
Maya Erez1dd658a2011-08-09 10:14:47 +03003949 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3950 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003951 sdio_release_host(sdio_al_dev->card->sdio_func[0]);
3952
3953 if (ret)
Krishna Kondaa7af6062011-09-01 18:34:38 -07003954 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3955 ": %s - fail to read "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003956 "is_HOST_ok_to_sleep from mailbox for card %d",
3957 __func__, sdio_al_dev->card->host->index);
3958 else
Krishna Kondaa7af6062011-09-01 18:34:38 -07003959 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3960 ": Card#%d: "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003961 "is_HOST_ok_to_sleep=%d\n",
3962 sdio_al_dev->card->host->index,
3963 is_ok_to_sleep);
3964 }
3965
3966 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
3967 struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
3968
3969 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3970 return;
3971
3972 if (!sdio_al_dev->card->host) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003973 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3974 ": Host is NULL");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003975 continue;
3976 }
3977
3978 /* Reading HW Mailbox */
3979 hw_mailbox = sdio_al_dev->mailbox;
3980 func1 = sdio_al_dev->card->sdio_func[0];
3981
3982 sdio_claim_host(func1);
3983 ret = sdio_memcpy_fromio(func1, hw_mailbox,
3984 HW_MAILBOX_ADDR, sizeof(*hw_mailbox));
Maya Erez1dd658a2011-08-09 10:14:47 +03003985 if (sdio_al_verify_dev(sdio_al_dev, __func__))
3986 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003987 sdio_release_host(func1);
3988
3989 if (ret) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07003990 sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
3991 ": fail to read "
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003992 "mailbox for card#%d. "
3993 "continuing...\n",
3994 sdio_al_dev->card->host->index);
3995 continue;
3996 }
3997
3998 snprintf(buf, sizeof(buf), "Card#%d: Current HW MB",
3999 sdio_al_dev->card->host->index);
4000
4001 /* Printing HW Mailbox */
4002 sdio_print_mailbox(buf, hw_mailbox);
4003 }
4004}
4005
4006static struct sdio_device_id sdio_al_sdioid[] = {
4007 {.class = 0, .vendor = 0x70, .device = 0x2460},
4008 {.class = 0, .vendor = 0x70, .device = 0x0460},
4009 {.class = 0, .vendor = 0x70, .device = 0x23F1},
4010 {.class = 0, .vendor = 0x70, .device = 0x23F0},
4011 {}
4012};
4013
4014static struct sdio_driver sdio_al_sdiofn_driver = {
4015 .name = "sdio_al_sdiofn",
4016 .id_table = sdio_al_sdioid,
4017 .probe = sdio_al_sdio_probe,
4018 .remove = sdio_al_sdio_remove,
4019};
4020
4021#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4022/*
4023 * Callback for notifications from restart mudule.
4024 * This function handles only the BEFORE_RESTART notification.
4025 * Stop all the activity on the card and notify our clients.
4026 */
4027static int sdio_al_subsys_notifier_cb(struct notifier_block *this,
4028 unsigned long notif_type,
4029 void *data)
4030{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004031 if (notif_type != SUBSYS_BEFORE_SHUTDOWN) {
Krishna Kondaa7af6062011-09-01 18:34:38 -07004032 sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: got "
4033 "notification %ld", __func__, notif_type);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004034 return NOTIFY_DONE;
4035 }
4036
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004037
Maya Erez6862b142011-08-22 09:07:07 +03004038 msm_sdio_al_shutdown(NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004039 return NOTIFY_OK;
4040}
4041
4042static struct notifier_block sdio_al_nb = {
4043 .notifier_call = sdio_al_subsys_notifier_cb,
4044};
4045#endif
4046
4047/**
4048 * Module Init.
4049 *
4050 * @warn: allocate sdio_al context before registering driver.
4051 *
4052 */
4053static int __init sdio_al_init(void)
4054{
4055 int ret = 0;
4056 int i;
4057
4058 pr_debug(MODULE_NAME ":sdio_al_init\n");
4059
4060 pr_info(MODULE_NAME ":SDIO-AL SW version %s\n",
4061 DRV_VERSION);
4062
4063 sdio_al = kzalloc(sizeof(struct sdio_al), GFP_KERNEL);
4064 if (sdio_al == NULL)
4065 return -ENOMEM;
4066
4067 for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
4068 sdio_al->devices[i] = NULL;
4069
4070 sdio_al->unittest_mode = false;
4071
4072 sdio_al->debug.debug_lpm_on = debug_lpm_on;
4073 sdio_al->debug.debug_data_on = debug_data_on;
4074
4075#ifdef CONFIG_DEBUG_FS
4076 sdio_al_debugfs_init();
4077#endif
4078
4079
4080#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4081 sdio_al->subsys_notif_handle = subsys_notif_register_notifier(
4082 "external_modem", &sdio_al_nb);
4083#endif
4084
4085 ret = platform_driver_register(&msm_sdio_al_driver);
4086 if (ret) {
4087 pr_err(MODULE_NAME ": platform_driver_register failed: %d\n",
4088 ret);
4089 goto exit;
4090 }
4091
4092 sdio_register_driver(&sdio_al_sdiofn_driver);
Krishna Kondaa7af6062011-09-01 18:34:38 -07004093
4094 spin_lock_init(&sdio_al->gen_log.log_lock);
4095
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004096exit:
4097 if (ret)
4098 kfree(sdio_al);
4099 return ret;
4100}
4101
4102/**
4103 * Module Exit.
4104 *
4105 * Free allocated memory.
4106 * Disable SDIO-Card.
4107 * Unregister driver.
4108 *
4109 */
4110static void __exit sdio_al_exit(void)
4111{
4112 if (sdio_al == NULL)
4113 return;
4114
4115 pr_debug(MODULE_NAME ":sdio_al_exit\n");
4116
4117#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
4118 subsys_notif_unregister_notifier(
4119 sdio_al->subsys_notif_handle, &sdio_al_nb);
4120#endif
4121
4122 sdio_al_tear_down();
4123
4124 sdio_unregister_driver(&sdio_al_sdiofn_driver);
4125
4126 kfree(sdio_al);
4127
4128#ifdef CONFIG_DEBUG_FS
4129 sdio_al_debugfs_cleanup();
4130#endif
4131
4132 platform_driver_unregister(&msm_sdio_al_driver);
4133
4134 pr_debug(MODULE_NAME ":sdio_al_exit complete\n");
4135}
4136
4137module_init(sdio_al_init);
4138module_exit(sdio_al_exit);
4139
4140MODULE_LICENSE("GPL v2");
4141MODULE_DESCRIPTION("SDIO Abstraction Layer");
4142MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
4143MODULE_VERSION(DRV_VERSION);
4144