aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dpram/raffaello
diff options
context:
space:
mode:
authorDorian Snyder <dastin1015@gmail.com>2013-06-12 02:24:45 -0700
committerDorian Snyder <dastin1015@gmail.com>2013-06-20 00:06:04 -0700
commit4b2308ce699b9c599dd6e6acf57ac11f483381d9 (patch)
tree4c31179b06d094887b1c8ca70264cf8f184a5981 /drivers/dpram/raffaello
parent855d6a6c1f7c54ef073caac3f6c5f9b1ed72eb4d (diff)
downloadkernel_samsung_smdk4412-4b2308ce699b9c599dd6e6acf57ac11f483381d9.zip
kernel_samsung_smdk4412-4b2308ce699b9c599dd6e6acf57ac11f483381d9.tar.gz
kernel_samsung_smdk4412-4b2308ce699b9c599dd6e6acf57ac11f483381d9.tar.bz2
d710: initial support for the Epic 4G Touch (SPH-D710)
Change-Id: Iafbd9fb45253b02d539ac0ba114f57b3bf9eeed4
Diffstat (limited to 'drivers/dpram/raffaello')
-rwxr-xr-xdrivers/dpram/raffaello/dpram.c3747
-rwxr-xr-xdrivers/dpram/raffaello/dpram.h418
-rw-r--r--drivers/dpram/raffaello/dpram_recovery.c1527
-rw-r--r--drivers/dpram/raffaello/dpram_recovery.h132
4 files changed, 5824 insertions, 0 deletions
diff --git a/drivers/dpram/raffaello/dpram.c b/drivers/dpram/raffaello/dpram.c
new file mode 100755
index 0000000..77e4a03
--- /dev/null
+++ b/drivers/dpram/raffaello/dpram.c
@@ -0,0 +1,3747 @@
+/****************************************************************************
+**
+** COPYRIGHT(C) : Samsung Electronics Co.Ltd, 2006-2010 ALL RIGHTS RESERVED
+**
+** IDPRAM Device Driver
+**
+****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/irq.h>
+#include <linux/poll.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <mach/regs-gpio.h>
+#include <plat/gpio-cfg.h>
+#include <mach/hardware.h>
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif /* CONFIG_PROC_FS */
+
+#include <linux/workqueue.h>
+#include <linux/wakelock.h>
+#include <linux/miscdevice.h>
+#include <linux/netdevice.h>
+#ifdef CONFIG_SEC_DEBUG
+#include <linux/kernel_sec_common.h>
+#endif
+
+#include "dpram.h"
+#include <mach/system.h>
+#include <mach/sec_debug.h>
+
+/***************************************************************************/
+/* GPIO SETTING */
+/***************************************************************************/
+#include <mach/gpio.h>
+
+int sec_debug_dpram(void);
+
+/* Added to store irq num */
+int dpram_irq;
+int dpram_wakeup_irq;
+int phone_active_irq;
+int cp_dump_irq;
+
+#define GPIO_QSC_INT GPIO_C210_DPRAM_INT_N
+#define IRQ_QSC_INT GPIO_QSC_INT
+
+#define IRQ_CP_DUMP_INT GPIO_CP_DUMP_INT
+
+#ifdef IRQ_DPRAM_AP_INT_N
+#undef IRQ_DPRAM_AP_INT_N
+#endif
+#define IRQ_DPRAM_AP_INT_N IRQ_MODEM_IF
+
+#define PRINT_DPRAM_PWR_CTRL
+
+/*
+** Definitions for CP RAMDUMP
+*/
+#if 1
+#define CMD_CP_RAMDUMP_START_REQ 0x9200
+#define CMD_CP_RAMDUMP_START_RESP 0x0300
+#define CMD_CP_RAMDUMP_SEND_REQ 0x9400
+#define CMD_CP_RAMDUMP_SEND_RESP 0x0500
+#define CMD_CP_RAMDUMP_SEND_DONE_REQ 0x9600
+#define CMD_CP_RAMDUMP_SEND_DONE_RESP 0x0700
+
+#define MASK_CMD_RESULT_FAIL 0x0002
+#define MASK_CMD_RESULT_SUCCESS 0x0001
+
+/* MailBox Message */
+#define QSC_UPLOAD_MODE (0x444D554C)
+#define QSC_UPLOAD_MODE_COMPLETE (0xABCDEF90)
+
+#define CP_RAMDUMP_MAGIC_CODE_SIZE 4
+#define CP_RAMDUMP_HEADER_SIZE 12
+#define CP_RAMDUMP_BUFFER_SIZE 16364
+#define DPRAM_CP_HEADER_START_ADDRESS (DPRAM_VBASE + CP_RAMDUMP_MAGIC_CODE_SIZE)
+#define DPRAM_CP_RAMDUMP_START_ADDRESS (DPRAM_CP_HEADER_START_ADDRESS + CP_RAMDUMP_HEADER_SIZE)
+
+#define MASK_CMD_VALID 0x8000
+#define MASK_PDA_CMD 0x1000
+#define MASK_PHONE_CMD 0x2000
+
+#define RAMDUMP_WAIT_TIMEOUT 5*HZ
+
+typedef struct _DumpCMDHeader
+{
+ u32 addr;
+ u32 size;
+ u32 copyto_offset;
+} DumpCMDHeader;
+
+typedef struct
+{
+ int index;
+ unsigned long start_addr;
+ unsigned long end_addr;
+} s_cp_mem_region;
+
+typedef struct
+{
+ unsigned long dram_base_addr;
+ s_cp_mem_region cp_mem_region[16];
+} s_cp_mem_info;
+
+s_cp_mem_info cp_mem_info = {
+ 0x40000000,
+ {
+ {0, 0x00000000, 0x01FFFFFF },
+ }
+};
+
+struct dpram {
+ struct class *class;
+ struct device *dev;
+ struct cdev cdev;
+ dev_t devid;
+
+ wait_queue_head_t waitq;
+ struct fasync_struct *async_queue;
+ u32 mailbox;
+
+ unsigned long base;
+ unsigned long size;
+ void __iomem *mmio;
+
+ int irq;
+
+ struct completion comp;
+ atomic_t ref_sem;
+ unsigned long flags;
+
+ const struct attribute_group *group;
+};
+
+struct dpram *dpram_dev;
+
+struct completion wait_dump_data;
+
+static int g_irq_mask = 0;
+
+static u32 dump_rx_total = 0;
+#endif
+
+
+/* ===========================================================================
+**
+** L O C A L - V A R I A B L E S
+**
+** =========================================================================*/
+
+/*
+ * GLOBALS
+ */
+volatile void __iomem *idpram_base = NULL;
+volatile IDPRAM_SFR __iomem *idpram_sfr_base = NULL;
+
+static volatile u16 *dpram_mbx_BA;
+static volatile u16 *dpram_mbx_AB;
+
+struct wake_lock dpram_wake_lock = {.name = NULL};
+static atomic_t dpram_write_lock;
+static atomic_t dpram_read_lock;
+
+static int g_phone_sync = 0;
+static int g_dump_on = 0;
+static int g_dpram_wpend = IDPRAM_WPEND_UNLOCK;
+struct completion g_complete_dpramdown;
+static int g_cp_reset_cnt = 0;
+static int g_phone_power_off_sequence = 0;
+
+static struct tty_driver *dpram_tty_driver;
+static struct tty_struct *dpram_tty[MAX_INDEX];
+static struct ktermios *dpram_termios[MAX_INDEX];
+static struct ktermios *dpram_termios_locked[MAX_INDEX];
+static struct pdp_info *pdp_table[MAX_PDP_CONTEXT];
+
+static dpram_tasklet_data_t dpram_tasklet_data[MAX_INDEX];
+
+static dpram_device_t dpram_table[MAX_INDEX] =
+{
+ {
+ .in_head_addr = DPRAM_PHONE2PDA_FORMATTED_HEAD_ADDRESS,
+ .in_tail_addr = DPRAM_PHONE2PDA_FORMATTED_TAIL_ADDRESS,
+ .in_buff_addr = DPRAM_PHONE2PDA_FORMATTED_BUFFER_ADDRESS,
+ .in_buff_size = DPRAM_PHONE2PDA_FORMATTED_BUFFER_SIZE,
+ .in_head_saved = 0,
+ .in_tail_saved = 0,
+
+ .out_head_addr = DPRAM_PDA2PHONE_FORMATTED_HEAD_ADDRESS,
+ .out_tail_addr = DPRAM_PDA2PHONE_FORMATTED_TAIL_ADDRESS,
+ .out_buff_addr = DPRAM_PDA2PHONE_FORMATTED_BUFFER_ADDRESS,
+ .out_buff_size = DPRAM_PDA2PHONE_FORMATTED_BUFFER_SIZE,
+ .out_head_saved = 0,
+ .out_tail_saved = 0,
+
+ .mask_req_ack = INT_MASK_REQ_ACK_F,
+ .mask_res_ack = INT_MASK_RES_ACK_F,
+ .mask_send = INT_MASK_SEND_F,
+ },
+ {
+ .in_head_addr = DPRAM_PHONE2PDA_RAW_HEAD_ADDRESS,
+ .in_tail_addr = DPRAM_PHONE2PDA_RAW_TAIL_ADDRESS,
+ .in_buff_addr = DPRAM_PHONE2PDA_RAW_BUFFER_ADDRESS,
+ .in_buff_size = DPRAM_PHONE2PDA_RAW_BUFFER_SIZE,
+ .in_head_saved = 0,
+ .in_tail_saved = 0,
+
+ .out_head_addr = DPRAM_PDA2PHONE_RAW_HEAD_ADDRESS,
+ .out_tail_addr = DPRAM_PDA2PHONE_RAW_TAIL_ADDRESS,
+ .out_buff_addr = DPRAM_PDA2PHONE_RAW_BUFFER_ADDRESS,
+ .out_buff_size = DPRAM_PDA2PHONE_RAW_BUFFER_SIZE,
+ .out_head_saved = 0,
+ .out_tail_saved = 0,
+
+ .mask_req_ack = INT_MASK_REQ_ACK_R,
+ .mask_res_ack = INT_MASK_RES_ACK_R,
+ .mask_send = INT_MASK_SEND_R,
+ },
+};
+
+static unsigned int __log_level__ = (DL_IPC|DL_WARN|DL_NOTICE|DL_INFO|DL_DEBUG);
+
+#if defined(PRINT_DPRAM_WRITE) || defined(PRINT_DPRAM_READ)
+static char print_buff[128];
+#endif
+
+static atomic_t raw_txq_req_ack_rcvd;
+static atomic_t fmt_txq_req_ack_rcvd;
+struct delayed_work phone_active_work;
+
+/* For Dual Core*/
+static DEFINE_SPINLOCK(mux_tty_lock);
+
+
+/*
+** TASKLET DECLARATIONs
+*/
+static void res_ack_tasklet_handler(unsigned long data);
+static void fmt_rcv_tasklet_handler(unsigned long data);
+static void raw_rcv_tasklet_handler(unsigned long data);
+
+static DECLARE_TASKLET(fmt_send_tasklet, fmt_rcv_tasklet_handler, 0);
+static DECLARE_TASKLET(raw_send_tasklet, raw_rcv_tasklet_handler, 0);
+static DECLARE_TASKLET(fmt_res_ack_tasklet, res_ack_tasklet_handler, (unsigned long)&dpram_table[FORMATTED_INDEX]);
+static DECLARE_TASKLET(raw_res_ack_tasklet, res_ack_tasklet_handler, (unsigned long)&dpram_table[RAW_INDEX]);
+static DEFINE_MUTEX(pdp_lock);
+
+
+/*
+** FUNCTION PROTOTYPEs
+*/
+static void dpram_drop_data(dpram_device_t *device);
+static int kernel_sec_dump_cp_handle2(void);
+static int dpram_phone_getstatus(void);
+static void dpram_send_mbx_BA(u16 irq_mask);
+static void dpram_send_mbx_BA_cmd(u16 irq_mask);
+static void dpram_power_down(void);
+static void dpram_powerup_start(void);
+static int register_interrupt_handler(void);
+static irqreturn_t dpram_irq_handler(int irq, void *dev_id);
+
+
+static inline struct pdp_info * pdp_get_dev(u8 id);
+static inline void check_pdp_table(const char*, int);
+static void cmd_error_display_handler(void);
+
+
+#ifdef _ENABLE_ERROR_DEVICE
+static unsigned int dpram_err_len = 0;
+static char dpram_err_buf[DPRAM_ERR_MSG_LEN];
+static unsigned int dpram_err_cause = 0;
+
+static unsigned int dpram_dump_len = 0;
+static char cp_ramdump_buff[16384];
+
+struct class *dpram_err_class;
+struct class *dpram_dump_class;
+
+static DECLARE_WAIT_QUEUE_HEAD(dpram_err_wait_q);
+static DECLARE_WAIT_QUEUE_HEAD(dpram_dump_wait_q);
+
+static struct fasync_struct *dpram_err_async_q;
+static struct fasync_struct *dpram_dump_async_q;
+
+extern void usb_switch_mode(int);
+#ifdef CONFIG_SEC_DEBUG
+extern int get_sec_debug_level(void);
+#endif
+#endif /* _ENABLE_ERROR_DEVICE */
+
+
+#ifndef DISABLE_IPC_DEBUG
+typedef struct {
+ unsigned char start_flag;
+ unsigned char hdlc_length[2];
+ unsigned char hdlc_control;
+ unsigned char ipc_length[2];
+ unsigned char msg_seq;
+ unsigned char ack_seq;
+ unsigned char main_cmd;
+ unsigned char sub_cmd;
+ unsigned char cmd_type;
+ unsigned char parameter[1024];
+} dpram_fmt_frame;
+#endif
+
+
+#if 1
+u32 dpram_write_magic_code(u32 code)
+{
+ u32 address = 0;
+ u32 value = 0;
+
+ address = (u32)(DPRAM_VBASE + DPRAM_MAGIC_CODE_ADDRESS);
+
+ LOGA("Code : 0x%08x, Magic code address : 0x%08x\n", code, address);
+
+ memcpy_toio((void *)address, (void *)&code, 4);
+ memcpy_fromio((void *)&value, (void *)address, 4);
+
+ LOGA("DPRAM Read Magic = 0x%08x\n", value);
+
+ if (value != code)
+ LOGE("value != code\n");
+
+ return (value == code);
+}
+
+static void DRV_Setting_ModemUploadMode(void)
+{
+
+ dpram_write_magic_code(QSC_UPLOAD_MODE);
+}
+
+static void DRV_Wait_ModemInit(void)
+{
+
+ while (!gpio_get_value(GPIO_QSC_PHONE_ACTIVE)) {
+ msleep(100);
+ printk(".");
+ }
+ printk("\n");
+}
+
+static inline void dpram_clear_modem_command(void)
+{
+ iowrite16(0, (void*)(DPRAM_VBASE + DPRAM_PHONE2PDA_INTERRUPT_ADDRESS));
+}
+
+static inline u16 dpram_read_command(void)
+{
+ return ioread16((void*)(DPRAM_VBASE + DPRAM_PHONE2PDA_INTERRUPT_ADDRESS));
+}
+
+static void dpram_send_command(u16 nCmd)
+{
+ dpram_clear_modem_command();
+ iowrite16(nCmd, (void*)(DPRAM_VBASE + DPRAM_PDA2PHONE_INTERRUPT_ADDRESS));
+}
+
+/* return value
+// -1 : false
+// 0 : continue
+// 1 : true */
+#define CMD_FALSE -1
+#define CMD_RETRY 0
+#define CMD_TRUE 1
+
+static u32 check_command(u16 intr, u16 mask)
+{
+ if (intr == 0) {
+ return CMD_RETRY;
+ } else {
+ if ((intr & MASK_CMD_VALID) != MASK_CMD_VALID) {
+ return CMD_RETRY;
+ }
+ else if ((intr & MASK_PDA_CMD) == MASK_PDA_CMD) {
+ return CMD_RETRY;
+ }
+ else if ((intr & MASK_PHONE_CMD) == MASK_PHONE_CMD) {
+ if ((intr & mask) == mask)
+ return CMD_TRUE;
+ else
+ return CMD_FALSE;
+ }
+ else
+ return CMD_RETRY;
+ }
+}
+
+static u16 dpram_wait_response(u16 nCmd)
+{
+ u16 intr, ret;
+ int i;
+
+ for (i = 0; i < 100; i++)
+ {
+ intr = dpram_read_command();
+ ret = check_command(intr, nCmd);
+ if(ret == CMD_TRUE)
+ return CMD_TRUE;
+ else if(ret == CMD_FALSE)
+ return CMD_FALSE;
+ wait_for_completion_interruptible_timeout(&wait_dump_data, (HZ/100));
+ init_completion(&wait_dump_data);
+ }
+ return CMD_RETRY;
+}
+
+static void dpram_clear_response(void)
+{
+ init_completion(&wait_dump_data);
+ IDPRAM_INT_CLEAR();
+ dpram_clear_modem_command();
+}
+
+static void _Request_ModemData(u32 addr, u32 size)
+{
+ DumpCMDHeader header;
+ u32 rx_required = 0;
+ int ret = 0;
+
+ memset(&header, 0, sizeof(header));
+
+ rx_required = min(size - dump_rx_total, (u32)CP_RAMDUMP_BUFFER_SIZE);
+
+ header.addr = addr + dump_rx_total;
+ header.size = rx_required;
+ header.copyto_offset = 0x38000010;
+
+ memcpy_toio((void*)DPRAM_CP_HEADER_START_ADDRESS, (void*)&header, sizeof(header));
+
+ /* Wait for ACK */
+ dpram_send_command(CMD_CP_RAMDUMP_SEND_REQ);
+ ret = dpram_wait_response(CMD_CP_RAMDUMP_SEND_RESP|MASK_CMD_RESULT_SUCCESS);
+ if (!ret) {
+ LOGE("Failed in dpram_wait_response()!!!\n");
+ return;
+ }
+ dpram_clear_response();
+
+ /* Copy dump from DPRAM to local buffer */
+ memcpy_fromio((void*)cp_ramdump_buff, (void*)DPRAM_CP_RAMDUMP_START_ADDRESS, CP_RAMDUMP_BUFFER_SIZE);
+
+ /* Prepare to pass the dump data to RIL */
+ dpram_dump_len = rx_required;
+
+ dump_rx_total += rx_required;
+}
+
+static void setup_cp_ramdump(void)
+{
+ DRV_Setting_ModemUploadMode();
+ DRV_Wait_ModemInit();
+}
+
+static void start_cp_ramdump(void)
+{
+ int i, ret;
+
+ for (i = 0; i < 30; i++)
+ {
+ dpram_send_command(CMD_CP_RAMDUMP_START_REQ);
+ ret = dpram_wait_response(CMD_CP_RAMDUMP_START_RESP|MASK_CMD_RESULT_SUCCESS);
+ if (ret == CMD_TRUE) {
+ LOGA("succeeded in dpram_wait_response()!!!\n");
+ dpram_clear_response();
+ return;
+ } else if (ret == CMD_FALSE) {
+ LOGE("Failed in dpram_wait_response()!!!\n");
+ dpram_clear_response();
+ return;
+ }
+ LOGA("RETRY is required in dpram_wait_response()!!!\n");
+ }
+
+ LOGE("Failed in dpram_wait_response()!!!\n");
+ dpram_clear_response();
+}
+
+static void receive_cp_ramdump(void)
+{
+ u32 dump_start_addr, dump_end_addr, dump_size;
+
+ dump_start_addr = cp_mem_info.cp_mem_region[0].start_addr;
+ dump_end_addr = cp_mem_info.cp_mem_region[0].end_addr;
+ dump_size = (dump_end_addr - dump_start_addr) + 1;
+
+ /* read modem RAMDUMP data */
+ _Request_ModemData(dump_start_addr, dump_size);
+}
+
+static void close_cp_ramdump(void)
+{
+ int ret;
+
+ dpram_send_command(CMD_CP_RAMDUMP_SEND_DONE_REQ);
+ ret = dpram_wait_response(CMD_CP_RAMDUMP_SEND_DONE_RESP|MASK_CMD_RESULT_SUCCESS);
+ if (!ret) {
+ LOGE("Failed in dpram_wait_response()!!!\n");
+ return;
+ }
+ LOGA("succeeded in dpram_wait_response()!!!\n");
+ dpram_clear_response();
+}
+#endif
+
+
+/*
+** tty related functions.
+*/
+static inline void dpram_byte_align(unsigned long dest, unsigned long src)
+{
+ volatile u16 *p_dest;
+ u16 *p_src;
+
+ if ( (dest & 1) && (src & 1) )
+ {
+ p_dest = (u16 *)(dest - 1);
+ p_src = (u16 *)(src - 1);
+
+ *p_dest = (*p_dest & 0x00FF) | (*p_src & 0xFF00);
+ }
+ else if ( (dest & 1) && !(src & 1) )
+ {
+ p_dest = (u16 *)(dest - 1);
+ p_src = (u16 *)src;
+ *p_dest = (*p_dest & 0x00FF) | ((*p_src << 8) & 0xFF00);
+ }
+ else if ( !(dest & 1) && (src & 1) )
+ {
+ p_dest = (u16 *)dest;
+ p_src = (u16 *)(src - 1);
+ *p_dest = (*p_dest & 0xFF00) | ((*p_src >> 8) & 0x00FF);
+ }
+ else //if ( !(dest & 1) && !(src & 1) )
+ {
+ p_dest = (u16 *)dest;
+ p_src = (u16 *)src;
+ *p_dest = (*p_dest & 0xFF00) | (*p_src & 0x00FF);
+ }
+#if 0
+ else
+ {
+ LOGE("oops.~\n");
+ }
+#endif
+}
+
+static inline void _memcpy(void *p_dest, const void *p_src, int size)
+{
+ unsigned long dest = (unsigned long)p_dest;
+ unsigned long src = (unsigned long)p_src;
+
+ if (size <= 0)
+ return;
+
+ if (dest & 1)
+ {
+ /* If the destination address is odd, store the first byte at first.*/
+ dpram_byte_align(dest, src);
+ dest++, src++;
+ size--;
+ }
+
+ if (size & 1)
+ {
+ /* If the size is odd, store the last byte at first.*/
+ dpram_byte_align(dest + size - 1, src + size - 1);
+ size--;
+ }
+
+ if (src & 1)
+ {
+ volatile u16 *d = (u16 *)dest;
+ unsigned char *s = (u8 *)src;
+
+ size >>= 1;
+
+ while (size--)
+ {
+ *d++ = s[0] | (s[1] << 8);
+ s += 2;
+ }
+ }
+ else
+ {
+ volatile u16 *d = (u16 *)dest;
+ u16 *s = (u16 *)src;
+
+ size >>= 1;
+
+ while (size--)
+ {
+ *d++ = *s++;
+ }
+ }
+}
+
+/* Note the use of non-standard return values (0=match, 1=no-match) */
+static inline int _memcmp(u8 *dest, u8 *src, int size)
+{
+ while( size-- )
+ {
+ if( *dest++ != *src++ )
+ return 1 ;
+ }
+
+ return 0 ;
+}
+
+
+#define WRITE_TO_DPRAM(dest, src, size) \
+ _memcpy((void *)(DPRAM_VBASE + dest), src, size)
+
+#define READ_FROM_DPRAM(dest, src, size) \
+ _memcpy(dest, (void *)(DPRAM_VBASE + src), size)
+
+
+static inline int WRITE_TO_DPRAM_VERIFY(u32 dest, void *src, int size)
+{
+ int cnt = 3;
+
+ while (cnt--)
+ {
+ _memcpy((void *)(DPRAM_VBASE + dest), (void *)src, size);
+
+ if (!_memcmp((u8 *)(DPRAM_VBASE + dest), (u8 *)src, size))
+ return 0;
+ }
+
+ return -1;
+}
+
+static inline int READ_FROM_DPRAM_VERIFY(void *dest, u32 src, int size)
+{
+ int cnt = 3;
+
+ while (cnt--)
+ {
+ _memcpy((void *)dest, (void *)(DPRAM_VBASE + src), size);
+
+ if (!_memcmp((u8 *)dest, (u8 *)(DPRAM_VBASE + src), size))
+ return 0;
+ }
+
+ return -1;
+}
+
+static int dpram_lock_write(const char* func)
+{
+ int lock_value;
+
+ lock_value = (g_dpram_wpend == IDPRAM_WPEND_LOCK) ? -3 : atomic_inc_return(&dpram_write_lock);
+ if ( lock_value != 1 )
+ LOGE("lock_value (%d) != 1\n", lock_value);
+
+ return lock_value;
+}
+
+static void dpram_unlock_write(const char* func)
+{
+ int lock_value;
+
+ lock_value = atomic_dec_return(&dpram_write_lock);
+
+ if ( lock_value != 0 )
+ LOGE("lock_value (%d) != 0\n", lock_value);
+}
+
+// TODO:
+// because it is dpram device, I think read_lock don't need but I will use for holding wake_lock
+static int dpram_get_lock_read(void)
+{
+ return atomic_read(&dpram_read_lock);
+}
+
+static int dpram_lock_read(const char* func)
+{
+ int lock_value;
+
+ lock_value = atomic_inc_return(&dpram_read_lock);
+ if(lock_value !=1)
+ LOGE("(%s, lock) lock_value: %d\n", func, lock_value);
+ wake_lock_timeout(&dpram_wake_lock, HZ*6);
+ return 0;
+}
+
+static void dpram_unlock_read(const char* func)
+{
+ int lock_value;
+
+ lock_value = atomic_dec_return(&dpram_read_lock);
+
+ if(lock_value !=0)
+ LOGE("(%s, lock) lock_value: %d\n", func, lock_value);
+
+ wake_unlock(&dpram_wake_lock);
+}
+
+
+#if defined(PRINT_DPRAM_WRITE) || defined(PRINT_DPRAM_READ)
+static void dpram_print_packet(char *buf, int len)
+{
+ int i = 0;
+ LOGA("len = %d\n", len);
+
+ print_buff[0] = '\0';
+
+ for (i = 0; i < len; i++)
+ {
+ sprintf((print_buff + (i%16)*3), "%02x \0", *((char *)buf + i));
+ if ( (i%16) == 15 )
+ {
+ LOGA("%s\n", print_buff);
+ print_buff[0] = '\0';
+ }
+ }
+
+ if ( strlen(print_buff) )
+ {
+ LOGA("%s\n", print_buff);
+ }
+}
+#endif /*PRINT_DPRAM_WRITE || PRINT_DPRAM_READ*/
+
+static int dpram_write(dpram_device_t *device, const unsigned char *buf, int len)
+{
+ int retval = 0;
+ int size = 0;
+ u16 head, tail, magic, access ;
+ u16 irq_mask = 0;
+ struct pdp_hdr *pdp_hdr_ptr = (struct pdp_hdr *)(buf + 1);
+ int curr_pkt_len = 0, free_space = 0;
+
+ //PRINT_FUNC();
+#ifdef PRINT_DPRAM_WRITE
+ PRINT_FUNC();
+ dpram_print_packet(buf, len);
+#endif
+
+ if (g_dump_on) {
+ LOGA("g_dump_on == 1\n");
+ return 0;
+ }
+
+ // If the phone is down, let's reset everything and fail the write.
+#ifdef CDMA_IPC_C210_IDPRAM
+ magic = ioread16((void *)(DPRAM_VBASE + DPRAM_MAGIC_CODE_ADDRESS));
+ access = ioread16((void *)(DPRAM_VBASE + DPRAM_ACCESS_ENABLE_ADDRESS));
+#else
+ READ_FROM_DPRAM_VERIFY(&magic, DPRAM_MAGIC_CODE_ADDRESS, sizeof(magic));
+ READ_FROM_DPRAM_VERIFY(&access, DPRAM_ACCESS_ENABLE_ADDRESS, sizeof(access));
+#endif
+
+ /* Gaudi : modified ril power off sequence */
+ //if (g_phone_sync != 1 || !access || magic != 0xAA)
+ if (!access || magic != 0xAA)
+ {
+ LOGE("Phone has not booted yet!!! (phone_sync = %d)\n", g_phone_sync);
+ return -EFAULT;
+ }
+
+ if ( dpram_lock_write(__func__) < 0 )
+ {
+ return -EAGAIN;
+ }
+
+#ifdef CDMA_IPC_C210_IDPRAM
+ head = ioread16((void *)(DPRAM_VBASE + device->out_head_addr));
+ tail = ioread16((void *)(DPRAM_VBASE + device->out_tail_addr));
+#else
+ READ_FROM_DPRAM_VERIFY(&head, device->out_head_addr, sizeof(head));
+ READ_FROM_DPRAM_VERIFY(&tail, device->out_tail_addr, sizeof(tail));
+#endif
+
+ // Make sure the queue tail pointer is valid.
+ if( tail >= device->out_buff_size || head >= device->out_buff_size )
+ {
+ head = tail = 0;
+#ifdef CDMA_IPC_C210_IDPRAM
+ iowrite16(head, (void *)(DPRAM_VBASE + device->out_head_addr));
+ iowrite16(tail, (void *)(DPRAM_VBASE + device->out_tail_addr));
+#else
+ WRITE_TO_DPRAM_VERIFY(device->out_head_addr, &head, sizeof(head));
+ WRITE_TO_DPRAM_VERIFY(device->out_tail_addr, &tail, sizeof(tail));
+#endif
+ dpram_unlock_write(__func__);
+ return 0 ;
+ }
+
+#ifdef PRINT_DPRAM_WRITE
+ LOGA("head: %d, tail: %d\n", head, tail);
+#endif
+
+ /* check free space */
+ curr_pkt_len = pdp_hdr_ptr->len + 2; /*include SOF/EOF*/
+ free_space = (head < tail) ? tail-head -1 : device->out_buff_size + tail - head - 1;
+
+ if (curr_pkt_len > free_space) {
+ LOGE("WRITE: No space in Q, curr_pkt_len[%d] free_space[%d] head[%d] tail[%d]\n",
+ curr_pkt_len, free_space, head, tail);
+ dpram_unlock_write(__func__);
+ return -EAGAIN;
+ }
+
+ // +++++++++ head ---------- tail ++++++++++ //
+ if (head < tail) {
+ size = tail - head - 1;
+ size = (len > size) ? size : len;
+ WRITE_TO_DPRAM(device->out_buff_addr + head, buf, size);
+ retval = size;
+ }
+
+ // tail +++++++++++++++ head --------------- //
+ else if (tail == 0) {
+ size = device->out_buff_size - head - 1;
+ size = (len > size) ? size : len;
+ WRITE_TO_DPRAM(device->out_buff_addr + head, buf, size);
+ retval = size;
+ }
+
+ // ------ tail +++++++++++ head ------------ //
+ else {
+ size = device->out_buff_size - head;
+ size = (len > size) ? size : len;
+ WRITE_TO_DPRAM(device->out_buff_addr + head, buf, size);
+ retval = size;
+
+ if (len > retval) {
+ size = (len - retval > tail - 1) ? tail - 1 : len - retval;
+ WRITE_TO_DPRAM(device->out_buff_addr, buf + retval, size);
+ retval += size;
+ }
+ }
+
+ /* @LDK@ calculate new head */
+ head = (u16)((head + retval) % device->out_buff_size);
+#ifdef CDMA_IPC_C210_IDPRAM
+ iowrite16(head, (void *)(DPRAM_VBASE + device->out_head_addr));
+#else
+ WRITE_TO_DPRAM_VERIFY(device->out_head_addr, &head, sizeof(head));
+#endif
+ device->out_head_saved = head;
+ device->out_tail_saved = tail;
+
+ /* @LDK@ send interrupt to the phone, if.. */
+ irq_mask = INT_MASK_VALID;
+
+ if (retval > 0)
+ irq_mask |= device->mask_send;
+
+ if (len > retval)
+ irq_mask |= device->mask_req_ack;
+
+ dpram_unlock_write(__func__);
+ dpram_send_mbx_BA(irq_mask);
+
+ return retval;
+}
+
+static inline int dpram_tty_insert_data(dpram_device_t *device, const u8 *psrc, u16 size)
+{
+#define CLUSTER_SEGMENT 1500
+
+ u16 copied_size = 0;
+ int retval = 0;
+
+#ifdef PRINT_DPRAM_READ
+ dpram_print_packet(psrc, size);
+#endif
+
+ if ( size > CLUSTER_SEGMENT && (device->serial.tty->index == 1) )
+ {
+ while (size)
+ {
+ copied_size = (size > CLUSTER_SEGMENT) ? CLUSTER_SEGMENT : size;
+ tty_insert_flip_string(device->serial.tty, psrc + retval, copied_size);
+
+ size -= copied_size;
+ retval += copied_size;
+ }
+
+ return retval;
+ }
+
+ return tty_insert_flip_string(device->serial.tty, psrc, size);
+}
+
+static int dpram_read_fmt(dpram_device_t *device, const u16 non_cmd)
+{
+ int retval = 0;
+ int retval_add = 0;
+ int size = 0;
+ u16 head, tail;
+
+ dpram_lock_read(__func__);
+
+#ifdef CDMA_IPC_C210_IDPRAM
+ head = ioread16((void *)(DPRAM_VBASE + device->in_head_addr));
+ tail = ioread16((void *)(DPRAM_VBASE + device->in_tail_addr));
+#else
+ READ_FROM_DPRAM_VERIFY(&head, device->in_head_addr, sizeof(head));
+ READ_FROM_DPRAM_VERIFY(&tail, device->in_tail_addr, sizeof(tail));
+#endif
+
+#ifdef PRINT_DPRAM_READ
+ LOGA("head: %d, tail: %d\n", head, tail);
+#endif
+
+ if (head != tail)
+ {
+ u16 up_tail = 0;
+
+ // ------- tail ########## head -------- //
+ if (head > tail)
+ {
+ size = head - tail;
+ retval = dpram_tty_insert_data(device, (u8 *)(DPRAM_VBASE + (device->in_buff_addr + tail)), size);
+ if (size != retval)
+ LOGE("size: %d, retval: %d\n", size, retval);
+ }
+ // ####### head ------------ tail ###### //
+ else
+ {
+ int tmp_size = 0;
+
+ // Total Size.
+ size = device->in_buff_size - tail + head;
+
+ // 1. tail -> buffer end.
+ tmp_size = device->in_buff_size - tail;
+ retval = dpram_tty_insert_data(device, (u8 *)(DPRAM_VBASE + (device->in_buff_addr + tail)), tmp_size);
+ if (tmp_size != retval)
+ {
+ LOGE("size: %d, retval: %d\n", size, retval);
+ }
+
+ // 2. buffer start -> head.
+ if (size > tmp_size)
+ {
+ retval_add = dpram_tty_insert_data(device, (u8 *)(DPRAM_VBASE + device->in_buff_addr), size - tmp_size);
+ retval += retval_add;
+
+ if((size - tmp_size)!= retval_add)
+ {
+ LOGE("size - tmp_size: %d, retval_add: %d\n", size - tmp_size, retval_add);
+ }
+ }
+ }
+
+ /* new tail */
+ up_tail = (u16)((tail + retval) % device->in_buff_size);
+#ifdef CDMA_IPC_C210_IDPRAM
+ iowrite16(up_tail, (void *)(DPRAM_VBASE + device->in_tail_addr));
+#else
+ WRITE_TO_DPRAM_VERIFY(device->in_tail_addr, &up_tail, sizeof(up_tail));
+#endif
+ }
+
+
+ device->in_head_saved = head;
+ device->in_tail_saved = tail;
+
+ dpram_unlock_read(__func__);
+
+ if ( atomic_read(&fmt_txq_req_ack_rcvd) > 0 || (non_cmd & device->mask_req_ack) )
+ {
+ // there is a situation where the q become full after we reached the tasklet.
+ // so this logic will allow us to send the RES_ACK as soon as we read 1 packet and CP get a chance to
+ // write another buffer.
+// LOGA("Sending INT_MASK_RES_ACK_F\n");
+ dpram_send_mbx_BA(INT_NON_COMMAND(device->mask_res_ack));
+ atomic_set(&fmt_txq_req_ack_rcvd, 0);
+ }
+
+ return retval;
+
+}
+
+static int dpram_read_raw(dpram_device_t *device, const u16 non_cmd)
+{
+ int retval = 0;
+ int size = 0;
+ u16 head, tail;
+ u16 up_tail = 0;
+ int ret;
+ size_t len;
+ struct pdp_info *dev = NULL;
+ struct pdp_hdr hdr;
+ u16 read_offset;
+ u8 len_high, len_low, id, control;
+ u16 pre_data_size; //pre_hdr_size,
+ u8 ch;
+
+ dpram_lock_read(__func__);
+
+#ifdef CDMA_IPC_C210_IDPRAM
+ head = ioread16((void *)(DPRAM_VBASE + device->in_head_addr));
+ tail = ioread16((void *)(DPRAM_VBASE + device->in_tail_addr));
+#else
+ READ_FROM_DPRAM_VERIFY(&head, device->in_head_addr, sizeof(head));
+ READ_FROM_DPRAM_VERIFY(&tail, device->in_tail_addr, sizeof(tail));
+#endif
+
+#ifdef PRINT_DPRAM_HEAD_TAIL
+ LOGA("head: %d, tail: %d\n", head, tail);
+#endif
+
+ if (head != tail)
+ {
+ up_tail = 0;
+
+ if (head > tail)
+ /* ----- (tail) 7f 00 00 7e (head) ----- */
+ size = head - tail;
+ else
+ /* 00 7e (head) ----------- (tail) 7f 00 */
+ size = device->in_buff_size - tail + head;
+
+ read_offset = 0;
+#ifdef PRINT_DPRAM_HEAD_TAIL
+ LOGA("head: %d, tail: %d, size: %d\n", head, tail, size);
+#endif
+ while (size)
+ {
+ READ_FROM_DPRAM(&ch, device->in_buff_addr +((u16)(tail + read_offset) % device->in_buff_size), sizeof(ch));
+
+ if (ch == 0x7F)
+ {
+ read_offset ++;
+ }
+ else
+ {
+ LOGE("First byte: 0x%02x, drop bytes: %d, buff addr: 0x%08lx, "
+ "read addr: 0x%08lx\n",ch, size,
+ (device->in_buff_addr), (device->in_buff_addr +
+ ((u16)(tail + read_offset) % device->in_buff_size)));
+ dpram_drop_data(device);
+ dpram_unlock_read(__func__);
+ return -1;
+ }
+
+ len_high = len_low = id = control = 0;
+ READ_FROM_DPRAM(&len_low, device->in_buff_addr + ((u16)(tail + read_offset) % device->in_buff_size) ,sizeof(len_high));
+ read_offset ++;
+ READ_FROM_DPRAM(&len_high, device->in_buff_addr + ((u16)(tail + read_offset) % device->in_buff_size) ,sizeof(len_low));
+ read_offset ++;
+ READ_FROM_DPRAM(&id, device->in_buff_addr + ((u16)(tail + read_offset) % device->in_buff_size) ,sizeof(id));
+ read_offset ++;
+ READ_FROM_DPRAM(&control, device->in_buff_addr + ((u16)(tail + read_offset) % device->in_buff_size) ,sizeof(control));
+ read_offset ++;
+
+ hdr.len = len_high <<8 | len_low;
+ hdr.id = id;
+ hdr.control = control;
+
+ len = hdr.len - sizeof(struct pdp_hdr);
+ if (len <= 0)
+ {
+ LOGE("oops... read_offset: %d, len: %d, hdr.id: %d\n", read_offset, len, hdr.id);
+ dpram_drop_data(device);
+ dpram_unlock_read(__func__);
+ return -1;
+ }
+
+ dev = pdp_get_dev(hdr.id);
+#ifdef PRINT_DPRAM_READ
+ LOGA("read_offset: %d, len: %d, hdr.id: %d\n", read_offset, len, hdr.id);
+#endif
+ if (!dev)
+ {
+ LOGE("RAW READ Failed.. NULL dev detected \n");
+ check_pdp_table(__func__, __LINE__);
+ dpram_drop_data(device);
+ dpram_unlock_read(__func__);
+ return -1;
+ }
+
+ if (dev->vs_dev.tty != NULL && dev->vs_dev.refcount)
+ {
+ if((u16)(tail + read_offset) % device->in_buff_size + len < device->in_buff_size)
+ {
+ ret = tty_insert_flip_string(dev->vs_dev.tty, (u8 *)(DPRAM_VBASE + (device->in_buff_addr + (u16)(tail + read_offset) % device->in_buff_size)), len);
+ dev->vs_dev.tty->low_latency = 0;
+ tty_flip_buffer_push(dev->vs_dev.tty);
+ }
+ else
+ {
+ pre_data_size = device->in_buff_size - (tail + read_offset);
+ ret = tty_insert_flip_string(dev->vs_dev.tty, (u8 *)(DPRAM_VBASE + (device->in_buff_addr + tail + read_offset)), pre_data_size);
+ ret += tty_insert_flip_string(dev->vs_dev.tty, (u8 *)(DPRAM_VBASE + (device->in_buff_addr)),len - pre_data_size);
+ dev->vs_dev.tty->low_latency = 0;
+ tty_flip_buffer_push(dev->vs_dev.tty);
+#ifdef PRINT_DPRAM_READ
+ LOGE("RAW pre_data_size: %d, len-pre_data_size: %d, ret: %d\n", pre_data_size, len- pre_data_size, ret);
+#endif
+ }
+ }
+ else
+ {
+ LOGE("tty channel(id:%d) is not opened!!!\n", dev->id);
+ ret = len;
+ }
+
+ if (!ret)
+ {
+ LOGE("(tty_insert_flip_string) drop bytes: %d, "
+ "buff addr: 0x%08lx\n, read addr: 0x%08lx\n",
+ size, (device->in_buff_addr),
+ (device->in_buff_addr + ((u16)(tail + read_offset)
+ % device->in_buff_size)));
+ dpram_drop_data(device);
+ dpram_unlock_read(__func__);
+ return -1;
+ }
+
+ read_offset += ret;
+#ifdef PRINT_DPRAM_READ
+ LOGA("read_offset: %d, ret: %d\n", read_offset, ret);
+#endif
+ READ_FROM_DPRAM(&ch, (device->in_buff_addr + ((u16)(tail + read_offset) % device->in_buff_size)), sizeof(ch));
+ if (ch == 0x7e)
+ {
+ read_offset++;
+ }
+ else
+ {
+ LOGE("Last byte: 0x%02x, drop bytes: %d, buff addr: 0x%08lx, "
+ "read addr: 0x%08lx\n",ch, size, (device->in_buff_addr),
+ (device->in_buff_addr + ((u16)(tail + read_offset) %
+ device->in_buff_size)));
+ dpram_drop_data(device);
+ dpram_unlock_read(__func__);
+ return -1;
+ }
+
+ size -= (ret + sizeof(struct pdp_hdr) + 2);
+ retval += (ret + sizeof(struct pdp_hdr) + 2);
+
+ if (size < 0)
+ {
+ LOGE("something wrong....\n");
+ break;
+ }
+
+ }
+
+ up_tail = (u16)((tail + read_offset) % device->in_buff_size);
+#ifdef CDMA_IPC_C210_IDPRAM
+ iowrite16(up_tail, (void *)(DPRAM_VBASE + device->in_tail_addr));
+#else
+ WRITE_TO_DPRAM_VERIFY(device->in_tail_addr, &up_tail, sizeof(up_tail));
+#endif
+ }
+
+ device->in_head_saved = head;
+ device->in_tail_saved = tail;
+
+ dpram_unlock_read(__func__);
+
+ if ( atomic_read(&raw_txq_req_ack_rcvd) > 0 || (non_cmd & device->mask_req_ack) )
+ {
+ // there is a situation where the q become full after we reached the tasklet.
+ // so this logic will allow us to send the RES_ACK as soon as we read 1 packet and CP get a chance to
+ // write another buffer.
+// LOGA("Sending INT_MASK_RES_ACK_R\n");
+ dpram_send_mbx_BA(INT_NON_COMMAND(device->mask_res_ack));
+ atomic_set(&raw_txq_req_ack_rcvd, 0);
+ }
+
+ return retval;
+}
+
+static int dpram_init_magic_num(void)
+{
+ const u16 magic_code = 0x4D4E;
+ u16 acc_code = 0;
+ u16 ret_value = 0;
+
+ PRINT_FUNC();
+
+ if ( dpram_lock_write(__func__) < 0 )
+ return -EAGAIN;
+
+ /*write DPRAM disable code */
+ iowrite16(acc_code, (void *)(DPRAM_VBASE + DPRAM_ACCESS_ENABLE_ADDRESS));
+
+ /* write DPRAM magic code : Normal boot Magic - 0x4D4E*/
+ iowrite16(magic_code, (void *)(DPRAM_VBASE + DPRAM_MAGIC_CODE_ADDRESS));
+
+ /*write enable code */
+ acc_code = 0x0001;
+ iowrite16(acc_code, (void *)(DPRAM_VBASE + DPRAM_ACCESS_ENABLE_ADDRESS));
+
+ /*send init end code to phone */
+ dpram_unlock_write(__func__);
+
+ ret_value = ioread16((void *)(DPRAM_VBASE + DPRAM_MAGIC_CODE_ADDRESS));
+
+ LOGA("Read_MagicNum : 0x%04x\n", ret_value);
+
+ return 0;
+
+}
+
+
+#ifdef _ENABLE_ERROR_DEVICE
+void request_phone_reset(void)
+{
+ return;
+
+ /* char buf[DPRAM_ERR_MSG_LEN];
+ unsigned long flags;
+
+ dpram_init_magic_num();
+
+ memset((void *)buf, 0, sizeof (buf));
+
+ LOGE("CDMA reset cnt = %d\n", g_cp_reset_cnt);
+ if (g_cp_reset_cnt > 5)
+ {
+ buf[0] = '1';
+ buf[1] = ' ';
+ memcpy(buf+2, "$CDMA-DEAD", sizeof("$CDMA-DEAD"));
+ }
+ else
+ {
+ buf[0] = '8';
+ buf[1] = ' ';
+ memcpy(buf+2, "$PHONE-OFF", sizeof("$PHONE-OFF"));
+ }
+
+ LOGE("[PHONE ERROR] ->> %s\n", buf);
+ local_irq_save(flags);
+ memcpy(dpram_err_buf, buf, DPRAM_ERR_MSG_LEN);
+ dpram_err_len = 64;
+ local_irq_restore(flags);
+
+ wake_up_interruptible(&dpram_err_wait_q);
+ kill_fasync(&dpram_err_async_q, SIGIO, POLL_IN);*/
+}
+#endif
+
+
+static void dpram_send_mbx_BA(u16 irq_mask)
+{
+ if (g_dump_on)
+ return;
+
+#ifdef CDMA_IPC_C210_IDPRAM
+ iowrite16(irq_mask, (void *)dpram_mbx_BA);
+#else
+ *dpram_mbx_BA = irq_mask;
+#endif
+
+#ifdef PRINT_DPRAM_WRITE
+ LOG("mbx_BA = 0x%04X\n", irq_mask);
+#endif
+}
+
+
+/*
+ * dpram_send_mbx_BA_cmd()
+ * - for prevent CP interrupt command miss issue,
+ * below function check the CP dpram interrupt level before send interrupt
+ */
+#define DPRAM_CMD_SEND_RETRY_CNT 0x5
+static void dpram_send_mbx_BA_cmd(u16 irq_mask)
+{
+ int retry_cnt = DPRAM_CMD_SEND_RETRY_CNT;
+
+ if (g_dump_on)
+ return;
+
+ /* Set GPIO_PDA_ACTIVE as CP sometimes seems to read this pin as Low */
+ gpio_set_value(GPIO_PDA_ACTIVE, GPIO_LEVEL_HIGH);
+
+ while (gpio_get_value(GPIO_DPRAM_INT_CP_N) == 0 && retry_cnt--)
+ {
+ msleep(1);
+ LOGE("send cmd intr, retry cnt = %d\n", (DPRAM_CMD_SEND_RETRY_CNT-retry_cnt));
+
+ /* Set GPIO_PDA_ACTIVE as CP sometimes seems to read this pin as Low */
+ LOGA("Current GPIO_PDA_ACTIVE = %d\n", gpio_get_value(GPIO_PDA_ACTIVE) );
+ gpio_set_value(GPIO_PDA_ACTIVE, GPIO_LEVEL_HIGH);
+ LOGA("GPIO_PDA_ACTIVE = %d\n", gpio_get_value(GPIO_PDA_ACTIVE) );
+ }
+
+#ifdef CDMA_IPC_C210_IDPRAM
+ iowrite16(irq_mask, (void *)dpram_mbx_BA);
+#else
+ *dpram_mbx_BA = irq_mask;
+#endif
+
+#ifdef PRINT_DPRAM_WRITE
+ LOGA("mbx_BA = 0x%04X\n", irq_mask);
+#endif
+}
+
+
+static void dpram_clear(void)
+{
+ long i = 0;
+ long size = 0;
+ unsigned long flags;
+
+ u16 value = 0;
+
+ size = DPRAM_SIZE - (DPRAM_INTERRUPT_PORT_SIZE * 4);
+
+ /* @LDK@ clear DPRAM except interrupt area */
+ local_irq_save(flags);
+
+ for (i = DPRAM_PDA2PHONE_FORMATTED_HEAD_ADDRESS; i < size; i += 2)
+ {
+ iowrite16(0, (void *)(DPRAM_VBASE + i));
+ }
+
+ local_irq_restore(flags);
+
+ value = ioread16((void *)dpram_mbx_AB);
+}
+
+static int dpram_init_and_report(void)
+{
+ const u16 init_start = INT_COMMAND(MBX_CMD_INIT_START);
+ const u16 init_end = INT_COMMAND(MBX_CMD_INIT_END | AP_PLATFORM_ANDROID);
+ const u16 magic_code = 0x00AA;
+ u16 acc_code = 0;
+
+//#ifdef DEBUG_DPRAM_INT_HANDLER
+ PRINT_FUNC();
+//#endif
+
+ dpram_send_mbx_BA(init_start);
+
+ if ( dpram_lock_write(__func__) < 0 )
+ return -EAGAIN;
+
+ /* @LDK@ write DPRAM disable code */
+ iowrite16(acc_code, (void *)(DPRAM_VBASE + DPRAM_ACCESS_ENABLE_ADDRESS));
+
+ /* @LDK@ dpram clear */
+ dpram_clear();
+
+ /* @LDK@ write DPRAM magic code & enable code */
+ iowrite16(magic_code, (void *)(DPRAM_VBASE + DPRAM_MAGIC_CODE_ADDRESS));
+ acc_code = 0x0001;
+ iowrite16(acc_code, (void *)(DPRAM_VBASE + DPRAM_ACCESS_ENABLE_ADDRESS));
+
+ /* @LDK@ send init end code to phone */
+ dpram_unlock_write(__func__);
+
+ dpram_send_mbx_BA(init_end);
+
+//#ifdef DEBUG_DPRAM_INT_HANDLER
+ LOGA("Sent CMD_INIT_END(0x%04X) to Phone!!!\n", init_end);
+//#endif
+
+ g_phone_sync = 1;
+ g_cp_reset_cnt = 0;
+
+ return 0;
+}
+
+static inline int dpram_get_read_available(dpram_device_t *device)
+{
+ u16 head = 0, tail = 0, size = 0;
+
+#ifdef CDMA_IPC_C210_IDPRAM
+ head = ioread16((void *)(DPRAM_VBASE + device->in_head_addr));
+ tail = ioread16((void *)(DPRAM_VBASE + device->in_tail_addr));
+#else
+ READ_FROM_DPRAM_VERIFY(&head, device->in_head_addr, sizeof(head));
+ READ_FROM_DPRAM_VERIFY(&tail, device->in_tail_addr, sizeof(tail));
+#endif
+
+ if ( tail >= device->in_buff_size || head >= device->in_buff_size )
+ {
+ return 0;
+ }
+
+ size = ( head >= tail )? (head - tail) : (device->in_buff_size - tail + head);
+
+#ifdef PRINT_DPRAM_READ
+ if ( size > 0 )
+ LOGA("Data size = %d\n", size);
+#endif
+
+ return size;
+}
+
+static void dpram_drop_data(dpram_device_t *device)
+{
+ u16 head, tail;
+
+#ifdef CDMA_IPC_C210_IDPRAM
+ head = ioread16((void *)(DPRAM_VBASE + device->in_head_addr));
+ tail = ioread16((void *)(DPRAM_VBASE + device->in_tail_addr));
+#else
+ READ_FROM_DPRAM_VERIFY(&head, device->in_head_addr, sizeof(head));
+ READ_FROM_DPRAM_VERIFY(&tail, device->in_tail_addr, sizeof(tail));
+#endif
+
+ if( head >= device->in_buff_size || tail >= device->in_buff_size )
+ {
+ head = tail = 0 ;
+#ifdef CDMA_IPC_C210_IDPRAM
+ iowrite16(head, (void *)(DPRAM_VBASE + device->in_head_addr));
+#else
+ WRITE_TO_DPRAM_VERIFY(device->in_head_addr, &head, sizeof(head));
+#endif
+ }
+
+#ifdef CDMA_IPC_C210_IDPRAM
+ iowrite16(head, (void *)(DPRAM_VBASE + device->in_tail_addr));
+#else
+ WRITE_TO_DPRAM_VERIFY(device->in_tail_addr, &head, sizeof(head));
+#endif
+
+ LOGA("DROP head: %d, tail: %d\n", head, tail);
+}
+
+
+static void dpram_phone_power_on(void)
+{
+ u16 ret_value = 0;
+
+ PRINT_FUNC();
+
+ /*Add for Gadui : Normal boot Magic - 0x54424D4E*/
+ dpram_init_magic_num();
+
+ gpio_direction_output(GPIO_QSC_PHONE_RST, GPIO_LEVEL_HIGH);
+ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_LOW);
+ msleep(100);
+
+ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_HIGH);
+ msleep(400);
+ msleep(400);
+ msleep(200);
+ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_LOW);
+
+
+ ret_value = ioread16((void *)(DPRAM_VBASE + DPRAM_MAGIC_CODE_ADDRESS));
+ LOGA("Read_MagicNum : 0x%04x\n", ret_value);
+
+
+}
+
+static void dpram_only_qsc_phone_on_off(void)
+{
+ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_LOW);
+
+ LOGA("PHONE_ON level: %s\n",
+ gpio_get_value(GPIO_QSC_PHONE_ON) ? "HIGH" : "LOW ");
+}
+
+static int dpram_phone_getstatus(void)
+{
+ return gpio_get_value(GPIO_QSC_PHONE_ACTIVE);
+}
+
+static void dpram_phone_reset(void)
+{
+ PRINT_FUNC();
+
+ if(g_dpram_wpend == IDPRAM_WPEND_LOCK)
+ g_dpram_wpend = IDPRAM_WPEND_UNLOCK; // dpram write unlock
+
+ /*Add for Gadui : Normal boot Magic - 0x54424D4E*/
+ dpram_init_magic_num();
+
+ gpio_set_value(GPIO_QSC_PHONE_RST, GPIO_LEVEL_LOW);
+ msleep(100);
+ gpio_set_value(GPIO_QSC_PHONE_RST, GPIO_LEVEL_HIGH);
+
+ g_cp_reset_cnt++;
+}
+static int dpram_extra_mem_rw(struct _param_em *param)
+{
+
+ if(param->offset + param->size > 0xFFF800)
+ {
+ LOGE("Wrong rage of external memory access\n");
+ return -1;
+ }
+
+ if (param->rw)
+ { //write
+ if(dpram_lock_write(__func__) < 0)
+ return -EAGAIN;
+ WRITE_TO_DPRAM(param->offset, param->addr, param->size);
+ dpram_unlock_write(__func__);
+ }
+ else
+ { //read
+ dpram_lock_read(__func__);
+ READ_FROM_DPRAM(param->addr, param->offset, param->size);
+ dpram_unlock_read(__func__);
+ }
+ return 0;
+}
+
+static int dpram_phone_ramdump_on(void)
+{
+ const u16 rdump_flag1 = 0xdead;
+ const u16 rdump_flag2 = 0xdead;
+ const u16 temp1, temp2;
+
+ LOGL(DL_INFO,"Ramdump ON.\n");
+ if(dpram_lock_write(__func__) < 0)
+ return -EAGAIN;
+
+ WRITE_TO_DPRAM(DPRAM_MAGIC_CODE_ADDRESS, &rdump_flag1, sizeof(rdump_flag1));
+ WRITE_TO_DPRAM(DPRAM_ACCESS_ENABLE_ADDRESS, &rdump_flag2, sizeof(rdump_flag2));
+
+ READ_FROM_DPRAM((void *)&temp1, DPRAM_MAGIC_CODE_ADDRESS, sizeof(temp1));
+ READ_FROM_DPRAM((void *)&temp2, DPRAM_ACCESS_ENABLE_ADDRESS, sizeof(temp2));
+ LOGL(DL_INFO,"flag1: %x flag2: %x\n", temp1, temp2);
+
+ /* @LDK@ send init end code to phone */
+ dpram_unlock_write(__func__);
+
+ g_dump_on = 1;
+ // If it is configured to dump both AP and CP, reset both AP and CP here.
+ kernel_sec_dump_cp_handle2();
+
+ return 0;
+
+}
+
+static int dpram_phone_ramdump_off(void)
+{
+ const u16 rdump_flag1 = 0x00aa;
+ const u16 rdump_flag2 = 0x0001;
+
+ LOGL(DL_INFO, "Ramdump OFF.\n");
+
+ g_dump_on = 0;
+ if(dpram_lock_write(__func__) < 0)
+ return -EAGAIN;
+
+ WRITE_TO_DPRAM(DPRAM_MAGIC_CODE_ADDRESS, &rdump_flag1, sizeof(rdump_flag1));
+ WRITE_TO_DPRAM(DPRAM_ACCESS_ENABLE_ADDRESS, &rdump_flag2, sizeof(rdump_flag2));
+ /* @LDK@ send init end code to phone */
+ dpram_unlock_write(__func__);
+
+ //usb_switch_mode(1); #############Need to be enabled later
+
+ g_phone_sync = 0;
+
+ dpram_phone_reset();
+ return 0;
+
+}
+
+#ifdef CONFIG_PROC_FS
+static int dpram_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ int len;
+
+ u16 magic, enable;
+ u16 fmt_in_head, fmt_in_tail, fmt_out_head, fmt_out_tail;
+ u16 raw_in_head, raw_in_tail, raw_out_head, raw_out_tail;
+ u16 in_interrupt = 0, out_interrupt = 0;
+
+ int fih, fit, foh, fot;
+ int rih, rit, roh, rot;
+
+#ifdef _ENABLE_ERROR_DEVICE
+ char buf[DPRAM_ERR_MSG_LEN];
+ unsigned long flags;
+#endif /* _ENABLE_ERROR_DEVICE */
+
+ READ_FROM_DPRAM((void *)&magic, DPRAM_MAGIC_CODE_ADDRESS, sizeof(magic));
+ READ_FROM_DPRAM((void *)&enable, DPRAM_ACCESS_ENABLE_ADDRESS, sizeof(enable));
+ READ_FROM_DPRAM((void *)&fmt_in_head, DPRAM_PHONE2PDA_FORMATTED_HEAD_ADDRESS, sizeof(fmt_in_head));
+ READ_FROM_DPRAM((void *)&fmt_in_tail, DPRAM_PHONE2PDA_FORMATTED_TAIL_ADDRESS, sizeof(fmt_in_tail));
+ READ_FROM_DPRAM((void *)&fmt_out_head, DPRAM_PDA2PHONE_FORMATTED_HEAD_ADDRESS, sizeof(fmt_out_head));
+ READ_FROM_DPRAM((void *)&fmt_out_tail, DPRAM_PDA2PHONE_FORMATTED_TAIL_ADDRESS, sizeof(fmt_out_tail));
+ READ_FROM_DPRAM((void *)&raw_in_head, DPRAM_PHONE2PDA_RAW_HEAD_ADDRESS, sizeof(raw_in_head));
+ READ_FROM_DPRAM((void *)&raw_in_tail, DPRAM_PHONE2PDA_RAW_TAIL_ADDRESS, sizeof(raw_in_tail));
+ READ_FROM_DPRAM((void *)&raw_out_head, DPRAM_PDA2PHONE_RAW_HEAD_ADDRESS, sizeof(raw_out_head));
+ READ_FROM_DPRAM((void *)&raw_out_tail, DPRAM_PDA2PHONE_RAW_TAIL_ADDRESS, sizeof(raw_out_tail));
+
+ fih = dpram_table[FORMATTED_INDEX].in_head_saved;
+ fit = dpram_table[FORMATTED_INDEX].in_tail_saved;
+ foh = dpram_table[FORMATTED_INDEX].out_head_saved;
+ fot = dpram_table[FORMATTED_INDEX].out_tail_saved;
+ rih = dpram_table[RAW_INDEX].in_head_saved;
+ rit = dpram_table[RAW_INDEX].in_tail_saved;
+ roh = dpram_table[RAW_INDEX].out_head_saved;
+ rot = dpram_table[RAW_INDEX].out_tail_saved;
+ out_interrupt = ioread16((void *)dpram_mbx_BA);
+ in_interrupt = ioread16((void *)dpram_mbx_AB);
+
+#ifdef _ENABLE_ERROR_DEVICE
+ memset((void *)buf, '\0', DPRAM_ERR_MSG_LEN);
+ local_irq_save(flags);
+ memcpy(buf, dpram_err_buf, DPRAM_ERR_MSG_LEN - 1);
+ local_irq_restore(flags);
+#endif /* _ENABLE_ERROR_DEVICE */
+
+ p += sprintf(p,
+ "-------------------------------------\n"
+ "| NAME\t\t\t| VALUE\n"
+ "-------------------------------------\n"
+ "|R MAGIC CODE\t\t| 0x%04x\n"
+ "|R ENABLE CODE\t\t| 0x%04x\n"
+ "|R PHONE->PDA FMT HEAD\t| %u\n"
+ "|R PHONE->PDA FMT TAIL\t| %u\n"
+ "|R PDA->PHONE FMT HEAD\t| %u\n"
+ "|R PDA->PHONE FMT TAIL\t| %u\n"
+ "|R PHONE->PDA RAW HEAD\t| %u\n"
+ "|R RPHONE->PDA RAW TAIL\t| %u\n"
+ "|R PDA->PHONE RAW HEAD\t| %u\n"
+ "|R PDA->PHONE RAW TAIL\t| %u\n"
+ "-------------------------------------\n"
+ "| FMT PHONE->PDA HEAD\t| %d\n"
+ "| FMT PHONE->PDA TAIL\t| %d\n"
+ "| FMT PDA->PHONE HEAD\t| %d\n"
+ "| FMT PDA->PHONE TAIL\t| %d\n"
+ "-------------------------------------\n"
+ "| RAW PHONE->PDA HEAD\t| %d\n"
+ "| RAW PHONE->PDA TAIL\t| %d\n"
+ "| RAW PDA->PHONE HEAD\t| %d\n"
+ "| RAW PDA->PHONE TAIL\t| %d\n"
+ "-------------------------------------\n"
+ "| PHONE->PDA MAILBOX\t| 0x%04x\n"
+ "| PDA->PHONE MAILBOX\t| 0x%04x\n"
+ "-------------------------------------\n"
+#ifdef _ENABLE_ERROR_DEVICE
+ "| LAST PHONE ERR MSG\t| %s\n"
+#endif /* _ENABLE_ERROR_DEVICE */
+ "| PHONE ACTIVE\t\t| %s\n"
+ "| DPRAM INT Level\t| %d\n"
+ "-------------------------------------\n",
+ magic, enable,
+ fmt_in_head, fmt_in_tail, fmt_out_head, fmt_out_tail,
+ raw_in_head, raw_in_tail, raw_out_head, raw_out_tail,
+ fih, fit, foh, fot,
+ rih, rit, roh, rot,
+ in_interrupt, out_interrupt,
+
+#ifdef _ENABLE_ERROR_DEVICE
+ (buf[0] != '\0' ? buf : "NONE"),
+#endif /* _ENABLE_ERROR_DEVICE */
+ (dpram_phone_getstatus() ? "ACTIVE" : "INACTIVE"),
+ gpio_get_value(IRQ_QSC_PHONE_ACTIVE)
+ );
+
+ len = (p - page) - off;
+ if (len < 0) {
+ len = 0;
+ }
+
+ *eof = (len <= count) ? 1 : 0;
+ *start = page + off;
+
+ return len;
+}
+#endif /* CONFIG_PROC_FS */
+
+/* dpram tty file operations. */
+static int dpram_tty_open(struct tty_struct *tty, struct file *file)
+{
+ dpram_device_t *device = &dpram_table[tty->index];
+
+ PRINT_FUNC();
+ device->serial.tty = tty;
+ device->serial.open_count++;
+
+ if (device->serial.open_count > 1)
+ {
+ device->serial.open_count--;
+ return -EBUSY;
+ }
+
+ tty->driver_data = (void *)device;
+ tty->low_latency = 1;
+ return 0;
+}
+
+static void dpram_tty_close(struct tty_struct *tty, struct file *file)
+{
+ dpram_device_t *device = (dpram_device_t *)tty->driver_data;
+
+ //PRINT_FUNC();
+ if ( device && (device == &dpram_table[tty->index]) )
+ {
+ down(&device->serial.sem);
+ device->serial.open_count--;
+ device->serial.tty = NULL;
+ up(&device->serial.sem);
+ }
+}
+
+static int dpram_tty_write(struct tty_struct *tty, const unsigned char *buffer, int count)
+{
+ dpram_device_t *device = (dpram_device_t *)tty->driver_data;
+
+ //PRINT_FUNC();
+ if (!device)
+ return 0;
+
+ return dpram_write(device, buffer, count);
+}
+
+static int dpram_tty_write_room(struct tty_struct *tty)
+{
+ int avail;
+ u16 head, tail;
+ dpram_device_t *device = (dpram_device_t *)tty->driver_data;
+
+ //PRINT_FUNC();
+
+ if (device != NULL)
+ {
+ head = device->out_head_saved;
+ tail = device->out_tail_saved;
+
+ avail = (head < tail) ? (tail - head - 1) : (device->out_buff_size + tail - head - 1);
+
+ return avail;
+ }
+
+ return 0;
+}
+
+static int dpram_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
+{
+ unsigned int val;
+
+ PRINT_FUNC();
+ switch (cmd)
+ {
+ case DPRAM_PHONE_ON:
+ g_phone_sync = 0;
+ g_dump_on = 0;
+ g_phone_power_off_sequence = 0;
+ LOGA("IOCTL cmd = DPRAM_PHONE_ON\n");
+ dpram_phone_power_on();
+ return 0;
+
+ case DPRAM_PHONE_GETSTATUS:
+ LOGA("IOCTL cmd = DPRAM_PHONE_GETSTATUS\n");
+ val = dpram_phone_getstatus();
+ return copy_to_user((unsigned int *)arg, &val, sizeof(val));
+
+ case DPRAM_PHONE_RESET:
+ g_phone_sync = 0;
+ g_dump_on = 0;
+ g_phone_power_off_sequence = 0;
+ LOGA("IOCTL cmd = DPRAM_PHONE_RESET\n");
+ dpram_phone_reset();
+ return 0;
+
+ case DPRAM_PHONE_OFF:
+ g_phone_sync = 0;
+ g_phone_power_off_sequence = 1;
+ LOGA("IOCTL cmd = DPRAM_PHONE_OFF\n");
+ dpram_only_qsc_phone_on_off();
+ return 0;
+
+ // Silent reset
+ case MBX_CMD_PHONE_RESET:
+ LOGA("IOCTL cmd = MBX_CMD_PHONE_RESET\n");
+ request_phone_reset();
+ return 0;
+
+ case DPRAM_PHONE_RAMDUMP_ON:
+ LOGA("IOCTL cmd = DPRAM_PHONE_RAMDUMP_ON\n");
+ dpram_phone_ramdump_on();
+ return 0;
+
+ case DPRAM_PHONE_RAMDUMP_OFF:
+ LOGA("IOCTL cmd = DPRAM_PHONE_RAMDUMP_OFF\n");
+ dpram_phone_ramdump_off();
+ return 0;
+
+ case DPRAM_PHONE_UNSET_UPLOAD:
+ LOGA("IOCTL cmd = DPRAM_PHONE_UNSET_UPLOAD\n");
+#ifdef CONFIG_SEC_DEBUG
+ kernel_sec_clear_upload_magic_number();
+#endif
+ break;
+
+ case DPRAM_PHONE_SET_AUTOTEST:
+ LOGA("IOCTL cmd = DPRAM_PHONE_SET_AUTOTEST\n");
+#ifdef CONFIG_SEC_DEBUG
+ kernel_sec_set_autotest();
+#endif
+ break;
+
+ case DPRAM_PHONE_GET_DEBUGLEVEL:
+ LOGA("IOCTL cmd = DPRAM_PHONE_GET_DEBUGLEVEL\n");
+#ifdef CONFIG_SEC_DEBUG
+ switch(kernel_sec_get_debug_level()) {
+ case KERNEL_SEC_DEBUG_LEVEL_LOW:
+ val = 0xA0A0;
+ break;
+ case KERNEL_SEC_DEBUG_LEVEL_MID:
+ val = 0xB0B0;
+ break;
+ case KERNEL_SEC_DEBUG_LEVEL_HIGH:
+ val = 0xC0C0;
+ break;
+ default:
+ val = 0xFFFF;
+ break;
+ }
+ LOGA("DPRAM_PHONE_GET_DEBUGLEVEL = %x, %d\n", kernel_sec_get_debug_level(), val);
+#endif
+ return copy_to_user((unsigned int *)arg, &val, sizeof(val));
+
+ break;
+
+ case DPRAM_PHONE_SET_DEBUGLEVEL:
+ LOGA("IOCTL cmd = DPRAM_PHONE_SET_DEBUGLEVEL\n");
+#ifdef CONFIG_SEC_DEBUG
+ switch(kernel_sec_get_debug_level()) {
+ case KERNEL_SEC_DEBUG_LEVEL_LOW:
+ kernel_sec_set_debug_level(KERNEL_SEC_DEBUG_LEVEL_MID);
+ break;
+ case KERNEL_SEC_DEBUG_LEVEL_MID:
+ kernel_sec_set_debug_level(KERNEL_SEC_DEBUG_LEVEL_HIGH);
+ break;
+ case KERNEL_SEC_DEBUG_LEVEL_HIGH:
+ kernel_sec_set_debug_level(KERNEL_SEC_DEBUG_LEVEL_LOW);
+ break;
+ default:
+ break;
+ }
+#endif
+ return 0;
+
+ case DPRAM_EXTRA_MEM_RW:
+ {
+ struct _param_em param;
+
+ LOGA("IOCTL cmd = DPRAM_EXTRA_MEM_RW\n");
+
+ val = copy_from_user((void *)&param, (void *)arg, sizeof(param));
+ if (dpram_extra_mem_rw(&param) < 0)
+ {
+ LOGE("External memory access fail..\n");
+ return -1;
+ }
+
+ if (!param.rw) //read
+ {
+ return copy_to_user((unsigned long *)arg, &param, sizeof(param));
+ }
+
+ return 0;
+ }
+
+ case DPRAM_PHONE_CPRAMDUMP_START:
+ {
+ LOGA("IOCTL cmd = DPRAM_PHONE_CPRAMDUMP_START\n");
+// setup_cp_ramdump();
+// LOGA("Succeeded in setup_cp_ramdump()!!!\n");
+ return 0;
+ }
+
+ case DPRAM_PHONE_CPRAMDUMP_DONE:
+ {
+ int ret;
+
+ LOGA("IOCTL cmd = DPRAM_PHONE_CPRAMDUMP_DONE\n");
+
+ dpram_send_command(CMD_CP_RAMDUMP_SEND_DONE_REQ);
+ ret = dpram_wait_response(CMD_CP_RAMDUMP_SEND_DONE_RESP|MASK_CMD_RESULT_SUCCESS);
+ if (!ret) {
+ LOGE("Failed in dpram_wait_response()!!!\n");
+ return 0;
+ }
+ LOGE("succeeded in dpram_wait_response()!!!\n");
+ dpram_clear_response();
+
+ // goto Upload mode
+#ifdef CONFIG_SEC_DEBUG
+ if (kernel_sec_get_debug_level() != KERNEL_SEC_DEBUG_LEVEL_LOW) {
+ LOGE("Upload Mode!!!\n");
+ kernel_sec_dump_cp_handle2();
+ }
+#endif
+
+ return 0;
+ }
+
+ default:
+ LOGA("IOCTL cmd = 0x%X\n", cmd);
+ break;
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static int dpram_tty_chars_in_buffer(struct tty_struct *tty)
+{
+ int data;
+ u16 head, tail;
+
+
+ dpram_device_t *device = (dpram_device_t *)tty->driver_data;
+
+ //PRINT_FUNC();
+ if (device != NULL)
+ {
+ head = device->out_head_saved;
+ tail = device->out_tail_saved;
+
+ data = (head > tail) ? (head - tail - 1) : (device->out_buff_size - tail + head);
+
+ return data;
+ }
+
+ return 0;
+}
+
+#ifdef _ENABLE_ERROR_DEVICE
+static int dpram_err_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ ssize_t ret;
+ size_t ncopy;
+
+ //PRINT_FUNC();
+ add_wait_queue(&dpram_err_wait_q, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ while (1) {
+ if (dpram_err_len) {
+ ncopy = min(count, dpram_err_len);
+ if (copy_to_user(buf, dpram_err_buf, ncopy))
+ ret = -EFAULT;
+ else
+ ret = ncopy;
+
+ dpram_err_len = 0;
+
+ break;
+ }
+
+ if (filp->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ schedule();
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&dpram_err_wait_q, &wait);
+
+ return ret;
+}
+
+static int dpram_err_fasync(int fd, struct file *filp, int mode)
+{
+ //PRINT_FUNC();
+ return fasync_helper(fd, filp, mode, &dpram_err_async_q);
+}
+
+static unsigned int dpram_err_poll(struct file *filp,
+ struct poll_table_struct *wait)
+{
+ poll_wait(filp, &dpram_err_wait_q, wait);
+ return ((dpram_err_len) ? (POLLIN | POLLRDNORM) : 0);
+}
+
+static int dpram_dump_open(struct inode *inode, struct file *filp)
+{
+ struct cdev *cdev = inode->i_cdev;
+ struct dpram *dp = container_of(cdev, struct dpram, cdev);
+
+ //PRINT_FUNC();
+ LOGA("Invoked!!!\n");
+ filp->private_data = dp;
+
+ setup_cp_ramdump();
+
+ return 0;
+}
+
+static int dpram_dump_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+ int ret;
+ int ncopy;
+
+ //PRINT_FUNC();
+ receive_cp_ramdump();
+
+ ncopy = min(count, dpram_dump_len);
+ if (copy_to_user(buf, cp_ramdump_buff, ncopy))
+ ret = -EFAULT;
+ else
+ ret = ncopy;
+
+ dpram_dump_len = 0;
+
+ LOGA("RX bytes = %d\n", dump_rx_total);
+
+ return ret;
+}
+
+static int dpram_dump_fasync(int fd, struct file *filp, int mode)
+{
+ return fasync_helper(fd, filp, mode, &dpram_dump_async_q);
+}
+
+static unsigned int dpram_dump_poll(struct file *filp,
+ struct poll_table_struct *wait)
+{
+ LOGA("%d bytes are ready.\n", dpram_dump_len);
+ poll_wait(filp, &dpram_dump_wait_q, wait);
+ return ((dpram_dump_len) ? (POLLIN | POLLRDNORM) : 0);
+}
+
+static long dpram_dump_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ switch (cmd)
+ {
+ case DPRAM_PHONE_CPRAMDUMP_START:
+ {
+ LOGA("IOCTL cmd = DPRAM_PHONE_CPRAMDUMP_START\n");
+
+ start_cp_ramdump();
+ return 0;
+ }
+
+ case DPRAM_PHONE_CPRAMDUMP_DONE:
+ {
+ LOGA("IOCTL cmd = DPRAM_PHONE_CPRAMDUMP_DONE\n");
+
+ close_cp_ramdump();
+
+#ifdef CONFIG_SEC_DEBUG
+ /* Go to Upload mode*/
+ if (kernel_sec_get_debug_level() != KERNEL_SEC_DEBUG_LEVEL_LOW)
+ kernel_sec_dump_cp_handle2();
+#endif
+
+ return 0;
+ }
+
+ default:
+ LOGA("IOCTL cmd = 0x%X\n", cmd);
+ break;
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+
+#endif /* _ENABLE_ERROR_DEVICE */
+
+/* handlers. */
+static void res_ack_tasklet_handler(unsigned long data)
+{
+ dpram_device_t *device = (dpram_device_t *)data;
+
+ //PRINT_FUNC();
+ if (device && device->serial.tty) {
+ struct tty_struct *tty = device->serial.tty;
+
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc->ops->write_wakeup) {
+ (tty->ldisc->ops->write_wakeup)(tty);
+ }
+
+ wake_up_interruptible(&tty->write_wait);
+ }
+}
+
+static void fmt_rcv_tasklet_handler(unsigned long data)
+{
+ dpram_tasklet_data_t *tasklet_data = (dpram_tasklet_data_t *)data;
+
+ dpram_device_t *device = tasklet_data->device;
+ u16 non_cmd = tasklet_data->non_cmd;
+
+ int ret = 0;
+ int cnt = 0;
+
+ //PRINT_FUNC();
+ if (device && device->serial.tty)
+ {
+ struct tty_struct *tty = device->serial.tty;
+
+ while (dpram_get_read_available(device))
+ {
+ ret = dpram_read_fmt(device, non_cmd);
+
+ if (!ret)
+ cnt++;
+
+ if (cnt > 10)
+ {
+ dpram_drop_data(device);
+ break;
+ }
+
+ if (ret < 0)
+ {
+ LOGE("FMT dpram_read_fmt failed\n");
+ /* TODO: ... wrong.. */
+ }
+ tty->low_latency = 0;
+ tty_flip_buffer_push(tty);
+ }
+ }
+ else
+ {
+ dpram_drop_data(device);
+ }
+}
+
+static void raw_rcv_tasklet_handler(unsigned long data)
+{
+ dpram_tasklet_data_t *tasklet_data = (dpram_tasklet_data_t *)data;
+
+ dpram_device_t *device = tasklet_data->device;
+ u16 non_cmd = tasklet_data->non_cmd;
+
+ int ret = 0;
+ //PRINT_FUNC();
+ while (dpram_get_read_available(device))
+ {
+ ret = dpram_read_raw(device, non_cmd);
+
+ if (ret < 0)
+ {
+ LOGE("RAW dpram_read_raw failed\n");
+ /* TODO: ... wrong.. */
+ }
+ }
+}
+
+static void cmd_req_active_handler(void)
+{
+ dpram_send_mbx_BA(INT_COMMAND(MBX_CMD_RES_ACTIVE));
+}
+
+/* static void cmd_error_display_handler(void)
+ *
+ * this fucntion was called by dpram irq handler and phone active irq hander
+ * first this fucntion check the log level then jump to send error message to ril
+ * or CP Upload mode
+ */
+static void cmd_error_display_handler(void)
+{
+#ifdef _ENABLE_ERROR_DEVICE
+ unsigned short intr;
+ unsigned long flags;
+ char buf[DPRAM_ERR_MSG_LEN];
+
+ memset((void *)buf, 0, sizeof (buf));
+
+#ifdef CONFIG_SEC_DEBUG
+ if (dpram_err_cause == UPLOAD_CAUSE_CDMA_RESET) {
+ if(get_sec_debug_level())
+ memcpy((void *)buf, "UPLOAD", sizeof("UPLOAD"));
+ else /*debug level is low*/
+ memcpy((void *)buf, "9 $PHONE-RESET", sizeof("9 $PHONE-RESET"));
+ }
+ else {
+ if(get_sec_debug_level()) {
+ buf[0] = 'C';
+ buf[1] = 'D';
+ buf[2] = 'M';
+ buf[3] = 'A';
+ buf[4] = ' ';
+ READ_FROM_DPRAM((buf + 5), DPRAM_PHONE2PDA_FORMATTED_BUFFER_ADDRESS, (sizeof(buf) - 6));
+ } else /*debug level is low */
+ memcpy((void *)buf, "9 $PHONE-RESET", sizeof("9 $PHONE-RESET"));
+ }
+ LOGE("[PHONE ERROR] ->> %s\n", buf);
+ memcpy(dpram_err_buf, buf, DPRAM_ERR_MSG_LEN);
+ dpram_err_len = 64;
+ LOGE("start wake_lock_timeout: during 20sec\n");
+ wake_lock_timeout(&dpram_wake_lock, HZ*20);
+ /* goto Upload mode : receive C9 */
+ if ((get_sec_debug_level())&& \
+ (dpram_err_cause != UPLOAD_CAUSE_CDMA_RESET))
+ /*if (sec_debug_level())*/
+ {
+ local_irq_save(flags);
+ LOGE("Upload Mode!!!\n");
+ intr = ioread16((void *)dpram_mbx_AB);
+ if (intr == (MBX_CMD_CDMA_DEAD|INT_MASK_VALID|INT_MASK_COMMAND))
+ {
+ LOGE("mbx_AB = 0x%04X\n", intr);
+ }
+ kernel_sec_dump_cp_handle2();
+ local_irq_restore(flags);
+ }
+ dpram_err_cause = 0;
+ wake_up_interruptible(&dpram_err_wait_q);
+ kill_fasync(&dpram_err_async_q, SIGIO, POLL_IN);
+#endif
+#endif /* _ENABLE_ERROR_DEVICE */
+}
+
+
+static void cmd_phone_start_handler(void)
+{
+ LOGA("Received CMD_PHONE_START!!! %d\n", g_phone_sync);
+
+ PRINT_FUNC();
+ if (g_phone_sync == 0) {
+ /* Set GPIO_PDA_ACTIVE as CP sometimes seems to read this pin as Low */
+ LOGA("Current GPIO_PDA_ACTIVE = %d\n", gpio_get_value(GPIO_PDA_ACTIVE) );
+ gpio_set_value(GPIO_PDA_ACTIVE, GPIO_LEVEL_HIGH);
+
+ dpram_init_and_report();
+
+ LOGA("GPIO_PDA_ACTIVE = %d\n", gpio_get_value(GPIO_PDA_ACTIVE) );
+ }
+}
+
+
+static void cmd_req_time_sync_handler(void)
+{
+ /* TODO: add your codes here.. */
+}
+
+static void cmd_phone_deep_sleep_handler(void)
+{
+ /* TODO: add your codes here.. */
+}
+
+static void dpram_command_handler(u16 cmd)
+{
+//PRINT_FUNC();
+ switch (cmd)
+ {
+ case MBX_CMD_REQ_ACTIVE:
+ cmd_req_active_handler();
+ break;
+
+ case MBX_CMD_CDMA_DEAD:
+ LOGE("received MBX_CMD_CDMA_DEAD\n");
+ cmd_error_display_handler();
+ break;
+
+ case MBX_CMD_ERR_DISPLAY:
+ LOGE("received MBX_CMD_ERR_DISPLAY\n");
+ cmd_error_display_handler();
+ break;
+
+ case MBX_CMD_PHONE_START:
+ cmd_phone_start_handler();
+ break;
+
+ case MBX_CMD_REQ_TIME_SYNC:
+ cmd_req_time_sync_handler();
+ break;
+
+ case MBX_CMD_PHONE_DEEP_SLEEP:
+ cmd_phone_deep_sleep_handler();
+ break;
+
+ case MBX_CMD_DPRAM_DOWN:
+ dpram_power_down();
+ break;
+
+ case MBX_CMD_CP_WAKEUP_START:
+ dpram_powerup_start();
+ break;
+
+ default:
+ LOGA("Unknown command (0x%04X)\n", cmd);
+ }
+}
+
+static void dpram_data_handler(u16 non_cmd)
+{
+ u16 head, tail;
+
+ // PRINT_FUNC();
+ /* @LDK@ formatted check. */
+#ifdef CDMA_IPC_C210_IDPRAM
+ head = ioread16((void *)(DPRAM_VBASE + DPRAM_PHONE2PDA_FORMATTED_HEAD_ADDRESS));
+ tail = ioread16((void *)(DPRAM_VBASE + DPRAM_PHONE2PDA_FORMATTED_TAIL_ADDRESS));
+#else
+ READ_FROM_DPRAM_VERIFY(&head, DPRAM_PHONE2PDA_FORMATTED_HEAD_ADDRESS, sizeof(head));
+ READ_FROM_DPRAM_VERIFY(&tail, DPRAM_PHONE2PDA_FORMATTED_TAIL_ADDRESS, sizeof(tail));
+#endif
+
+ if (head != tail)
+ {
+ non_cmd |= INT_MASK_SEND_F;
+
+ if (non_cmd & INT_MASK_REQ_ACK_F)
+ atomic_inc(&fmt_txq_req_ack_rcvd);
+ }
+ else
+ {
+ if (non_cmd & INT_MASK_REQ_ACK_F)
+ {
+ LOGA("FMT DATA EMPTY & REQ_ACK_F (non_cmd:0x%x)\n", non_cmd);
+ dpram_send_mbx_BA(INT_NON_COMMAND(INT_MASK_RES_ACK_F));
+ atomic_set(&fmt_txq_req_ack_rcvd, 0);
+ }
+ }
+
+ /* @LDK@ raw check. */
+#ifdef CDMA_IPC_C210_IDPRAM
+ head = ioread16((void *)(DPRAM_VBASE + DPRAM_PHONE2PDA_RAW_HEAD_ADDRESS));
+ tail = ioread16((void *)(DPRAM_VBASE + DPRAM_PHONE2PDA_RAW_TAIL_ADDRESS));
+#else
+ READ_FROM_DPRAM_VERIFY(&head, DPRAM_PHONE2PDA_RAW_HEAD_ADDRESS, sizeof(head));
+ READ_FROM_DPRAM_VERIFY(&tail, DPRAM_PHONE2PDA_RAW_TAIL_ADDRESS, sizeof(tail));
+#endif
+
+ if (head != tail)
+ {
+ non_cmd |= INT_MASK_SEND_R;
+
+ if (non_cmd & INT_MASK_REQ_ACK_R)
+ atomic_inc(&raw_txq_req_ack_rcvd);
+ }
+ else
+ {
+ if (non_cmd & INT_MASK_REQ_ACK_R)
+ {
+ LOGA("RAW DATA EMPTY & REQ_ACK_R (non_cmd:0x%x)\n", non_cmd);
+ dpram_send_mbx_BA(INT_NON_COMMAND(INT_MASK_RES_ACK_R));
+ atomic_set(&raw_txq_req_ack_rcvd, 0);
+ }
+ }
+
+ /* @LDK@ +++ scheduling.. +++ */
+ if (non_cmd & INT_MASK_SEND_F)
+ {
+ dpram_tasklet_data[FORMATTED_INDEX].device = &dpram_table[FORMATTED_INDEX];
+ dpram_tasklet_data[FORMATTED_INDEX].non_cmd = non_cmd;
+ fmt_send_tasklet.data = (unsigned long)&dpram_tasklet_data[FORMATTED_INDEX];
+ tasklet_schedule(&fmt_send_tasklet);
+ }
+
+ if (non_cmd & INT_MASK_SEND_R)
+ {
+ dpram_tasklet_data[RAW_INDEX].device = &dpram_table[RAW_INDEX];
+ dpram_tasklet_data[RAW_INDEX].non_cmd = non_cmd;
+ raw_send_tasklet.data = (unsigned long)&dpram_tasklet_data[RAW_INDEX];
+ /* @LDK@ raw buffer op. -> soft irq level. */
+ tasklet_hi_schedule(&raw_send_tasklet);
+ }
+
+ if (non_cmd & INT_MASK_RES_ACK_F)
+ {
+ tasklet_schedule(&fmt_res_ack_tasklet);
+ }
+
+ if (non_cmd & INT_MASK_RES_ACK_R)
+ {
+ tasklet_hi_schedule(&raw_res_ack_tasklet);
+ }
+}
+
+static inline void check_int_pin_level(void)
+{
+ u16 mask = 0, cnt = 0;
+
+ while (cnt++ < 3)
+ {
+ mask = ioread16((void *)dpram_mbx_AB);
+ if ( gpio_get_value(GPIO_DPRAM_INT_CP_N) )
+ break;
+ }
+}
+
+static void phone_active_work_func(struct work_struct *work)
+{
+ u32 reset_code;
+
+ //PRINT_FUNC();
+ LOGA("PHONE_ACTIVE level: %s, phone_sync: %d\n",
+ gpio_get_value(GPIO_QSC_PHONE_ACTIVE) ? "HIGH" : "LOW ",
+ g_phone_sync);
+
+#ifdef _ENABLE_ERROR_DEVICE
+ /*
+ ** If CDMA was reset by watchdog, phone active low time is very short. So,
+ ** change the IRQ type to FALLING EDGE and don't check the GPIO_QSC_PHONE_ACTIVE.
+ */
+ if (g_phone_sync) {
+#ifdef DUMP_OF_PHONE_ACTIVE_LOW_CRASH
+ free_irq(dpram_irq, NULL);
+ IDPRAM_INT_CLEAR();
+ free_irq(phone_active_irq, NULL);
+ g_dump_on = 1;
+ init_completion(&wait_dump_data);
+#endif
+ memcpy_fromio(&reset_code, (void *)DPRAM_VBASE, sizeof(reset_code));
+ if (reset_code != CP_RESET_CODE) {
+#ifdef CONFIG_SEC_DEBUG
+ dpram_err_cause = UPLOAD_CAUSE_CDMA_RESET;
+#endif
+ if (g_phone_power_off_sequence != 1)
+ cmd_error_display_handler();
+ }
+ }
+#endif
+}
+
+
+/* @LDK@ interrupt handlers. */
+static irqreturn_t dpram_irq_handler(int irq, void *dev_id)
+{
+ unsigned long flags;
+ u16 irq_mask = 0;
+#ifdef PRINT_DPRAM_HEAD_TAIL
+ u16 fih, fit, foh, fot;
+ u16 rih, rit, roh, rot;
+#endif
+
+ //PRINT_FUNC();
+ local_irq_save(flags);
+ local_irq_disable();
+
+ irq_mask = ioread16((void *)dpram_mbx_AB);
+ //check_int_pin_level();
+
+ if (g_dump_on) {
+ g_irq_mask = irq_mask;
+ IDPRAM_INT_CLEAR();
+ complete(&wait_dump_data);
+ LOGA("g_dump_on == 1\n");
+ local_irq_restore(flags);
+ return IRQ_HANDLED;
+ }
+
+#ifdef DEBUG_DPRAM_INT_HANDLER
+ LOGA("INT2AP: 0x%04X\n", irq_mask);
+#endif
+
+ /* valid bit verification. @LDK@ */
+ if ( !(irq_mask & INT_MASK_VALID) )
+ {
+ LOGE("Invalid interrupt mask: 0x%04x\n", irq_mask);
+ IDPRAM_INT_CLEAR();
+ local_irq_restore(flags);
+ return IRQ_NONE;
+ }
+
+ /* command or non-command? @LDK@ */
+ if ( irq_mask & INT_MASK_COMMAND )
+ {
+ irq_mask &= ~(INT_MASK_VALID | INT_MASK_COMMAND);
+ dpram_command_handler(irq_mask);
+ }
+ else
+ {
+#ifdef PRINT_DPRAM_HEAD_TAIL
+ fih = ioread16((void *)(DPRAM_VBASE + DPRAM_PHONE2PDA_FORMATTED_HEAD_ADDRESS));
+ fit = ioread16((void *)(DPRAM_VBASE + DPRAM_PHONE2PDA_FORMATTED_TAIL_ADDRESS));
+ foh = ioread16((void *)(DPRAM_VBASE + DPRAM_PDA2PHONE_FORMATTED_HEAD_ADDRESS));
+ fot = ioread16((void *)(DPRAM_VBASE + DPRAM_PDA2PHONE_FORMATTED_TAIL_ADDRESS));
+ rih = ioread16((void *)(DPRAM_VBASE + DPRAM_PHONE2PDA_RAW_HEAD_ADDRESS));
+ rit = ioread16((void *)(DPRAM_VBASE + DPRAM_PHONE2PDA_RAW_TAIL_ADDRESS));
+ roh = ioread16((void *)(DPRAM_VBASE + DPRAM_PDA2PHONE_RAW_HEAD_ADDRESS));
+ rot = ioread16((void *)(DPRAM_VBASE + DPRAM_PDA2PHONE_RAW_TAIL_ADDRESS));
+ LOGA(" FMT_IN (H:%4d, T:%4d, M:%4d)\n FMT_OUT (H:%4d, T:%4d, M:%4d)\n RAW_IN (H:%4d, T:%4d, M:%4d)\n RAW_OUT (H:%4d, T:%4d, M:%4d)\n",
+ fih, fit, DPRAM_PHONE2PDA_FORMATTED_BUFFER_SIZE,
+ foh, fot, DPRAM_PDA2PHONE_FORMATTED_BUFFER_SIZE,
+ rih, rit, DPRAM_PHONE2PDA_RAW_BUFFER_SIZE,
+ roh, rot, DPRAM_PDA2PHONE_RAW_BUFFER_SIZE);
+#endif
+ irq_mask &= ~INT_MASK_VALID;
+ dpram_data_handler(irq_mask);
+ }
+
+ IDPRAM_INT_CLEAR();
+
+ local_irq_restore(flags);
+ return IRQ_HANDLED;
+}
+
+
+static irqreturn_t dpram_wake_from_CP_irq_handler(int irq, void *dev_id)
+{
+#ifdef DEBUG_DPRAM_INT_HANDLER
+ LOGA("wake_lock_timeout() in 5 seconds.\n", __func__);
+#endif
+
+ wake_lock_timeout(&dpram_wake_lock, 5*HZ);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t phone_active_irq_handler(int irq, void *dev_id)
+{
+ schedule_delayed_work(&phone_active_work, msecs_to_jiffies(1));
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t cp_dump_irq_handler(int irq, void *dev_id)
+{
+ //only print log
+ //LOGA("CP_DUMP_INT - High\n", __func__);
+ return IRQ_HANDLED;
+}
+
+
+static int kernel_sec_dump_cp_handle2(void)
+{
+#ifdef CONFIG_SEC_DEBUG
+ LOGA("Configure to restart AP and collect dump on restart...\n");
+ /* output high */
+ gpio_set_value(S5PV310_GPE0_3_MDM_IRQn, GPIO_LEVEL_HIGH);
+ /* GPIO output mux */
+ s3c_gpio_cfgpin(S5PV310_GPE0_0_MDM_WEn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_1_MDM_CSn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_2_MDM_Rn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_3_MDM_IRQn, S3C_GPIO_SFN(S3C_GPIO_OUTPUT));
+ s3c_gpio_cfgpin(S5PV310_GPE0_4_MDM_ADVN, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ if (dpram_err_len)
+ kernel_sec_set_cause_strptr(dpram_err_buf, dpram_err_len);
+ panic("CP Crash");
+#endif
+ return 0;
+}
+
+/* basic functions. */
+#ifdef _ENABLE_ERROR_DEVICE
+static struct file_operations dpram_err_ops = {
+ .owner = THIS_MODULE,
+ .read = dpram_err_read,
+ .fasync = dpram_err_fasync,
+ .poll = dpram_err_poll,
+ .llseek = no_llseek,
+
+ /* TODO: add more operations */
+};
+
+static struct file_operations dpram_dump_ops = {
+ .owner = THIS_MODULE,
+ .open = dpram_dump_open,
+ .read = dpram_dump_read,
+ .fasync = dpram_dump_fasync,
+ .poll = dpram_dump_poll,
+ .unlocked_ioctl = dpram_dump_ioctl,
+ .llseek = no_llseek,
+};
+#endif /* _ENABLE_ERROR_DEVICE */
+
+static struct tty_operations dpram_tty_ops = {
+ .open = dpram_tty_open,
+ .close = dpram_tty_close,
+ .write = dpram_tty_write,
+ .write_room = dpram_tty_write_room,
+ .ioctl = dpram_tty_ioctl,
+ .chars_in_buffer = dpram_tty_chars_in_buffer,
+
+ /* TODO: add more operations */
+};
+
+#ifdef _ENABLE_ERROR_DEVICE
+static void unregister_dpram_err_device(void)
+{
+ unregister_chrdev(DRIVER_MAJOR_NUM, DPRAM_ERR_DEVICE);
+ class_destroy(dpram_err_class);
+}
+
+static int register_dpram_err_device(void)
+{
+ struct device *dpram_err_dev_t;
+ int ret;
+
+ ret = register_chrdev(DRIVER_MAJOR_NUM, DPRAM_ERR_DEVICE, &dpram_err_ops);
+ if (ret < 0)
+ return ret;
+
+ dpram_err_class = class_create(THIS_MODULE, "err");
+ if (IS_ERR(dpram_err_class)) {
+ unregister_dpram_err_device();
+ return -EFAULT;
+ }
+
+ /* @LDK@ 1 = formatted, 2 = raw, so error device is '0' */
+ dpram_err_dev_t = device_create(
+ dpram_err_class,
+ NULL,
+ MKDEV(DRIVER_MAJOR_NUM, 0),
+ NULL,
+ DPRAM_ERR_DEVICE);
+ if (IS_ERR(dpram_err_dev_t)) {
+ unregister_dpram_err_device();
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static void unregister_dpram_dump_device(void)
+{
+ unregister_chrdev(DPRAM_DUMP_DEV_MAJOR, DPRAM_DUMP_DEVICE);
+ class_destroy(dpram_dump_class);
+}
+
+static int register_dpram_dump_device(void)
+{
+ struct device *dpram_dump_dev_t;
+ int ret;
+
+ ret = register_chrdev(DPRAM_DUMP_DEV_MAJOR, DPRAM_DUMP_DEVICE, &dpram_dump_ops);
+ if (ret < 0)
+ {
+ LOGE("Failed in register_chrdev() (%d)\n", ret);
+ return ret;
+ }
+
+ dpram_dump_class = class_create(THIS_MODULE, "dump");
+ if (IS_ERR(dpram_dump_class)) {
+ LOGE("Failed in class_create()\n");
+ unregister_dpram_dump_device();
+ return -EFAULT;
+ }
+
+ dpram_dump_dev_t = device_create(
+ dpram_dump_class,
+ NULL,
+ MKDEV(DPRAM_DUMP_DEV_MAJOR, 0),
+ NULL,
+ DPRAM_DUMP_DEVICE);
+ if (IS_ERR(dpram_dump_dev_t)) {
+ LOGE("Failed in device_create()\n");
+ unregister_dpram_dump_device();
+ return -EFAULT;
+ }
+
+ return 0;
+}
+#endif /* _ENABLE_ERROR_DEVICE */
+
+static int register_dpram_driver(void)
+{
+ int retval = 0;
+
+ /* @LDK@ allocate tty driver */
+ dpram_tty_driver = alloc_tty_driver(MAX_INDEX);
+
+ if (!dpram_tty_driver) {
+ return -ENOMEM;
+ }
+
+ /* @LDK@ initialize tty driver */
+ dpram_tty_driver->owner = THIS_MODULE;
+ dpram_tty_driver->magic = TTY_DRIVER_MAGIC;
+ dpram_tty_driver->driver_name = DRIVER_NAME;
+ dpram_tty_driver->name = "dpram";
+ dpram_tty_driver->major = DRIVER_MAJOR_NUM;
+ dpram_tty_driver->minor_start = 1;
+ dpram_tty_driver->num = MAX_INDEX;
+ dpram_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ dpram_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+ dpram_tty_driver->flags = TTY_DRIVER_REAL_RAW;
+ dpram_tty_driver->init_termios = tty_std_termios;
+ dpram_tty_driver->init_termios.c_cflag = (B115200 | CS8 | CREAD | CLOCAL | HUPCL);
+ tty_set_operations(dpram_tty_driver, &dpram_tty_ops);
+
+ dpram_tty_driver->ttys = dpram_tty;
+ dpram_tty_driver->termios = dpram_termios;
+ dpram_tty_driver->termios_locked = dpram_termios_locked;
+
+ /* @LDK@ register tty driver */
+ retval = tty_register_driver(dpram_tty_driver);
+ if (retval) {
+ LOGE("tty_register_driver error\n");
+ put_tty_driver(dpram_tty_driver);
+ return retval;
+ }
+
+ return 0;
+}
+
+static void unregister_dpram_driver(void)
+{
+ tty_unregister_driver(dpram_tty_driver);
+}
+
+/*
+ * MULTI PDP FUNCTIONs
+ */
+
+static long multipdp_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return -EINVAL;
+}
+
+static struct file_operations multipdp_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = multipdp_ioctl,
+ .llseek = no_llseek,
+};
+
+static struct miscdevice multipdp_dev = {
+ .minor = 132, //MISC_DYNAMIC_MINOR,
+ .name = APP_DEVNAME,
+ .fops = &multipdp_fops,
+};
+
+static inline struct pdp_info * pdp_get_serdev(const char *name)
+{
+ int slot;
+ struct pdp_info *dev;
+
+ for (slot = 0; slot < MAX_PDP_CONTEXT; slot++) {
+ dev = pdp_table[slot];
+ if (dev && dev->type == DEV_TYPE_SERIAL &&
+ strcmp(name, dev->vs_dev.tty_name) == 0) {
+ return dev;
+ }
+ }
+ return NULL;
+}
+
+static inline struct pdp_info * pdp_remove_dev(u8 id)
+{
+ int slot;
+ struct pdp_info *dev;
+
+ for (slot = 0; slot < MAX_PDP_CONTEXT; slot++) {
+ if (pdp_table[slot] && pdp_table[slot]->id == id) {
+ dev = pdp_table[slot];
+ pdp_table[slot] = NULL;
+ return dev;
+ }
+ }
+ return NULL;
+}
+
+static int vs_open(struct tty_struct *tty, struct file *filp)
+{
+ struct pdp_info *dev;
+ //PRINT_FUNC();
+ dev = pdp_get_serdev(tty->driver->name); // 2.6 kernel porting
+
+ if (dev == NULL) {
+ return -ENODEV;
+ }
+
+ tty->driver_data = (void *)dev;
+ tty->low_latency = 1;
+ dev->vs_dev.tty = tty;
+ dev->vs_dev.refcount++;
+
+ return 0;
+}
+
+static void vs_close(struct tty_struct *tty, struct file *filp)
+{
+ struct pdp_info *dev;
+
+ dev = pdp_get_serdev(tty->driver->name);
+
+ if (!dev )
+ return;
+ dev->vs_dev.refcount--;
+
+ return;
+}
+
+static int pdp_mux(struct pdp_info *dev, const void *data, size_t len )
+{
+ int ret;
+ size_t nbytes;
+ u8 *tx_buf;
+ struct pdp_hdr *hdr;
+ const u8 *buf;
+
+ int in_softirq_context = in_softirq();
+
+ /* check current context */
+ if (in_softirq_context)
+ spin_lock(&mux_tty_lock);
+ else
+ spin_lock_bh(&mux_tty_lock);
+
+ tx_buf = dev->tx_buf;
+ hdr = (struct pdp_hdr *)(tx_buf + 1);
+ buf = data;
+
+ hdr->id = dev->id;
+ hdr->control = 0;
+
+ while (len) {
+ if (len > MAX_PDP_DATA_LEN) {
+ nbytes = MAX_PDP_DATA_LEN;
+ } else {
+ nbytes = len;
+ }
+ hdr->len = nbytes + sizeof(struct pdp_hdr);
+
+ tx_buf[0] = 0x7f;
+
+ memcpy(tx_buf + 1 + sizeof(struct pdp_hdr), buf, nbytes);
+
+ tx_buf[1 + hdr->len] = 0x7e;
+
+ ret =
+ dpram_write(&dpram_table[RAW_INDEX], tx_buf, hdr->len + 2);
+
+ if (ret < 0) {
+ LOGE("write_to_dpram() failed: %d\n", ret);
+ /* check curent context */
+ if (in_softirq_context)
+ spin_unlock(&mux_tty_lock);
+ else
+ spin_unlock_bh(&mux_tty_lock);
+
+ return ret;
+ }
+ buf += nbytes;
+ len -= nbytes;
+ }
+
+ /* check curent context */
+ if (in_softirq_context)
+ spin_unlock(&mux_tty_lock);
+ else
+ spin_unlock_bh(&mux_tty_lock);
+
+ return 0;
+
+}
+
+
+static int vs_write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
+{
+ int ret;
+ struct pdp_info *dev = (struct pdp_info *)tty->driver_data;
+ //PRINT_FUNC();
+ ret = pdp_mux(dev, buf, count);
+
+ if (ret == 0)
+ {
+ ret = count;
+ }
+
+ return ret;
+}
+
+static int vs_write_room(struct tty_struct *tty)
+{
+// return TTY_FLIPBUF_SIZE;
+ return 8192*2;
+}
+
+static int vs_chars_in_buffer(struct tty_struct *tty)
+{
+ return 0;
+}
+
+static int vs_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg)
+{
+ return -ENOIOCTLCMD;
+}
+
+static struct tty_operations multipdp_tty_ops = {
+ .open = vs_open,
+ .close = vs_close,
+ .write = vs_write,
+ .write_room = vs_write_room,
+ .ioctl = vs_ioctl,
+ .chars_in_buffer = vs_chars_in_buffer,
+
+ /* TODO: add more operations */
+};
+
+static struct tty_driver* get_tty_driver_by_id(struct pdp_info *dev)
+{
+ int index = 0;
+
+ switch (dev->id) {
+ case 1: index = 0; break;
+ case 7: index = 1; break;
+ case 29: index = 2; break;
+ default: index = 0;
+ }
+
+ return &dev->vs_dev.tty_driver[index];
+}
+
+static int get_minor_start_index(int id)
+{
+ int start = 0;
+
+ switch (id) {
+ case 1: start = 0; break;
+ case 7: start = 1; break;
+ case 29: start = 2; break;
+ default: start = 0;
+ }
+
+ return start;
+}
+
+static int vs_add_dev(struct pdp_info *dev)
+{
+ struct tty_driver *tty_driver;
+
+ tty_driver = get_tty_driver_by_id(dev);
+
+ if (!tty_driver)
+ {
+ LOGE("tty driver == NULL!\n");
+ return -1;
+ }
+
+ kref_init(&tty_driver->kref);
+
+ tty_driver->magic = TTY_DRIVER_MAGIC;
+ tty_driver->driver_name = APP_DEVNAME;//"multipdp";
+ tty_driver->name = dev->vs_dev.tty_name;
+ tty_driver->major = CSD_MAJOR_NUM;
+ tty_driver->minor_start = get_minor_start_index(dev->id);
+ tty_driver->num = 1;
+ tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ tty_driver->subtype = SERIAL_TYPE_NORMAL;
+ tty_driver->flags = TTY_DRIVER_REAL_RAW;
+// kref_set(&tty_driver->kref, dev->vs_dev.refcount);
+ tty_driver->ttys = dev->vs_dev.tty_table; // 2.6 kernel porting
+ tty_driver->termios = dev->vs_dev.termios;
+ tty_driver->termios_locked = dev->vs_dev.termios_locked;
+
+ tty_set_operations(tty_driver, &multipdp_tty_ops);
+ return tty_register_driver(tty_driver);
+}
+
+static void vs_del_dev(struct pdp_info *dev)
+{
+ struct tty_driver *tty_driver = NULL;
+
+ tty_driver = get_tty_driver_by_id(dev);
+ tty_unregister_driver(tty_driver);
+}
+
+static inline void check_pdp_table(const char * func, int line)
+{
+ int slot;
+ for (slot = 0; slot < MAX_PDP_CONTEXT; slot++)
+ {
+ if (pdp_table[slot])
+ LOGA("[%s,%d] addr: %x slot: %d id: %d, name: %s\n", func, line,
+ (u32)pdp_table[slot], slot, pdp_table[slot]->id,
+ pdp_table[slot]->vs_dev.tty_name);
+ }
+}
+
+static inline struct pdp_info * pdp_get_dev(u8 id)
+{
+ int slot;
+
+ for (slot = 0; slot < MAX_PDP_CONTEXT; slot++)
+ {
+ if (pdp_table[slot] && pdp_table[slot]->id == id)
+ {
+ return pdp_table[slot];
+ }
+ }
+ return NULL;
+}
+
+static inline int pdp_add_dev(struct pdp_info *dev)
+{
+ int slot;
+
+ if (pdp_get_dev(dev->id)) {
+ return -EBUSY;
+ }
+
+ for (slot = 0; slot < MAX_PDP_CONTEXT; slot++) {
+ if (pdp_table[slot] == NULL) {
+ pdp_table[slot] = dev;
+ return slot;
+ }
+ }
+ return -ENOSPC;
+}
+
+static int pdp_activate(pdp_arg_t *pdp_arg, unsigned type, unsigned flags)
+{
+ int ret;
+ struct pdp_info *dev;
+
+ LOGL(DL_INFO, "id: %d\n", pdp_arg->id);
+ //PRINT_FUNC();
+ dev = kmalloc(sizeof(struct pdp_info) + MAX_PDP_PACKET_LEN, GFP_KERNEL);
+ if (dev == NULL) {
+ LOGE("out of memory\n");
+ return -ENOMEM;
+ }
+ memset(dev, 0, sizeof(struct pdp_info));
+
+ dev->id = pdp_arg->id;
+
+ dev->type = type;
+ dev->flags = flags;
+ dev->tx_buf = (u8 *)(dev + 1);
+
+ if (type == DEV_TYPE_SERIAL) {
+ sema_init(&dev->vs_dev.write_lock, 1);
+ strcpy(dev->vs_dev.tty_name, pdp_arg->ifname);
+
+ ret = vs_add_dev(dev);
+ if (ret < 0) {
+ kfree(dev);
+ return ret;
+ }
+
+ mutex_lock(&pdp_lock);
+ ret = pdp_add_dev(dev);
+ if (ret < 0) {
+ LOGE("pdp_add_dev() failed\n");
+ mutex_unlock(&pdp_lock);
+ vs_del_dev(dev);
+ kfree(dev);
+ return ret;
+ }
+ mutex_unlock(&pdp_lock);
+
+ {
+ struct tty_driver * tty_driver = get_tty_driver_by_id(dev);
+#ifndef PRODUCT_SHIP
+ LOGL(DL_INFO, "%s(id: %u) serial device is created.\n",
+ tty_driver->name, dev->id);
+#endif
+ }
+ }
+
+ return 0;
+}
+
+static int multipdp_init(void)
+{
+ int i;
+
+ pdp_arg_t pdp_args[NUM_PDP_CONTEXT] = {
+ { .id = 1, .ifname = "ttyCSD" },
+ { .id = 7, .ifname = "ttyCDMA" },
+ { .id = 29, .ifname = "ttyCPLOG" },
+ // { .id = 31, .ifname = "loopback" },
+
+ };
+
+
+ /* create serial device for Circuit Switched Data */
+ for (i = 0; i < NUM_PDP_CONTEXT; i++) {
+ if (pdp_activate(&pdp_args[i], DEV_TYPE_SERIAL, DEV_FLAG_STICKY) < 0) {
+ LOGE("failed to create a serial device for %s\n", pdp_args[i].ifname);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * DPRAM DRIVER INITIALIZE FUNCTIONs
+ */
+static int dpram_init_hw(void)
+{
+ int rv;
+
+ PRINT_FUNC();
+
+
+ //1) Initialize the interrupt pins
+ // set_irq_type(IRQ_DPRAM_AP_INT_N, IRQ_TYPE_LEVEL_LOW);
+ /*irq_set_irq_type(IRQ_DPRAM_AP_INT_N, IRQ_TYPE_LEVEL_LOW);*/
+
+ rv = gpio_request(IRQ_QSC_INT, "gpx1_0");
+ if(rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPX1_0\n",__func__);
+ goto err;
+ }
+
+ dpram_wakeup_irq = gpio_to_irq(IRQ_QSC_INT);
+
+ s3c_gpio_cfgpin(GPIO_C210_DPRAM_INT_N, S3C_GPIO_SFN(0xFF));
+ s3c_gpio_setpull(GPIO_C210_DPRAM_INT_N, S3C_GPIO_PULL_NONE);
+ irq_set_irq_type(dpram_wakeup_irq, IRQ_TYPE_EDGE_RISING);
+
+ rv = gpio_request(IRQ_QSC_PHONE_ACTIVE, "gpx1_6");
+ if(rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPX1_6\n",__func__);
+ goto err1;
+ }
+
+ phone_active_irq = gpio_to_irq(IRQ_QSC_PHONE_ACTIVE);
+
+ s3c_gpio_setpull(GPIO_QSC_PHONE_ACTIVE, S3C_GPIO_PULL_NONE);
+ s3c_gpio_setpull(GPIO_QSC_PHONE_RST, S3C_GPIO_PULL_NONE);
+// set_irq_type(IRQ_QSC_ACTIVE, IRQ_TYPE_EDGE_BOTH);
+ irq_set_irq_type(phone_active_irq, IRQ_TYPE_EDGE_FALLING);
+
+
+ rv = gpio_request(IRQ_CP_DUMP_INT, "gpx1_2");
+ if(rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPX1_2\n",__func__);
+ goto err6;
+ }
+
+ cp_dump_irq = gpio_to_irq(IRQ_CP_DUMP_INT);
+
+ s3c_gpio_cfgpin(GPIO_CP_DUMP_INT, S3C_GPIO_SFN(0xFF));
+ s3c_gpio_setpull(GPIO_CP_DUMP_INT, S3C_GPIO_PULL_DOWN);
+ irq_set_irq_type(cp_dump_irq, IRQ_TYPE_EDGE_RISING);
+
+
+
+ // 2)EINT15 : QSC_ACTIVE (GPIO_INTERRUPT)
+// #define FILTER_EINT15_EN (0x1<<31)
+// #define FILTER_EINT15_SEL_DEGIT (0x1<<30)
+//__raw_writel(__raw_readl(S5PV210_EINT1FLTCON1)|(FILTER_EINT15_EN & (~FILTER_EINT15_SEL_DEGIT)),S5PV210_EINT1FLTCON1);
+
+ //3)EINT09 : QSC_INT (GPIO_INTERRUPT)
+// #define FILTER_EINT9_EN (0x1<<15)
+// #define FILTER_EINT9_SEL_DEGIT (0x1<<14)
+//__raw_writel(__raw_readl(S5PV210_EINT1FLTCON0)|(FILTER_EINT9_EN & (~FILTER_EINT9_SEL_DEGIT)),S5PV210_EINT1FLTCON0);
+
+
+ // 4)gpio e3-e4 are for Modem if
+
+ s3c_gpio_cfgpin(S5PV310_GPE3_0_MDM_DATA_0, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_1_MDM_DATA_1, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_2_MDM_DATA_2, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_3_MDM_DATA_3, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_4_MDM_DATA_4, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_5_MDM_DATA_5, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_6_MDM_DATA_6, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_7_MDM_DATA_7, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+
+ s3c_gpio_cfgpin(S5PV310_GPE4_0_MDM_DATA_8, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_1_MDM_DATA_9, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_2_MDM_DATA_10, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_3_MDM_DATA_11, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_4_MDM_DATA_12, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_5_MDM_DATA_13, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_6_MDM_DATA_14, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_7_MDM_DATA_15, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+
+ s3c_gpio_cfgpin(S5PV310_GPE0_0_MDM_WEn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_1_MDM_CSn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_2_MDM_Rn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_3_MDM_IRQn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_4_MDM_ADVN, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+
+ rv = gpio_request(GPIO_PDA_ACTIVE, "GPY4_2");
+ if(rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPY4_2\n",__func__);
+ goto err2;
+ }
+
+ rv = gpio_request(GPIO_QSC_PHONE_ON, "GPC1_1");
+ if(rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPC1_1\n",__func__);
+ goto err3;
+ }
+
+ rv = gpio_request(GPIO_QSC_PHONE_RST, "GPX1_4");
+ if(rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPX1_4\n",__func__);
+ goto err4;
+ }
+
+ s5p_gpio_set_drvstr(GPIO_QSC_PHONE_RST, S5P_GPIO_DRVSTR_LV4); //To increase driving strength of this pin
+
+ //To config Not Connected pin GPY4_6 to I/P with no pullup
+ rv = gpio_request(GPIO_CP_REQ_RESET, "GPY4_6");
+ if(rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPY4_6\n",__func__);
+ goto err5;
+ }
+
+ gpio_direction_input(GPIO_CP_REQ_RESET);
+ s3c_gpio_setpull(GPIO_CP_REQ_RESET, S3C_GPIO_PULL_NONE);
+
+ // 5)PDA_ACTIVE, QSC_PHONE_ON, QSC_RESET_N
+ gpio_direction_output(GPIO_PDA_ACTIVE, GPIO_LEVEL_HIGH);
+ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_LOW);
+ s3c_gpio_setpull(GPIO_QSC_PHONE_ON, S3C_GPIO_PULL_NONE);
+ gpio_direction_output(GPIO_QSC_PHONE_RST, GPIO_LEVEL_LOW);
+
+ return 0;
+
+err6: gpio_free(IRQ_CP_DUMP_INT);
+err5: gpio_free(GPIO_QSC_PHONE_RST);
+err4: gpio_free(GPIO_QSC_PHONE_ON);
+err3: gpio_free(GPIO_PDA_ACTIVE);
+err2: gpio_free(IRQ_QSC_PHONE_ACTIVE);
+err1: gpio_free(IRQ_QSC_INT);
+err: return rv;
+}
+
+
+static int dpram_shared_bank_remap(void)
+{
+
+//Clock Settings for Modem IF ====>FixMe
+ u32 val;
+ void __iomem *regs = ioremap(0x10030000, 0x10000);
+ //PRINT_FUNC();
+ //Enabling Clock for ModemIF in Reg CLK_GATE_IP_PERIL:0x1003C950
+ val = readl(regs + 0xC950);
+ val |= 0x10000000;
+ writel(val, regs + 0xC950);
+ iounmap(regs);
+
+ //3 Get internal DPRAM / SFR Virtual address [[
+ // 1) dpram base
+ idpram_base = (volatile void __iomem *)ioremap_nocache(IDPRAM_PHYSICAL_ADDR, IDPRAM_SIZE);
+ if (idpram_base == NULL)
+ {
+ LOGE("Failed!!! (idpram_base == NULL)\n");
+ return -1;
+ }
+ LOGA("BUF PA = 0x%08X, VA = 0x%08X\n", (u32)IDPRAM_PHYSICAL_ADDR,
+ (u32)idpram_base);
+
+ // 2) sfr base
+ idpram_sfr_base = (volatile IDPRAM_SFR __iomem *)ioremap_nocache(IDPRAM_SFR_PHYSICAL_ADDR, IDPRAM_SFR_SIZE);
+ if (idpram_sfr_base == NULL)
+ {
+ LOGE("Failed!!! (idpram_sfr_base == NULL)\n");
+ iounmap(idpram_base);
+ return -1;
+ }
+ LOGA("SFR PA = 0x%08X, VA = 0x%08X\n", (u32)IDPRAM_SFR_PHYSICAL_ADDR,
+ (u32)idpram_sfr_base);
+
+ // 3) Initialize the Modem interface block(internal DPRAM)
+ // TODO : Use DMA controller? ask to sys.lsi
+ // set Modem interface config register
+ idpram_sfr_base->mifcon = (IDPRAM_MIFCON_FIXBIT|IDPRAM_MIFCON_INT2APEN|IDPRAM_MIFCON_INT2MSMEN); //FIXBIT enable, interrupt enable AP,MSM(CP)
+ idpram_sfr_base->mifpcon = (IDPRAM_MIFPCON_ADM_MODE); //mux mode
+
+ dpram_mbx_BA = (volatile u16*)(idpram_base + IDPRAM_AP2MSM_INT_OFFSET);
+ dpram_mbx_AB = (volatile u16*)(idpram_base + IDPRAM_MSM2AP_INT_OFFSET);
+ LOGA("VA of mbx_BA = 0x%08X, VA of mbx_AB = 0x%08X\n", (u32)dpram_mbx_BA,
+ (u32)dpram_mbx_AB);
+
+ // write the normal boot magic key for CDMA boot
+ *((unsigned int *)idpram_base) = DPRAM_BOOT_NORMAL;
+
+ atomic_set(&dpram_read_lock, 0);
+ atomic_set(&dpram_write_lock, 0);
+
+ return 0;
+}
+
+static void dpram_init_devices(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_INDEX; i++) {
+ //init_MUTEX(&dpram_table[i].serial.sem);
+ sema_init(&dpram_table[i].serial.sem, 1);
+
+ dpram_table[i].serial.open_count = 0;
+ dpram_table[i].serial.tty = NULL;
+ }
+}
+
+void dpram_wakeup_init(void)
+{
+ idpram_sfr_base->mifcon = (IDPRAM_MIFCON_FIXBIT|IDPRAM_MIFCON_INT2APEN|IDPRAM_MIFCON_INT2MSMEN);
+ idpram_sfr_base->mifpcon = (IDPRAM_MIFPCON_ADM_MODE);
+
+ // mux GPIO_DPRAM_INT_CP_N to dpram interrupt
+
+ s3c_gpio_cfgpin(S5PV310_GPE0_0_MDM_WEn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_1_MDM_CSn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_2_MDM_Rn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_3_MDM_IRQn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_4_MDM_ADVN, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+
+}
+
+#define WAKESTART_TIMEOUT (HZ/10)
+#define WAKESTART_TIMEOUT_RETRY 5
+
+void dpram_wait_wakeup_start(void)
+{
+ int wakeup_retry = WAKESTART_TIMEOUT_RETRY;
+ int timeout_ret = 0;
+
+ do {
+ init_completion(&g_complete_dpramdown);
+ dpram_send_mbx_BA_cmd(INT_COMMAND(MBX_CMD_PDA_WAKEUP));
+ timeout_ret = wait_for_completion_timeout(&g_complete_dpramdown, WAKESTART_TIMEOUT);
+ } while(!timeout_ret && wakeup_retry--);
+
+ if (!timeout_ret)
+ {
+ LOGE("T-I-M-E-O-U-T !!!\n");
+ }
+
+ g_dpram_wpend = IDPRAM_WPEND_UNLOCK; // dpram write unlock
+}
+
+static void kill_tasklets(void)
+{
+ tasklet_kill(&fmt_res_ack_tasklet);
+ tasklet_kill(&raw_res_ack_tasklet);
+
+ tasklet_kill(&fmt_send_tasklet);
+ tasklet_kill(&raw_send_tasklet);
+}
+
+static int register_interrupt_handler(void)
+{
+ int retval = 0;
+
+ dpram_irq = IRQ_DPRAM_AP_INT_N;
+
+ dpram_clear();
+
+ //1)dpram interrupt
+ IDPRAM_INT_CLEAR();
+ retval = request_irq(dpram_irq, dpram_irq_handler, IRQF_TRIGGER_NONE, "DPRAM irq", NULL);
+ if (retval)
+ {
+ LOGE("DPRAM interrupt handler failed.\n");
+ unregister_dpram_driver();
+ return -1;
+ }
+
+ //2) wake up for internal dpram
+
+ retval = request_irq(dpram_wakeup_irq, dpram_wake_from_CP_irq_handler, IRQF_DISABLED, "QSC_INT irq", NULL);
+ if (retval)
+ {
+ LOGE("DPRAM wakeup interrupt handler failed.\n");
+ free_irq(dpram_irq, NULL);
+ unregister_dpram_driver();
+ return -1;
+ }
+ enable_irq_wake(dpram_wakeup_irq);
+
+ //3) phone active interrupt
+ retval = request_irq(phone_active_irq, phone_active_irq_handler, IRQF_DISABLED, "QSC_ACTIVE", NULL);
+ if (retval)
+ {
+ LOGE("Phone active interrupt handler failed.\n");
+ free_irq(dpram_irq, NULL);
+ free_irq(dpram_wakeup_irq, NULL);
+ unregister_dpram_driver();
+ return -1;
+ }
+ enable_irq_wake(phone_active_irq);
+
+
+ //4) cp dump int interrupt for LPA mode
+ retval = request_irq(cp_dump_irq, cp_dump_irq_handler, IRQF_DISABLED, "CP_DUMP_INT irq", NULL);
+ if (retval)
+ {
+ LOGE("CP_DUMP_INT interrupt handler failed.\n");
+ free_irq(dpram_irq, NULL);
+ free_irq(dpram_wakeup_irq, NULL);
+ free_irq(phone_active_irq, NULL);
+ unregister_dpram_driver();
+ return -1;
+ }
+ enable_irq_wake(cp_dump_irq);
+
+
+
+ return 0;
+}
+
+static void check_miss_interrupt(void)
+{
+ unsigned long flags;
+
+ if (gpio_get_value(GPIO_QSC_PHONE_ACTIVE) && \
+ !gpio_get_value(GPIO_DPRAM_INT_CP_N)) {
+ printk(KERN_INFO "[IDPRAM] %s", __func__);
+ local_irq_save(flags);
+ dpram_irq_handler(IRQ_DPRAM_AP_INT_N, NULL);
+ local_irq_restore(flags);
+ }
+}
+
+/*
+ * INTERANL DPRAM POWER DOWN FUNCTION
+ */
+
+
+/*
+ * void dpram_power_down()
+ *
+ * This function release the wake_lock
+ * Phone send DRPAM POWER DOWN interrupt and handler call this function.
+ */
+static void dpram_power_down(void)
+{
+#ifdef PRINT_DPRAM_PWR_CTRL
+ LOGA("Received MBX_CMD_DPRAM_DOWN (lock count = %d)!!!\n",
+ dpram_get_lock_read());
+#endif
+ complete(&g_complete_dpramdown);
+}
+
+
+static void dpram_powerup_start(void)
+{
+#ifdef PRINT_DPRAM_PWR_CTRL
+ LOGA("Received MBX_CMD_CP_WAKEUP_START!!!\n");
+#endif
+ complete(&g_complete_dpramdown);
+}
+
+
+/*
+ * void dpram_power_up()
+ *
+ * Initialize dpram when ap wake up and send WAKEUP_INT to phone
+ * This function will be called by Onedram_resume()
+ */
+static inline void dpram_power_up(void)
+{
+ const u16 magic_code = 0x00AA;
+ u16 acc_code = 0x0001;
+
+ dpram_clear();
+
+ WRITE_TO_DPRAM(DPRAM_MAGIC_CODE_ADDRESS, &magic_code, sizeof(magic_code));
+ WRITE_TO_DPRAM(DPRAM_ACCESS_ENABLE_ADDRESS, &acc_code, sizeof(acc_code));
+
+ // Initialize the dpram controller
+ dpram_wakeup_init();
+
+#ifdef PRINT_DPRAM_PWR_CTRL
+ // Check for QSC_INT for debugging
+ LOGA("dpram_wakeup_init() ==> QSC_INT = %s\n",
+ gpio_get_value(GPIO_QSC_INT) ? "HIGH" : "LOW");
+#endif
+}
+
+
+/*
+ * DPRAM DRIVER FUNCTIONs
+ */
+#define DPRAMDOWN_TIMEOUT (HZ * 3)
+#define DPRAM_PDNINTR_RETRY_CNT 2
+
+/*
+** lock the AP write dpram and send the SLEEP INT to Phone
+*/
+static int dpram_suspend(struct platform_device *dev, pm_message_t state)
+{
+ u16 in_intr = 0;
+ u16 timeout_ret = 0;
+ u16 suspend_retry = DPRAM_PDNINTR_RETRY_CNT;
+
+ g_dpram_wpend = IDPRAM_WPEND_LOCK; // dpram write lock
+
+ /*
+ ** if some intrrupt was received by cp, dpram hold the wake lock and pass the suspend mode.
+ */
+ if (dpram_get_lock_read() == 0)
+ {
+ /*
+ ** retry sending MBX_CMD_PDA_SLEEP if CP does not send in timout
+ */
+ do {
+ init_completion(&g_complete_dpramdown);
+ dpram_send_mbx_BA_cmd(INT_COMMAND(MBX_CMD_PDA_SLEEP));
+ //timeout_ret = wait_for_completion_timeout(&g_complete_dpramdown, DPRAMDOWN_TIMEOUT);
+ timeout_ret = wait_for_completion_timeout(&g_complete_dpramdown, msecs_to_jiffies(500));
+#ifdef PRINT_DPRAM_PWR_CTRL
+ LOGA("suspend_enter cnt = %d\n", (DPRAM_PDNINTR_RETRY_CNT - suspend_retry));
+#endif
+ } while ( !timeout_ret && suspend_retry-- );
+
+ in_intr = ioread16((void *)dpram_mbx_AB);
+ if (in_intr != (INT_MASK_VALID|INT_MASK_COMMAND|MBX_CMD_DPRAM_DOWN))
+ {
+ LOGE("T-I-M-E-O-U-T !!! (intr = 0x%04X)\n", in_intr);
+ g_dpram_wpend = IDPRAM_WPEND_UNLOCK; // dpram write unlock
+
+ if (g_phone_sync == 0)
+ {
+ LOGE("phone_sync: [%d] retry Phone reset and on\n", g_phone_sync);
+ dpram_phone_reset();
+ dpram_phone_power_on();
+ }
+ return -1;
+ }
+
+ /*
+ * Because, if dpram was powered down, cp dpram random intr was ocurred,
+ * So, fixed by muxing cp dpram intr pin to GPIO output high,..
+ */
+ gpio_set_value(S5PV310_GPE0_3_MDM_IRQn, GPIO_LEVEL_HIGH);
+
+ s3c_gpio_cfgpin(S5PV310_GPE0_0_MDM_WEn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_1_MDM_CSn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_2_MDM_Rn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_3_MDM_IRQn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_4_MDM_ADVN, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+
+ gpio_set_value(GPIO_PDA_ACTIVE, GPIO_LEVEL_LOW);
+
+ flush_work(&phone_active_work.work);
+
+ //To configure AP_WAKE wakable interrupt
+ /* block this irq diable routine.*/
+ /* When CP send the interrupt after dpram_susepnd, */
+ /*int pending resister is not set until CPU sleep.*/
+ /* Becuase irq is disabled.*/
+ /*disable_irq(dpram_wakeup_irq);
+ enable_irq_wake(dpram_wakeup_irq);*/
+ }
+ else
+ {
+ //wake_lock_timeout(&dpram_wake_lock, HZ/4);
+ LOGA("Skip the suspned mode - read lock \n");
+ g_dpram_wpend = IDPRAM_WPEND_UNLOCK; // dpram write unlock
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int dpram_resume(struct platform_device *dev)
+{
+ gpio_set_value(GPIO_PDA_ACTIVE, GPIO_LEVEL_HIGH);
+
+ dpram_power_up();
+ dpram_wait_wakeup_start(); // wait the CP ack 0xCE
+
+ //To configure AP_WAKE normal interrupt
+ /*disable_irq_wake(dpram_wakeup_irq);
+ enable_irq(dpram_wakeup_irq);*/
+
+ /*check_miss_interrupt();*/
+ return 0;
+}
+
+
+static int __devinit dpram_probe(struct platform_device *dev)
+{
+ int retval;
+
+ PRINT_FUNC();
+
+ retval = register_dpram_driver();
+ if (retval) {
+ LOGE("Failed to register dpram (tty) driver.\n");
+ return -1;
+ }
+
+ LOGA("register_dpram_driver() success!!!\n");
+
+#ifdef _ENABLE_ERROR_DEVICE
+ retval = register_dpram_err_device();
+ if (retval) {
+ LOGE("Failed to register dpram error device. (%d)\n", retval);
+ unregister_dpram_driver();
+ return -1;
+ }
+ memset((void *)dpram_err_buf, 0, sizeof(dpram_err_buf));
+ LOGA("register_dpram_err_device() success!!!\n");
+
+ retval = register_dpram_dump_device();
+ if (retval) {
+ LOGE("Failed to register dpram dump device. (%d)\n", retval);
+ unregister_dpram_driver();
+ return -1;
+ }
+ memset((void *)cp_ramdump_buff, 0, sizeof(cp_ramdump_buff));
+ LOGA("register_dpram_dump_device() success!!!\n");
+
+ init_completion(&wait_dump_data);
+#endif /* _ENABLE_ERROR_DEVICE */
+
+ retval = misc_register(&multipdp_dev); /* create app. interface device */
+ if (retval < 0)
+ {
+ LOGE("misc_register() failed\n");
+ return -1;
+ }
+
+ multipdp_init();
+
+ retval = dpram_init_hw();
+ if (retval < 0)
+ {
+ LOGE("dpram_init_hw() failed\n");
+ return -1;
+ }
+
+ dpram_shared_bank_remap();
+
+ //3 DJ07 Dr.J ADD [[
+ iowrite16(0, (void *)(DPRAM_VBASE + DPRAM_MAGIC_CODE_ADDRESS));
+ iowrite16(0, (void *)(DPRAM_VBASE + DPRAM_ACCESS_ENABLE_ADDRESS));
+ dpram_clear();
+ //3 ]]
+
+ dpram_init_devices();
+
+ atomic_set(&raw_txq_req_ack_rcvd, 0);
+ atomic_set(&fmt_txq_req_ack_rcvd, 0);
+
+ wake_lock_init(&dpram_wake_lock, WAKE_LOCK_SUSPEND, "DPRAM_PWDOWN");
+ INIT_DELAYED_WORK(&phone_active_work, phone_active_work_func);
+
+ retval = register_interrupt_handler();
+ if ( retval < 0 )
+ {
+ LOGE("register_interrupt_handler() failed!!!\n");
+
+ gpio_free(IRQ_CP_DUMP_INT);
+ gpio_free(GPIO_QSC_PHONE_RST);
+ gpio_free(GPIO_QSC_PHONE_ON);
+ gpio_free(GPIO_PDA_ACTIVE);
+ gpio_free(IRQ_QSC_PHONE_ACTIVE);
+ gpio_free(IRQ_QSC_INT);
+
+ return -1;
+ }
+
+#ifdef CONFIG_PROC_FS
+ create_proc_read_entry(DRIVER_PROC_ENTRY, 0, 0, dpram_read_proc, NULL);
+#endif /* CONFIG_PROC_FS */
+//DI20 Dr.J ... cdma_slot_switch_handler = slot_switch_handler2;
+
+ //check_miss_interrupt();
+ init_completion(&g_complete_dpramdown);
+ printk("IDPRAM: DPRAM driver is registered !!!\n");
+
+ return 0;
+}
+
+static int __devexit dpram_remove(struct platform_device *dev)
+{
+ //PRINT_FUNC();
+
+ free_irq(IRQ_DPRAM_AP_INT_N, NULL);
+ free_irq(phone_active_irq, NULL);
+ free_irq(dpram_wakeup_irq, NULL);
+ free_irq(cp_dump_irq, NULL);
+
+ /* @LDK@ unregister dpram (tty) driver */
+ unregister_dpram_driver();
+
+ /* @LDK@ unregister dpram error device */
+#ifdef _ENABLE_ERROR_DEVICE
+ unregister_dpram_err_device();
+ unregister_dpram_dump_device();
+#endif
+
+ /* remove app. interface device */
+ misc_deregister(&multipdp_dev);
+
+ wake_lock_destroy(&dpram_wake_lock);
+
+ gpio_free(IRQ_CP_DUMP_INT);
+ gpio_free(GPIO_QSC_PHONE_RST);
+ gpio_free(GPIO_QSC_PHONE_ON);
+ gpio_free(GPIO_PDA_ACTIVE);
+ gpio_free(IRQ_QSC_PHONE_ACTIVE);
+ gpio_free(IRQ_QSC_INT);
+
+ flush_work(&phone_active_work.work);
+ kill_tasklets();
+
+ return 0;
+}
+
+static void dpram_shutdown(struct platform_device *dev)
+{
+ dpram_remove(dev);
+}
+
+u32 dpram_get_phone_dump_stat(void)
+{
+ return g_dump_on;
+}
+
+EXPORT_SYMBOL(dpram_get_phone_dump_stat);
+
+static struct platform_driver platform_dpram_driver = {
+ .probe = dpram_probe,
+ .remove = __devexit_p(dpram_remove),
+ .suspend = dpram_suspend,
+ .resume = dpram_resume,
+ .shutdown = dpram_shutdown,
+ .driver = {
+ .name = "dpram-device",
+ },
+};
+
+/* init & cleanup. */
+static int __init dpram_init(void)
+{
+
+ return platform_driver_register(&platform_dpram_driver);
+}
+
+static void __exit dpram_exit(void)
+{
+ platform_driver_unregister(&platform_dpram_driver);
+}
+
+module_init(dpram_init);
+module_exit(dpram_exit);
+
+MODULE_AUTHOR("SAMSUNG ELECTRONICS CO., LTD");
+MODULE_DESCRIPTION("Internal DPRAM Device Driver.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dpram/raffaello/dpram.h b/drivers/dpram/raffaello/dpram.h
new file mode 100755
index 0000000..c6ed226
--- /dev/null
+++ b/drivers/dpram/raffaello/dpram.h
@@ -0,0 +1,418 @@
+/****************************************************************************
+
+**
+
+** COPYRIGHT(C) : Samsung Electronics Co.Ltd, 2006-2010 ALL RIGHTS RESERVED
+
+**
+
+** AUTHOR : Kim, Geun-Young <geunyoung.kim@samsung.com> @LDK@
+
+** @LDK@
+
+****************************************************************************/
+
+#ifndef __IDPRAM_H__
+#define __IDPRAM_H__
+
+/*
+** FEATURE DEFINITIONs
+*/
+#define _DEBUG
+
+#define CDMA_IPC_C210_IDPRAM
+#define DPRAM_SIZE_16KB
+
+//#define DPRAM_SIZE_32KB
+
+#if defined(DPRAM_SIZE_16KB)
+/*
+** DPRAM SETTINGS - 16K S5PC210 Internal DPRAM
+*/
+#define DPRAM_SIZE 0x4000 /* 16KB */
+#define DPRAM_PDA2PHONE_FORMATTED_BUFFER_SIZE 1020
+#define DPRAM_PDA2PHONE_RAW_BUFFER_SIZE 7160
+#define DPRAM_PHONE2PDA_FORMATTED_BUFFER_SIZE 1020
+#define DPRAM_PHONE2PDA_RAW_BUFFER_SIZE 7160
+#define DPRAM_INTERRUPT_PORT_SIZE 2
+#elif defined(DPRAM_SIZE_32KB)
+/*
+** DPRAM SETTINGS - 32K External DPRAM
+*/
+#define DPRAM_SIZE 0x8000 /* 32 KB */
+#define DPRAM_PDA2PHONE_FORMATTED_BUFFER_SIZE 4092
+#define DPRAM_PDA2PHONE_RAW_BUFFER_SIZE 12272
+#define DPRAM_PHONE2PDA_FORMATTED_BUFFER_SIZE 4092
+#define DPRAM_PHONE2PDA_RAW_BUFFER_SIZE 12272
+#define DPRAM_INTERRUPT_PORT_SIZE 2
+#else
+#error "Feature is neither DPRAM_SIZE_16KB nor DPRAM_SIZE_32KB"
+#endif /*DPRAM_SIZE_16KB*/
+
+/*
+** Memory Offsets
+*/
+#define DPRAM_START_ADDRESS 0x0000
+
+#define DPRAM_MAGIC_CODE_ADDRESS (DPRAM_START_ADDRESS)
+#define DPRAM_ACCESS_ENABLE_ADDRESS (DPRAM_START_ADDRESS + 0x0002)
+
+#define DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS (DPRAM_START_ADDRESS + 0x0004)
+#define DPRAM_PDA2PHONE_FORMATTED_HEAD_ADDRESS (DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS)
+#define DPRAM_PDA2PHONE_FORMATTED_TAIL_ADDRESS (DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS + 0x0002)
+#define DPRAM_PDA2PHONE_FORMATTED_BUFFER_ADDRESS (DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS + 0x0004)
+
+#define DPRAM_PDA2PHONE_RAW_START_ADDRESS (DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS + DPRAM_PDA2PHONE_FORMATTED_BUFFER_SIZE + 4)
+#define DPRAM_PDA2PHONE_RAW_HEAD_ADDRESS (DPRAM_PDA2PHONE_RAW_START_ADDRESS)
+#define DPRAM_PDA2PHONE_RAW_TAIL_ADDRESS (DPRAM_PDA2PHONE_RAW_START_ADDRESS + 0x0002)
+#define DPRAM_PDA2PHONE_RAW_BUFFER_ADDRESS (DPRAM_PDA2PHONE_RAW_START_ADDRESS + 0x0004)
+
+#define DPRAM_PHONE2PDA_FORMATTED_START_ADDRESS (DPRAM_PDA2PHONE_RAW_START_ADDRESS + DPRAM_PDA2PHONE_RAW_BUFFER_SIZE + 4)
+#define DPRAM_PHONE2PDA_FORMATTED_HEAD_ADDRESS (DPRAM_PHONE2PDA_FORMATTED_START_ADDRESS)
+#define DPRAM_PHONE2PDA_FORMATTED_TAIL_ADDRESS (DPRAM_PHONE2PDA_FORMATTED_START_ADDRESS + 0x0002)
+#define DPRAM_PHONE2PDA_FORMATTED_BUFFER_ADDRESS (DPRAM_PHONE2PDA_FORMATTED_START_ADDRESS + 0x0004)
+
+#define DPRAM_PHONE2PDA_RAW_START_ADDRESS (DPRAM_PHONE2PDA_FORMATTED_START_ADDRESS + (DPRAM_PHONE2PDA_FORMATTED_BUFFER_SIZE + 4))
+#define DPRAM_PHONE2PDA_RAW_HEAD_ADDRESS (DPRAM_PHONE2PDA_RAW_START_ADDRESS)
+#define DPRAM_PHONE2PDA_RAW_TAIL_ADDRESS (DPRAM_PHONE2PDA_RAW_START_ADDRESS + 0x0002)
+#define DPRAM_PHONE2PDA_RAW_BUFFER_ADDRESS (DPRAM_PHONE2PDA_RAW_START_ADDRESS + 0x0004)
+
+#if defined(DPRAM_SIZE_16KB)
+#define DPRAM_PDA2PHONE_INTERRUPT_ADDRESS 0x3FFC
+#define DPRAM_PHONE2PDA_INTERRUPT_ADDRESS 0x3FFE
+#elif defined(DPRAM_SIZE_32KB)
+#define DPRAM_PDA2PHONE_INTERRUPT_ADDRESS 0x7FFC
+#define DPRAM_PHONE2PDA_INTERRUPT_ADDRESS 0x7FFE
+#else
+#error "Feature is neither DPRAM_SIZE_16KB nor DPRAM_SIZE_32KB"
+#endif
+
+
+/*
+** Logic Values
+*/
+#define TRUE 1
+#define FALSE 0
+
+
+/*
+** INTERRUPT MASKs
+*/
+#define INT_MASK_VALID 0x0080
+#define INT_MASK_COMMAND 0x0040
+#define INT_MASK_REQ_ACK_F 0x0020
+#define INT_MASK_REQ_ACK_R 0x0010
+#define INT_MASK_RES_ACK_F 0x0008
+#define INT_MASK_RES_ACK_R 0x0004
+#define INT_MASK_SEND_F 0x0002
+#define INT_MASK_SEND_R 0x0001
+
+/*
+** INTERRUPT COMMANDs
+*/
+#define MBX_CMD_INIT_START 0x0001
+#define MBX_CMD_INIT_END 0x0002
+#define MBX_CMD_REQ_ACTIVE 0x0003
+#define MBX_CMD_RES_ACTIVE 0x0004
+#define MBX_CMD_REQ_TIME_SYNC 0x0005
+#define MBX_CMD_PHONE_RESET 0x0007
+#define MBX_CMD_PHONE_START 0x0008
+#define MBX_CMD_PHONE_COMMON_BOOT 0x0108
+#define MBX_CMD_ERR_DISPLAY 0x0009
+#define MBX_CMD_PHONE_DEEP_SLEEP 0x000A
+
+#define MBX_CMD_DPRAM_DOWN 0x000B // DPRAM_DOWN Interrupt from Modem 0xCB
+#define MBX_CMD_PDA_WAKEUP 0x000C // PDA Wake up Interrupt to Modem 0xCC
+#define MBX_CMD_PDA_SLEEP 0x000D // PDA Sleep Interrupt to Modem 0xCD
+#define MBX_CMD_CP_WAKEUP_START 0x000E // CP Send ack CE to PDA
+
+#define MBX_CMD_CDMA_DEAD 0xAB09
+
+#define INT_COMMAND(x) (INT_MASK_VALID | INT_MASK_COMMAND | x)
+#define INT_NON_COMMAND(x) (INT_MASK_VALID | x)
+
+/* special interrupt cmd indicating modem boot failure. */
+#define INT_POWERSAFE_FAIL 0xDEAD
+
+#define FORMATTED_INDEX 0
+#define RAW_INDEX 1
+#define MAX_INDEX 2
+
+
+/*
+** IOCTL COMMANDs
+*/
+#define IOC_MZ_MAGIC ('o')
+#define DPRAM_PHONE_POWON _IO(IOC_MZ_MAGIC, 0xD0)
+#define DPRAM_PHONEIMG_LOAD _IO(IOC_MZ_MAGIC, 0xD1)
+#define DPRAM_NVDATA_LOAD _IO(IOC_MZ_MAGIC, 0xD2)
+#define DPRAM_PHONE_BOOTSTART _IO(IOC_MZ_MAGIC, 0xD3)
+#define DPRAM_PHONE_BOOTTYPE _IOW(IOC_MZ_MAGIC,0xD5, unsigned int)
+//#define DPRAM_PHONE_OFF _IO(IOC_MZ_MAGIC,0xD6)
+#define IOCTL_ONEDRAM_WAKEUP _IOW(IOC_MZ_MAGIC,0xD7, unsigned int)
+//#define DPRAM_PHONE_RESET _IO(IOC_MZ_MAGIC,0xD8)
+#define DPRAM_PHONE_RAM_DUMP _IO(IOC_MZ_MAGIC,0xD9)
+
+#define IOCTL_SET_FATAL_OPERATION _IOW(IOC_MZ_MAGIC,0xDA, unsigned int)
+
+#define IOC_SEC_MAGIC (0xF0)
+#define DPRAM_PHONE_ON _IO(IOC_SEC_MAGIC, 0xC0)
+#define DPRAM_PHONE_OFF _IO(IOC_SEC_MAGIC, 0xC1)
+#define DPRAM_PHONE_GETSTATUS _IOR(IOC_SEC_MAGIC, 0xC2, unsigned int)
+//#define DPRAM_PHONE_MDUMP _IO(IOC_SEC_MAGIC, 0xC3)
+//#define DPRAM_PHONE_BATTERY _IO(IOC_SEC_MAGIC, 0xC4)
+#define DPRAM_PHONE_RESET _IO(IOC_SEC_MAGIC, 0xC5)
+#define DPRAM_PHONE_RAMDUMP_ON _IO(IOC_SEC_MAGIC, 0xC6)
+#define DPRAM_PHONE_RAMDUMP_OFF _IO(IOC_SEC_MAGIC, 0xC7)
+#define DPRAM_EXTRA_MEM_RW _IOWR(IOC_SEC_MAGIC, 0xC8, unsigned long)
+
+#define DPRAM_PHONE_UNSET_UPLOAD _IO(IOC_SEC_MAGIC, 0xCA)
+#define DPRAM_PHONE_SET_AUTOTEST _IO(IOC_SEC_MAGIC, 0xCB)
+#define DPRAM_PHONE_SET_DEBUGLEVEL _IO(IOC_SEC_MAGIC, 0xCC)
+#define DPRAM_PHONE_GET_DEBUGLEVEL _IO(IOC_SEC_MAGIC, 0xCD)
+
+#define DPRAM_PHONE_CPRAMDUMP_START _IO(IOC_SEC_MAGIC, 0xCE)
+#define DPRAM_PHONE_CPRAMDUMP_DONE _IO(IOC_SEC_MAGIC, 0xCF)
+
+#define CP_RESET_CODE 0xCDABCDAB
+
+/*
+ * COMMON BOOT DEFINITIONs
+ */
+#define CP_CHIPSET_QUALCOMM 0x100
+#define CP_CHIPSET_INFINEON 0x200
+#define CP_CHIPSET_BROADCOM 0x300
+#define AP_PLATFORM_ANDROID 0x100
+#define AP_PLATFORM_LINUX 0x300
+#define CP_ONLINE_BOOT 0x0000
+#define CP_AIRPLANE_BOOT 0x1000
+
+/*
+ * BOOT MAGIC KEY
+ */
+#define DPRAM_BOOT_NORMAL (('T'<<24) | ('B'<<16) | ('M'<<8) | 'N')
+
+
+#ifdef CDMA_IPC_C210_IDPRAM
+#define DPRAM_VBASE idpram_base
+
+/*
+** S5PC11x DPRAM REGISTER MAP
+*/
+#ifndef IDPRAM_PHYSICAL_ADDR
+#define IDPRAM_PHYSICAL_ADDR S5P_PA_MODEMIF
+#endif
+#define IDPRAM_START_ADDR ((volatile void __iomem *)idpram_base)
+#define IDPRAM_SIZE 0x4000
+
+#define IDPRAM_AP2MSM_INT_OFFSET 0x3FFC
+#define IDPRAM_MSM2AP_INT_OFFSET 0x3FFE
+
+#define IDPRAM_SFR_PHYSICAL_ADDR (IDPRAM_PHYSICAL_ADDR + 0x8000)
+#define IDPRAM_SFR_START_ADDR ((volatile void __iomem *)idpram_sfr_base)
+#define IDPRAM_SFR_INT2AP (IDPRAM_SFR_START_ADDR)
+#define IDPRAM_SFR_INT2MSM (IDPRAM_SFR_START_ADDR + 0x4)
+#define IDPRAM_SFR_MIFCON (IDPRAM_SFR_START_ADDR + 0x8)
+#define IDPRAM_SFR_MIFPCON (IDPRAM_SFR_START_ADDR + 0xC)
+#define IDPRAM_SFR_MSMINTCLR (IDPRAM_SFR_START_ADDR + 0x10)
+#define IDPRAM_SFR_DMA_TX_ADR (IDPRAM_SFR_START_ADDR + 0x14)
+#define IDPRAM_SFR_DMA_RX_ADR (IDPRAM_SFR_START_ADDR + 0x18)
+#define IDPRAM_SFR_SIZE 0x1C
+
+// It is recommended that S5PC110 write data with half-word access on the interrupt port because
+// S5PC100 overwrites tha data in INT2AP if there are INT2AP and INT2MSM sharing the same word
+#define IDPRAM_INT2MSM_MASK 0xFF
+
+#define IDPRAM_MIFCON_INT2APEN (1<<2)
+#define IDPRAM_MIFCON_INT2MSMEN (1<<3)
+#define IDPRAM_MIFCON_DMATXREQEN_0 (1<<16)
+#define IDPRAM_MIFCON_DMATXREQEN_1 (1<<17)
+#define IDPRAM_MIFCON_DMARXREQEN_0 (1<<18)
+#define IDPRAM_MIFCON_DMARXREQEN_1 (1<<19)
+#define IDPRAM_MIFCON_FIXBIT (1<<20)
+
+#define IDPRAM_MIFPCON_ADM_MODE (1<<6) // mux / demux mode
+
+#define IDPRAM_DMA_ADR_MASK 0x3FFF
+#define IDPRAM_DMA_TX_ADR_0 // shift 0
+#define IDPRAM_DMA_TX_ADR_1 // shift 16
+#define IDPRAM_DMA_RX_ADR_0 // shift 0
+#define IDPRAM_DMA_RX_ADR_1 // shift 16
+
+#define IDPRAM_INT_CLEAR() idpram_sfr_base->msmintclr = 0xFF
+
+typedef struct {
+ unsigned int int2ap;
+ unsigned int int2msm;
+ unsigned int mifcon;
+ unsigned int mifpcon;
+ unsigned int msmintclr;
+ unsigned int dma_tx_adr;
+ unsigned int dma_rx_adr;
+} IDPRAM_SFR;
+#endif
+
+/*
+** DEVICE DEFINITIONs
+*/
+#define DRIVER_NAME "DPRAM"
+#define DRIVER_PROC_ENTRY "driver/dpram"
+#define DRIVER_MAJOR_NUM 249
+#define DPRAM_DUMP_DEV_MAJOR 250
+
+/*
+** MULTI PDP DEFINITIONs
+*/
+#define APP_DEVNAME "multipdp" /* Device node name for application interface */
+#define NUM_PDP_CONTEXT 3 /* number of PDP context */
+/* Device types */
+#define DEV_TYPE_NET 0 /* network device for IP data */
+#define DEV_TYPE_SERIAL 1 /* serial device for CSD */
+#define CSD_MAJOR_NUM 248 /* Device major number */
+#define CSD_MINOR_NUM 0 /* Device minor number */
+#define MAX_PDP_CONTEXT 10 /* Maximum number of PDP context */
+#define MAX_PDP_DATA_LEN 1500 /* Maximum PDP data length */
+/* Device flags */
+#define DEV_FLAG_STICKY 0x1 /* Sticky */
+/* Maximum PDP packet length including header and start/stop bytes */
+#define MAX_PDP_PACKET_LEN (MAX_PDP_DATA_LEN + 4 + 2)
+
+
+typedef struct pdp_arg {
+ unsigned char id;
+ char ifname[16];
+} __attribute__ ((packed)) pdp_arg_t; /* Multiple PDP */
+
+
+struct pdp_hdr {
+ u16 len; /* Data length */
+ u8 id; /* Channel ID */
+ u8 control; /* Control field */
+} __attribute__ ((packed)); /* PDP data packet header format */
+
+
+/* PDP information type */
+struct pdp_info {
+ u8 id; /* PDP context ID */
+ unsigned type; /* Device type */
+ unsigned flags; /* Device flags */
+ u8 *tx_buf; /* Tx packet buffer */
+ union {
+ struct {
+ struct tty_driver tty_driver[NUM_PDP_CONTEXT]; // CSD, CDMA, TRFB, CIQ
+ int refcount;
+ struct tty_struct *tty_table[1];
+ struct ktermios *termios[1];
+ struct ktermios *termios_locked[1];
+ char tty_name[16];
+ struct tty_struct *tty;
+ struct semaphore write_lock;
+ } vs_u; /* Virtual serial interface */
+ } dev_u; /* App device interface */
+#define vn_dev dev_u.vnet_u
+#define vs_dev dev_u.vs_u
+};
+
+/*
+** DEBUG FEATUREs
+*/
+#ifdef _DEBUG
+#define _DEBUG_LOG
+#define _ENABLE_ERROR_DEVICE
+#endif
+
+#define DL_IPC 0x01<<10
+#define DL_WARN 0x01<<15
+#define DL_NOTICE 0x01<<20
+#define DL_INFO 0x01<<25
+#define DL_DEBUG 0x01<<30
+
+#ifdef _DEBUG_LOG // debug printf
+#define LOGE(s, args...) printk(KERN_ERR "IDPRAM/Err : <%s:%d> " s, __func__, __LINE__, ##args) // Error log
+#define LOGA(s, args...) printk(KERN_INFO "IDPRAM : <%s:%d> " s, __func__, __LINE__, ##args) // Alway printed
+#define LOG(s, args...) printk(KERN_INFO"IDPRAM : <%s:%d> " s, __func__, __LINE__, ##args)
+#define LOGL(mask, s, args...) do{if(mask & __log_level__) printk("IDPRAM : <%s:%d> " s, __func__, __LINE__, ##args);}while(0)
+#define PRINT_FUNC() printk(KERN_INFO "IDPRAM : %s() ...\n", __func__)
+#else
+#define LOGE(s, args...) printk("IDPRAM/Err : %s()| " s, __func__, ##args) // Error log
+#define LOGA(s, args...) printk("IDPRAM : %s()| " s, __func__, ##args) // Alway printf
+#define LOG(...)
+#define LOGL(...)
+#define PRINT_FUNC()
+#endif
+
+#ifdef _ENABLE_ERROR_DEVICE
+#define DPRAM_ERR_MSG_LEN 65
+#define DPRAM_ERR_DEVICE "dpramerr"
+#define DPRAM_DUMP_DEVICE "dpram_dump"
+#endif /* _ENABLE_ERROR_DEVICE */
+
+
+/*
+** STRUCTURE DEFINITION
+*/
+struct _param_em {
+ unsigned int offset;
+ unsigned char *addr;
+ unsigned int size;
+ int rw;
+};
+
+typedef struct dpram_serial {
+ struct tty_struct *tty; /* pointer to the tty for this device */
+ int open_count; /* number of times this port has been opened */
+ struct semaphore sem; /* locks this structure */
+} dpram_serial_t;
+
+typedef struct dpram_device {
+ /* DPRAM memory addresses */
+ unsigned long in_head_addr;
+ unsigned long in_tail_addr;
+ unsigned long in_buff_addr;
+ unsigned long in_buff_size;
+
+ unsigned long out_head_addr;
+ unsigned long out_tail_addr;
+ unsigned long out_buff_addr;
+ unsigned long out_buff_size;
+
+ unsigned int in_head_saved;
+ unsigned int in_tail_saved;
+ unsigned int out_head_saved;
+ unsigned int out_tail_saved;
+
+ u_int16_t mask_req_ack;
+ u_int16_t mask_res_ack;
+ u_int16_t mask_send;
+
+ dpram_serial_t serial;
+} dpram_device_t;
+
+typedef struct dpram_tasklet_data {
+ dpram_device_t *device;
+ u_int16_t non_cmd;
+} dpram_tasklet_data_t;
+
+struct _mem_param {
+ unsigned short addr;
+ unsigned long data;
+ int dir;
+};
+
+
+/*
+** Add more definitions
+*/
+#define GPIO_LEVEL_LOW 0
+#define GPIO_LEVEL_HIGH 1
+
+#ifdef CDMA_IPC_C210_IDPRAM
+#define IDPRAM_WPEND_LOCK (('l'<<24) | ('o'<<16) | ('c'<<8) | 'k')
+#define IDPRAM_WPEND_UNLOCK (('u'<<24) | ('n'<<16) | ('l'<<8) | 'k')
+#endif
+
+/*
+** MACRO FUNCTIONs
+*/
+
+#endif /* __IDPRAM_H__ */
diff --git a/drivers/dpram/raffaello/dpram_recovery.c b/drivers/dpram/raffaello/dpram_recovery.c
new file mode 100644
index 0000000..3a27bf9
--- /dev/null
+++ b/drivers/dpram/raffaello/dpram_recovery.c
@@ -0,0 +1,1527 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/irq.h>
+#include <linux/poll.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <mach/regs-gpio.h>
+#include <plat/gpio-cfg.h>
+#include <mach/hardware.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif /* CONFIG_PROC_FS */
+#include <linux/wakelock.h>
+#include <linux/miscdevice.h>
+#include <linux/cdev.h>
+#include <linux/netdevice.h>
+#include "dpram_recovery.h"
+#define _DEBUG_
+
+#include <mach/gpio.h>
+
+#ifdef _DEBUG_
+#define MSGCRIT "\x1b[1;31m"
+#define MSGERR "\x1b[1;33m"
+#define MSGWARN "\x1b[1;35m"
+#define MSGINFO "\x1b[1;32m"
+#define MSGDBG "\x1b[1;37m"
+
+#define MSGEND "\x1b[0m \n"
+#else
+#define MSGCRIT
+#define MSGERR
+#define MSGWARN
+#define MSGINFO
+#define MSGDBG
+#define MSGEND
+#endif
+
+#define DRIVER_NAME "dpram_recovery"
+#define MAJOR_NUM 245
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define MAKEWORD(a, b) ((u16)(((u8)(a)) | ((u16)((u8)(b))) << 8))
+#define MAKELONG(a, b) ((LONG)(((u16)(a)) | ((u32)((u16)(b))) << 16))
+#define LOWORD(l) ((u16)(l))
+#define HIWORD(l) ((u16)(((u32)(l) >> 16) & 0xFFFF))
+#define LOBYTE(w) ((u8)(w))
+#define HIBYTE(w) ((u8)(((u16)(w) >> 8) & 0xFF))
+
+#ifdef IRQ_DPRAM_AP_INT_N
+#undef IRQ_DPRAM_AP_INT_N
+#endif
+#define IRQ_DPRAM_AP_INT_N IRQ_MODEM_IF /* IDPRAM's special interrupt in AP */
+
+
+static u16 SeqIdx;
+static u16 g_TotFrame;
+static u16 g_CurFrame = 1;
+static u16 error_code = 0x0;
+
+
+struct dpram_dev {
+ int memsize;
+ int dpram_vbase;
+ struct cdev cdev;
+};
+
+static struct dpram_dev *dpram;
+static struct dpram_firmware fw;
+
+#define CRC_TAB_SIZE 256 /* 2^CRC_TAB_BITS */
+#define CRC_16_L_SEED 0xFFFF
+
+const u16 CRC_Table[CRC_TAB_SIZE] = {
+ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
+static int dpram_recovery_ioremap(struct dpram_dev *dev);
+static int dpram_recovery_modem_pwr_status(void);
+static void dpram_recovery_modem_pwroff(void);
+static int dpram_recovery_modem_pwron(void);
+static u32 dpram_recovery_ReadMagicCode(void);
+static u32 dpram_recovery_ReadMagicCode_fota(void);
+static void dpram_recovery_WriteMagicCode(u32 dwCode);
+static void dpram_recovery_WriteMagicCode_fota(u32 dwCode);
+static int dpram_recovery_dpram_Init(void);
+static int dpram_recovery_download_Init(void);
+static u16 dpram_recovery_ReadCommand(void);
+static void dpram_recovery_WriteCommand(u16 nCmd);
+static u32 dpram_recovery_check_command(u16 intr, u16 mask);
+static int dpram_recovery_wait_response(u16 cmd_mask);
+static int dpram_recovery_WaitReadyPhase(void);
+static int dpram_recovery_write_modem_firmware(struct dpram_dev *dev, char __user *firmware, int size);
+static int dpram_recovery_write_modem_full_firmware(struct dpram_dev *dev, char __user *firmware, int size);
+static u32 dpram_recovery_WriteImage(u8 * const pBuf, u32 dwWriteLen);
+static u16 dpram_recovery_CalcTotFrame(u32 nDividend, u16 nDivisor);
+static void dpram_recovery_WriteDoneRequest(void);
+static int dpram_recovery_SendDonePhase(void);
+static int dpram_recovery_UpdateRequestPhase(void);
+static u32 dpram_recovery_DownloadControl(u8 *pBufIn, u32 Len);
+static u32 dpram_recovery_DownloadControl_fullfirmware(u8 *pBufIn, u32 Len);
+static u32 dpram_recovery_StatusNotiPhase(u32 *pPercent, u8 *UpDoneNotiFlag);
+static u32 dpram_recovery_StatusNotiPhase_download(u32 *pPercent, u8 *UpDoneNotiFlag);
+static int dpram_recovery_check_status(struct dpram_dev *dev, int __user *pct);
+static int dpram_recovery_check_status_download(struct dpram_dev *dev, int __user *pct);
+static int register_interrupt_handler(void);
+
+typedef struct Up_Noti {
+ u16 Bop;
+ u16 progress_status;
+ u16 error_code;
+ u16 Eop;
+} Status_UpNoti, *pStatus_UpNoti;
+
+typedef struct Up_Notification {
+ u16 Bop;
+ u16 Region;
+ u16 Percent;
+ u16 Eop;
+} Check_UpNoti;
+
+static int
+__inline __writel_once(struct dpram_dev *dev, int addr, int data)
+{
+ *(int *)(dev->dpram_vbase+addr) = data;
+
+ return 0;
+}
+
+static int
+dpram_recovery_ioremap(struct dpram_dev *dev)
+{
+ int i;
+
+ /*Clock Settings for Modem IF ====>FixMe */
+ u32 val;
+ void __iomem *regs = ioremap(0x10030000, 0x10000);
+
+ printk(MSGDBG "%s" MSGEND, __func__);
+ /*Enabling Clock for ModemIF in Reg CLK_GATE_IP_PERIL:0x1003C950 */
+ val = readl(regs + 0xC950);
+ val |= 0x10000000;
+ writel(val, regs + 0xC950);
+ iounmap(regs);
+
+ dev->dpram_vbase = (int)ioremap_nocache(DPRAM_BASE_ADDR, DPRAM_SIZE);
+
+ if (dev->dpram_vbase == 0) {
+ printk("failed ioremap\n");
+ return -ENOENT;
+ }
+
+ printk(KERN_DEBUG "dpram vbase=0x%8x\n", dev->dpram_vbase);
+
+ dev->memsize = DPRAM_SIZE;
+
+ printk(MSGDBG " dpram_vbase = 0x%08x" MSGEND, dev->dpram_vbase);
+ printk(MSGDBG " memsize = 0x%08x" MSGEND, dev->memsize);
+
+ for (i = 0; i < DPRAM_SIZE; i = i+4) {
+ if (__writel_once(dev, i, 0xffffffff)) {
+ printk(KERN_DEBUG "Exit during dpram initialization.\n");
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int
+dpram_recovery_modem_pwr_status(void)
+{
+ printk(KERN_ERR "%s Modem Active: %d\n", __func__, gpio_get_value(GPIO_QSC_PHONE_ACTIVE));
+
+ return gpio_get_value(GPIO_QSC_PHONE_ACTIVE);
+}
+
+static void
+dpram_recovery_modem_pwroff(void)
+{
+ int phone_wait_cnt = 0;
+
+ printk(KERN_ERR "%s\n", __func__);
+
+ /* phone power off */
+ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_LOW);
+
+ /* confirm phone off */
+ while (1) {
+ if (gpio_get_value(GPIO_QSC_PHONE_ACTIVE)) {
+ printk(KERN_ALERT"%s: Try to Turn Phone Off by CP_RST\n", __func__);
+ gpio_set_value(GPIO_QSC_PHONE_RST, 0);
+ if (phone_wait_cnt > 1) {
+ printk(KERN_ALERT "%s: PHONE OFF Failed\n", __func__);
+ break;
+ }
+ phone_wait_cnt++;
+ mdelay(1000);
+ } else {
+ printk(KERN_ALERT "%s: PHONE OFF Success\n", __func__);
+ break;
+ }
+ }
+
+}
+
+static int
+dpram_recovery_modem_pwron(void)
+{
+ printk(KERN_ERR "%s\n", __func__);
+
+ gpio_direction_output(GPIO_QSC_PHONE_RST, GPIO_LEVEL_HIGH);
+ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_LOW);
+ msleep(100);
+
+ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_HIGH);
+ msleep(400);
+ msleep(400);
+ msleep(200);
+ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_LOW);
+
+
+ return 1;
+}
+
+static u32
+dpram_recovery_ReadMagicCode(void)
+{
+ u32 dwCode;
+ u32 *dwMagicCodeAddress;
+
+ dwMagicCodeAddress = (u32 *)(dpram->dpram_vbase);
+ memcpy((void *)&dwCode, (void *)(dwMagicCodeAddress), 4);
+
+ return dwCode;
+}
+
+static void
+dpram_recovery_WriteMagicCode(u32 dwCode)
+{
+ u32 *dwMagicCodeAddress;
+ dwMagicCodeAddress = (u32 *)(dpram->dpram_vbase);
+
+ SeqIdx = 1;
+ memcpy((void *)dwMagicCodeAddress, (void *)&dwCode, 4);
+}
+
+static u32
+dpram_recovery_ReadMagicCode_fota(void)
+{
+ u32 dwCode;
+ u32 *dwMagicCodeAddress;
+
+ dwMagicCodeAddress = (u32 *)(dpram->dpram_vbase);
+ memcpy((void *)&dwCode, (void *)(dwMagicCodeAddress + 1), 4);
+
+ return dwCode;
+}
+
+static void
+dpram_recovery_WriteMagicCode_fota(u32 dwCode)
+{
+ u32 *dwMagicCodeAddress;
+ dwMagicCodeAddress = (u32 *)(dpram->dpram_vbase);
+
+ SeqIdx = 1;
+ memcpy((void *)(dwMagicCodeAddress + 1), (void *)&dwCode, 4);
+}
+
+
+static int
+dpram_recovery_dpram_Init(void)
+{
+ const u32 dwMagicCodeToWrite = MAGIC_FODN;
+ const u32 dwMagicCodeToWrite_fota = MAGIC_FOTA;
+ u32 dwMagicCode = 0;
+ u32 dwMagicCode_fota = 0;
+ int iRetry = 0, nCnt = 0;
+
+ printk(KERN_DEBUG "+DPRAM_Init\n");
+
+ /* Write the magic code */
+ for (iRetry = 1; iRetry > 0 ; iRetry--) {
+ dwMagicCode = dpram_recovery_ReadMagicCode();
+
+ if (dwMagicCode == dwMagicCodeToWrite) {
+ printk(KERN_DEBUG "dwMagicCode == dwMagicCodeToWrite!!\n");
+ break;
+ }
+ dpram_recovery_WriteMagicCode(dwMagicCodeToWrite);
+
+ dwMagicCode = dpram_recovery_ReadMagicCode();
+ printk("\n #### magic code: %x\n", dwMagicCode);
+ }
+
+ for (iRetry = 1; iRetry > 0 ; iRetry--) {
+
+ dwMagicCode_fota = dpram_recovery_ReadMagicCode_fota();
+
+ if (dwMagicCode_fota == dwMagicCodeToWrite_fota) {
+ printk(KERN_DEBUG "dwMagicCode_fota == dwMagicCodeToWrite_fota!!\n");
+ break;
+ }
+ dpram_recovery_WriteMagicCode_fota(dwMagicCodeToWrite_fota);
+
+ dwMagicCode_fota = dpram_recovery_ReadMagicCode_fota();
+ printk("\n ### magic code for FOTA: %x\n", dwMagicCode_fota);
+ }
+
+ dpram_recovery_modem_pwron();
+
+ /* Check phone on status */
+ while (!dpram_recovery_modem_pwr_status()) {
+ msleep(1000);
+ nCnt++;
+ if (nCnt >= 20) {
+ printk(KERN_DEBUG "no phone active!! \n");
+ return FALSE;
+ }
+ }
+ /* added one second delay after phone on */
+ mdelay(1000);
+ printk(KERN_DEBUG "Phone Active!!!\n");
+ printk(KERN_DEBUG "-DPRAM_Init\n");
+ return TRUE;
+}
+
+/* download */
+static int
+dpram_recovery_download_Init(void)
+{
+ const u32 dwMagicCodeToWrite = MAGIC_DMDL;
+ u32 dwMagicCode = 0;
+ int iRetry = 0, nCnt = 0;
+
+ printk(KERN_DEBUG "+DPRAM_Init\n");
+
+ /* Write the magic code */
+ for (iRetry = 1; iRetry > 0 ; iRetry--) {
+ dwMagicCode = dpram_recovery_ReadMagicCode();
+
+ if (dwMagicCode == dwMagicCodeToWrite) {
+ printk(KERN_DEBUG "dwMagicCode == dwMagicCodeToWrite!!\n");
+ break;
+ }
+ dpram_recovery_WriteMagicCode(dwMagicCodeToWrite);
+
+ dwMagicCode = dpram_recovery_ReadMagicCode();
+ printk("\n #### magic code: %x\n", dwMagicCode);
+ }
+
+ dpram_recovery_modem_pwron();
+
+ /* Check phone on status */
+ while (!dpram_recovery_modem_pwr_status()) {
+ msleep(1000);
+ nCnt++;
+ if (nCnt >= 20) {
+ printk(KERN_DEBUG "no phone active!! \n");
+ return FALSE;
+ }
+ }
+ mdelay(1000);
+ printk(KERN_DEBUG "Phone Active!!!\n");
+ printk(KERN_DEBUG "-DPRAM_Init\n");
+ return TRUE;
+}
+
+/* download */
+static u16
+dpram_recovery_ReadCommand(void)
+{
+ u16 nCmd = 0;
+
+ memcpy((void *)&nCmd, (void *)(dpram->dpram_vbase + DPRAM_PHONE2PDA_INTERRUPT_ADDRESS), 2);
+
+ return nCmd;
+}
+
+static void
+dpram_recovery_clear_modem_command(void)
+{
+ u16 clear;
+ clear = 0x0000;
+
+ printk(KERN_DEBUG "dpram_recovery_clear_modem_command\n");
+
+ memcpy((void *)(dpram->dpram_vbase + DPRAM_PHONE2PDA_INTERRUPT_ADDRESS), (void *)&clear, 2);
+}
+
+static void
+dpram_recovery_WriteCommand(u16 nCmd)
+{
+ printk(KERN_DEBUG "\n\n ###[DPRAM_WriteCommand] Start : 0x%04x \n\n", nCmd);
+
+ dpram_recovery_clear_modem_command();
+
+ memcpy((void *)(dpram->dpram_vbase + DPRAM_PDA2PHONE_INTERRUPT_ADDRESS), (void *)&nCmd, 2);
+}
+
+static u32
+dpram_recovery_check_command(u16 intr, u16 mask)
+{
+ /* There's no Interrupt from Phone. we have to poll again.*/
+ if (intr == 0) {
+ return CMD_RETRY;
+ }
+ /* Some command arrived.*/
+ else {
+ if ((intr & MASK_CMD_VALID) != MASK_CMD_VALID)
+ return CMD_RETRY;
+
+ else if ((intr & MASK_PDA_CMD) == MASK_PDA_CMD)
+ return CMD_RETRY;
+
+ else if ((intr & MASK_PHONE_CMD) == MASK_PHONE_CMD) {
+ if ((intr & mask) == mask)
+ return CMD_TRUE;
+
+ else
+ return CMD_FALSE;
+
+ } else
+ return CMD_RETRY;
+
+ }
+}
+
+static int
+dpram_recovery_wait_response(u16 cmd_mask)
+{
+ u16 intr;
+ int nRetry = 0;
+ int ret = 0;
+
+ while (1) {
+ if (nRetry > 100)
+ return FALSE;
+
+ intr = dpram_recovery_ReadCommand();
+ printk(KERN_DEBUG "intr = 0x%x\n", intr);
+
+ ret = dpram_recovery_check_command(intr, cmd_mask);
+ if (ret == CMD_TRUE) {
+ printk(KERN_DEBUG "READY ok\n");
+ return TRUE;
+ } else if (ret == CMD_FALSE) {
+ printk(KERN_DEBUG "READY failed.\n");
+ return FALSE;
+ }
+
+ nRetry++;
+ if (fw.image_type == DPRAM_MODEM_DELTA_IMAGE)
+ msleep(1000);
+ else
+ msleep(5);
+
+ }
+
+ return TRUE;
+}
+
+static int
+dpram_recovery_WaitReadyPhase(void)
+{
+ int retval = TRUE;
+
+ /* Send Delta Image Receive Ready Request */
+ printk("Writing command for modem \n");
+ dpram_recovery_WriteCommand(CMD_FOTA_IMG_RECEIVE_READY_REQ);
+
+ /* Wait Delta Image Receive Ready Response */
+ printk("Waiting for the response from Modem \n");
+ retval = dpram_recovery_wait_response(MASK_CMD_FOTA_IMG_RECEIVE_READY_RESP);
+
+ return retval;
+}
+
+static int
+dpram_recovery_WaitReadyPhase_download(void)
+{
+ int retval = TRUE;
+
+ /* Send Delta Image Receive Ready Request */
+ printk("Writing command for modem \n");
+ dpram_recovery_WriteCommand(CMD_FOTA_IMG_SEND_REQ);
+
+ /* Wait Delta Image Receive Ready Response */
+ printk("Waiting for the response from Modem \n");
+ retval = dpram_recovery_wait_response(MASK_CMD_FOTA_SEND_DONE_RESP | MASK_CMD_RESULT_SUCCESS);
+
+ return retval;
+}
+
+static int
+dpram_recovery_write_modem_firmware(
+ struct dpram_dev *dev, char __user *firmware, int size)
+{
+ int ret = FALSE;
+
+ /* Start Wait Ready Phase */
+ if (dpram_recovery_WaitReadyPhase() == FALSE) {
+ printk(" error[-2] in return %s \n", __func__);
+ ret = -2;
+ goto Exit;
+ }
+
+ /* Downlaod start Req ~ Update Status Noti */
+ ret = dpram_recovery_DownloadControl((u8 *)firmware, size);
+ if (ret < 0) {
+ printk(KERN_DEBUG "[DPRAM_Download]Failed in DownloadControl\n.");
+ goto Exit;
+ }
+ printk(KERN_DEBUG "[DPRAM_Download]FileSize : %d\n", size);
+ printk(KERN_DEBUG "[DPRAM_Download]Bootloader Image Download Completed!\n");
+
+ if (!dpram_recovery_UpdateRequestPhase()) {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] Wait FOTA Update Start Response Failed!!\n");
+ ret = -7; /* -7 means that FOTA Update Start Response failed. */
+ goto Exit;
+ }
+
+ ret = TRUE;
+
+Exit:
+ return ret;
+}
+
+static int
+dpram_recovery_write_modem_full_firmware(struct dpram_dev *dev, char __user *firmware, int size)
+{
+ int ret = FALSE;
+
+ /* Start Wait Ready Phase */
+ if (dpram_recovery_wait_response(MASK_CMD_FOTA_IMG_RECEIVE_READY_RESP) == FALSE) {
+ printk(" error[-2] in return %s \n", __func__);
+ ret = -2;
+ goto Exit;
+ }
+
+ /* Clear Response */
+ dpram_recovery_clear_modem_command();
+
+ /* Downlaod start Req ~ Update Status Noti */
+ ret = dpram_recovery_DownloadControl_fullfirmware((u8 *)firmware, size);
+ if (ret < 0) {
+ printk(KERN_DEBUG "[DPRAM_Download]Failed in DownloadControl\n.");
+ goto Exit;
+ }
+ printk(KERN_DEBUG "[DPRAM_Download]FileSize : %d\n", size);
+ printk(KERN_DEBUG "[DPRAM_Download]Bootloader Image Download Completed!\n");
+
+ ret = TRUE;
+
+Exit:
+ return ret;
+}
+
+static u16
+dpram_recovery_MakeCRC(u16 length, u16 *data_ptr_WORD)
+{
+ u16 data_crc = CRC_16_L_SEED;
+ u16 const *table = CRC_Table;
+ u8 *data_ptr = (u8 *)data_ptr_WORD;
+ int i;
+
+ for (i = 0; i < length; i++) {
+ data_crc = (((data_crc) >> 8) ^ table[((data_crc) ^ (u16)(data_ptr[i])) & 0x00ff]);
+ /*printk(KERN_DEBUG "%010d:0x%04x\r\n", i, data_crc ); */
+ }
+ /*printk(KERN_DEBUG "[MakeCRC] length:%d pt:0x%08x i:%d v:0x%04x \r\n", length, data_ptr, i, data_ptr[i] ); */
+ return data_crc;
+}
+
+static u32
+dpram_recovery_WriteImage(u8 *const pBuf, u32 dwWriteLen)
+{
+ u8 *pDest;
+ u8 *pDest_Data;
+ u16 Len;
+ u16 nCrc;
+
+ /*printk(KERN_DEBUG "Start %d 0x%04x(%d)\n", dwWriteLen, g_TotFrame, g_TotFrame);*/
+
+ pDest = (u8 *)(dpram->dpram_vbase + DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS);
+ Len = (u16)min((u32)dwWriteLen, (u32)FODN_DEFAULT_WRITE_LEN);
+
+ /*printk(KERN_DEBUG "Start : pDest(0x%08x), dwWriteLen(%d)\n",pDest, Len);*/
+
+ /* Start Index */
+ *pDest++ = LOBYTE(START_INDEX);
+ *pDest++ = HIBYTE(START_INDEX);
+
+ /*Total Frame number: */
+ *pDest++ = LOBYTE(g_TotFrame);
+ *pDest++ = HIBYTE(g_TotFrame);
+
+ /*Current Frame number; */
+ *pDest++ = LOBYTE(g_CurFrame);
+ *pDest++ = HIBYTE(g_CurFrame);
+ g_CurFrame++;
+
+ /* Length - Does it include the length of START_INDEX?? */
+ *pDest++ = LOBYTE(Len);
+ *pDest++ = HIBYTE(Len);
+
+ /* Data */
+ pDest_Data = pDest;
+ memcpy((void *)pDest, (void *)pBuf, Len);
+ pDest += Len;
+
+ /* Fill null if data length is odd */
+ if (Len%2 != 0) {
+ *pDest++ = 0xff;
+ printk(KERN_DEBUG "odd 0x%08x 0x%02x\n", (unsigned int)(pDest-1), (u8)(*pDest-1));
+ }
+
+ /*printk(KERN_DEBUG "len:%d default len:%d\n", Len, FODN_DEFAULT_WRITE_LEN);*/
+ /*printk(KERN_DEBUG "start data 0x%08x \n", pDest);*/
+
+ if (Len < FODN_DEFAULT_WRITE_LEN) {
+ memset((void *)pDest, 0x0 /*0xff*/, FODN_DEFAULT_WRITE_LEN - Len);
+ pDest += (FODN_DEFAULT_WRITE_LEN - Len) ;
+ }
+ printk(KERN_DEBUG "CRC start 0x%08x\n", (unsigned int)pDest);
+
+ nCrc = dpram_recovery_MakeCRC(Len, (u16 *)pDest_Data);
+
+ *pDest++ = LOBYTE(nCrc);
+ *pDest++ = HIBYTE(nCrc);
+
+ printk(KERN_DEBUG "CRC value 0x%04x \n", nCrc);
+
+ *pDest++ = LOBYTE(END_INDEX);
+ *pDest++ = HIBYTE(END_INDEX);
+
+ /* Write Command*/
+ dpram_recovery_WriteCommand(CMD_FOTA_IMG_SEND_REQ);
+
+ return Len;
+}
+
+static u32
+dpram_recovery_WriteImage_download(u8 *const pBuf, u32 dwWriteLen)
+{
+ u8 *pDest;
+ u8 *pDest_Data;
+ u16 Len;
+ u16 nCrc;
+
+ /*printk(KERN_DEBUG "Start %d 0x%04x(%d)\n", dwWriteLen, g_TotFrame, g_TotFrame);*/
+
+ pDest = (u8 *)(dpram->dpram_vbase + DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS);
+ Len = (u16)min((u32)dwWriteLen, (u32)FODN_DEFAULT_WRITE_LEN);
+
+ /*printk(KERN_DEBUG "Start : pDest(0x%08x), dwWriteLen(%d)\n",pDest, Len);*/
+
+ /* Start Index */
+ *pDest++ = LOBYTE(START_INDEX);
+ *pDest++ = HIBYTE(START_INDEX);
+
+ /*Total Frame number: */
+ *pDest++ = LOBYTE(g_TotFrame);
+ *pDest++ = HIBYTE(g_TotFrame);
+
+ /*Current Frame number; */
+ *pDest++ = LOBYTE(g_CurFrame);
+ *pDest++ = HIBYTE(g_CurFrame);
+ g_CurFrame++;
+
+ /* Length - Does it include the length of START_INDEX?? */
+ *pDest++ = LOBYTE(Len);
+ *pDest++ = HIBYTE(Len);
+
+ /* Data */
+ pDest_Data = pDest;
+ memcpy((void *)pDest, (void *)pBuf, Len);
+ pDest += Len;
+
+ /* Fill null if data length is odd */
+ if (Len%2 != 0) {
+ *pDest++ = 0xff;
+ printk(KERN_DEBUG "odd 0x%08x 0x%02x\n", (unsigned int)(pDest-1), (u8)(*pDest-1));
+ }
+
+ /*printk(KERN_DEBUG "len:%d default len:%d\n", Len, FODN_DEFAULT_WRITE_LEN);*/
+ /*printk(KERN_DEBUG "start data 0x%08x \n", pDest);*/
+
+ if (Len < FODN_DEFAULT_WRITE_LEN) {
+ memset((void *)pDest, 0x0 /*0xff*/, FODN_DEFAULT_WRITE_LEN - Len);
+ pDest += (FODN_DEFAULT_WRITE_LEN - Len) ;
+ }
+ printk(KERN_DEBUG "CRC start 0x%08x\n", (unsigned int)pDest);
+
+ nCrc = dpram_recovery_MakeCRC(Len, (u16 *)pDest_Data);
+
+ *pDest++ = LOBYTE(nCrc);
+ *pDest++ = HIBYTE(nCrc);
+
+ printk(KERN_DEBUG "CRC value 0x%04x \n", nCrc);
+
+ pDest = (u8 *)(dpram->dpram_vbase + BSP_DPRAM_BASE_SIZE - 2*DPRAM_INTERRUPT_SIZE - DPRAM_INDEX_SIZE);
+
+ *pDest++ = LOBYTE(END_INDEX);
+ *pDest++ = HIBYTE(END_INDEX);
+
+ /* Write Command*/
+ dpram_recovery_WriteCommand(CMD_FOTA_UPDATE_START_REQ);
+
+ return Len;
+}
+
+
+static u16
+dpram_recovery_CalcTotFrame(u32 nDividend, u16 nDivisor)
+{
+ u16 nCompVal1 = 0;
+ u16 nCompVal2 = 0;
+
+ printk(KERN_DEBUG "[CalcTotFrame](%d) %d %d\n", __LINE__, nDividend, nDivisor);
+ nCompVal1 = (u16) (nDividend / nDivisor);
+ nCompVal2 = (u16) (nDividend - (nCompVal1 * nDivisor));
+ if (nCompVal2 > 0) {
+ printk(KERN_DEBUG "[CalcTotFrame](%d) val2 : %d\n", __LINE__, nCompVal2);
+ nCompVal1++;
+ }
+ printk(KERN_DEBUG "[CalcTotFrame](%d) result %d\n", __LINE__, nCompVal1);
+ return nCompVal1;
+}
+
+static void
+dpram_recovery_WriteDoneRequest(void)
+{
+ printk(KERN_DEBUG "[DPRAM_WriteDoneRequest] Start\n");
+
+ SeqIdx = 1;
+
+ dpram_recovery_WriteCommand(CMD_FOTA_SEND_DONE_REQ);
+ printk(KERN_DEBUG "[DPRAM_WriteDoneRequest] End\n");
+}
+
+static int
+dpram_recovery_SendDonePhase(void)
+{
+ int retval = TRUE;
+
+ /* Send Write Done Request */
+ dpram_recovery_WriteDoneRequest();
+
+ /* Wait Write Done Response */
+ retval = dpram_recovery_wait_response(MASK_CMD_FOTA_SEND_DONE_RESP);
+ if (retval == FALSE) {
+ printk(KERN_DEBUG " Wait Write Done Response Failed!!\n");
+ return retval;
+ }
+
+ printk(KERN_DEBUG "Wait 0.5 secs.. .. ..\n");
+ msleep(500);
+
+ return retval;
+}
+
+static int
+dpram_recovery_UpdateRequestPhase(void)
+{
+ int retval = TRUE;
+
+ /* Send FOTA Update Start Request */
+ dpram_recovery_WriteCommand(CMD_FOTA_UPDATE_START_REQ);
+ /* Wait FOTA Update Start Response */
+ /*retval = dpram_recovery_wait_response(MASK_CMD_FOTA_UPDATE_START_RESP); */
+
+ return retval;
+}
+
+static u32
+dpram_recovery_DownloadControl(u8 *pBufIn, u32 Len)
+{
+ u32 dwWriteLen = 0, dwWrittenLen = 0, dwTotWrittenLen = 0;
+ u32 dwRet = 0;
+ u16 nTotalFrame = 0, nIntrValue = 0;
+ int nwRetry = 0, nrRetry = 0, retval;
+
+ nTotalFrame = dpram_recovery_CalcTotFrame(Len, DELTA_PACKET_SIZE);
+ g_TotFrame = nTotalFrame;
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] total frame:%d,%d\n", g_TotFrame, nTotalFrame);
+
+ while (dwTotWrittenLen < Len) {
+ /*Write proper size of image to DPRAM*/
+ printk(KERN_DEBUG "[DPRAM_DownloadControl]DPRAM_WriteImage %d/%d start\n",
+ g_CurFrame, g_TotFrame);
+ dwWriteLen = min((u32)(Len - dwTotWrittenLen), (u32)DELTA_PACKET_SIZE);
+ dwWrittenLen = dpram_recovery_WriteImage(pBufIn, dwWriteLen);
+ printk(KERN_DEBUG "[DPRAM_DownloadControl]Written data:%d\n", dwWrittenLen);
+
+ if (dwWrittenLen > 0) {
+ dwTotWrittenLen += dwWrittenLen;
+ pBufIn += dwWrittenLen;
+ } else {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl]Write Image Len is wierd.\n");
+ if (nwRetry < 3) {
+ nwRetry++;
+ printk(KERN_DEBUG "[DPRAM_DownloadControl]Retry to write. nRetry = %8x\n", nwRetry);
+ continue;
+ } else {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl]Fail to Write Image to DPRAM.\n");
+ dwRet = -3;
+ goto Exit;
+ }
+ }
+
+ /* Wait for the IMAGE WRITE RESPONSE */
+ while (nrRetry < 10) {
+ retval = dpram_recovery_wait_response(MASK_CMD_FOTA_IMG_SEND_RESP);
+ if (retval == FALSE) {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] Wait Image Send Response Failed\n");
+ dwRet = -4;
+ goto Exit;
+ } else {
+ nIntrValue = dpram_recovery_ReadCommand();
+ if ((nIntrValue & MASK_CMD_RESULT_FAIL) == 0) {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] MASK_CMD_IMAGE_SEND_RESPONSE OK issued.\n");
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] %d /%d ok\n", g_CurFrame - 1, g_TotFrame);
+ break;
+ } else {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] MASK_CMD_IMAGE_SEND_RESPONSE Failed issued.\n");
+ msleep(100);
+ nrRetry++;
+ dpram_recovery_WriteCommand(CMD_FOTA_IMG_SEND_REQ);
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] CMD_IMG_SEND_REQ retry.(%d)\n", nrRetry);
+
+ if (nrRetry >= 10) {
+ dwRet = -5;
+ goto Exit;
+ }
+ }
+ }
+ }
+ }
+
+ g_CurFrame = 1;
+
+ if (!dpram_recovery_SendDonePhase()) {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] There's something unexpeted in SendDone Phase.\n");
+ dwRet = -6; /* -6 means that SendDone Phase failed. */
+ goto Exit;
+ }
+
+Exit:
+ return dwRet;
+}
+
+static u32
+dpram_recovery_DownloadControl_fullfirmware(u8 *pBufIn, u32 Len)
+{
+ u32 dwWriteLen = 0, dwWrittenLen = 0, dwTotWrittenLen = 0;
+ u32 dwRet = 0;
+ u16 nTotalFrame = 0, nIntrValue = 0;
+ int nwRetry = 0, nrRetry = 0, retval;
+
+ /* Send command and wait for response */
+ if (dpram_recovery_WaitReadyPhase_download() == FALSE) {
+ printk(" error[-2] in return %s \n", __func__);
+ dwRet = -2;
+ goto Exit;
+ }
+
+ nTotalFrame = dpram_recovery_CalcTotFrame(Len, FODN_DEFAULT_WRITE_LEN);
+ g_TotFrame = nTotalFrame;
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] total frame:%d\n", nTotalFrame);
+
+ while (dwTotWrittenLen < Len) {
+ /*Write proper size of image to DPRAM*/
+ printk(KERN_DEBUG "[DPRAM_DownloadControl]DPRAM_WriteImage %d/%d start\n",
+ g_CurFrame, g_TotFrame);
+ dwWriteLen = min((u32)(Len - dwTotWrittenLen), (u32)FODN_DEFAULT_WRITE_LEN);
+ dwWrittenLen = dpram_recovery_WriteImage_download(pBufIn, dwWriteLen);
+ printk(KERN_DEBUG "[DPRAM_DownloadControl]Written data:%d\n", dwWrittenLen);
+
+ if (dwWrittenLen > 0) {
+ dwTotWrittenLen += dwWrittenLen;
+ pBufIn += dwWrittenLen;
+ } else {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl]Write Image Len is wierd.\n");
+ if (nwRetry < 3) {
+ nwRetry++;
+ printk(KERN_DEBUG "[DPRAM_DownloadControl]Retry to write. nRetry = %8x\n", nwRetry);
+ continue;
+ } else {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl]Fail to Write Image to DPRAM.\n");
+ dwRet = -3;
+ goto Exit;
+ }
+ }
+
+ /* Wait for the IMAGE WRITE RESPONSE */
+ while (nrRetry < 10) {
+ retval = dpram_recovery_wait_response(MASK_CMD_IMAGE_SEND_RESPONSE);
+ if (retval == FALSE) {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] Wait Image Send Response Failed\n");
+ dwRet = -4;
+ goto Exit;
+ } else {
+ nIntrValue = dpram_recovery_ReadCommand();
+ if ((nIntrValue & MASK_CMD_RESULT_FAIL) == 0) {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] MASK_CMD_IMAGE_SEND_RESPONSE OK issued.\n");
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] %d /%d ok\n", g_CurFrame - 1, g_TotFrame);
+ break;
+ } else {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] MASK_CMD_IMAGE_SEND_RESPONSE Failed issued.\n");
+ msleep(100);
+ nrRetry++;
+ dpram_recovery_WriteCommand(CMD_FOTA_UPDATE_START_REQ);
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] CMD_IMG_SEND_REQ retry.(%d)\n", nrRetry);
+
+ if (nrRetry >= 10) {
+ dwRet = -5;
+ goto Exit;
+ }
+ }
+ }
+ }
+ }
+
+ g_CurFrame = 1;
+
+ /* SendDone Phase */
+ dpram_recovery_WriteCommand(CMD_DL_SEND_DONE_REQ);
+ printk(KERN_DEBUG "[DPRAM_WriteDoneRequest] End\n");
+
+ printk(KERN_DEBUG "Wait 0.5 secs.. .. ..\n");
+ msleep(500);
+
+
+Exit:
+ return dwRet;
+}
+
+static u32
+dpram_recovery_StatusNotiPhase(u32 *pPercent, u8 *UpDoneNotiFlag)
+{
+ Status_UpNoti UpStatus;
+ u16 intr = 0, ret = 0;
+ u32 dwRet = TRUE;
+
+ UpStatus.progress_status = 0x00;
+ UpStatus.error_code = 0x00;
+
+ *UpDoneNotiFlag = FALSE;
+
+ /*dpram_recovery_WriteCommand(CMD_FOTA_UPDATE_STATUS_IND); */
+
+ /* Wait FOTA Update Status Indication */
+ dwRet = dpram_recovery_wait_response(MASK_CMD_FOTA_UPDATE_STATUS_IND);
+ if (dwRet == FALSE) {
+ printk(KERN_DEBUG "Wait FOTA Update Status Indication Failed!!\n");
+ intr = dpram_recovery_ReadCommand();
+ ret = dpram_recovery_check_command(intr, MASK_CMD_FOTA_UPDATE_END_IND);
+ if (ret == CMD_TRUE) {
+ dwRet = TRUE;
+ *UpDoneNotiFlag = TRUE;
+ printk(KERN_DEBUG "But FOTA Update Done Indication Received!!\n");
+ goto StatusRead;
+ } else
+ goto Exit;
+ }
+
+StatusRead:
+ memcpy((void *)&UpStatus, (void *)(dpram->dpram_vbase + DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS), 8);
+
+ printk(KERN_DEBUG "0x%x 0x%x 0x%x 0x%x \n", UpStatus.Bop, UpStatus.progress_status, UpStatus.error_code, UpStatus.Eop);
+
+ if ((UpStatus.Bop != START_INDEX) || (UpStatus.Eop != END_INDEX)) {
+ printk(KERN_DEBUG "Packet format is wrong.\n");
+ dwRet = 0;
+ } else {
+ printk(KERN_DEBUG "Get the Status info.\n");
+ *pPercent = (u32)UpStatus.progress_status;
+ error_code = (u16)UpStatus.error_code;
+ }
+
+ if (error_code != 0) {
+ printk(KERN_DEBUG "Update error is occured, error number:0x%x.\n", error_code);
+ dwRet = FALSE;
+ goto Exit;
+ }
+
+Exit:
+ /* Clear modem command for next IOCTL_CHK_STAT */
+ dpram_recovery_clear_modem_command();
+
+ return dwRet;
+}
+
+static u32
+dpram_recovery_StatusNotiPhase_download(u32 *pPercent, u8 *UpDoneNotiFlag)
+{
+ Check_UpNoti upstatus;
+ u16 ret = 0;
+ u32 dwRet = TRUE;
+
+ upstatus.Region = 0x0;
+ upstatus.Percent = 0x0;
+
+ *UpDoneNotiFlag = FALSE;
+
+ dwRet = dpram_recovery_wait_response(MASK_CMD_UPDATE_DONE_NOTIFICATION|MASK_CMD_RESULT_SUCCESS);
+ if (dwRet == FALSE) {
+ dwRet = dpram_recovery_wait_response(MASK_CMD_STATUS_UPDATE_NOTIFICATION|MASK_CMD_RESULT_SUCCESS);
+ if (dwRet == TRUE) {
+ printk(KERN_DEBUG "Received UPDATE Status Notification Command in %s", __func__);
+ goto StatusRead;
+ } else {
+ ret = FALSE;
+ goto Exit;
+ }
+ } else {
+ printk(KERN_DEBUG " Successfully Received UPDATE DONE Command in %s", __func__);
+ *UpDoneNotiFlag = TRUE;
+ ret = TRUE;
+ goto StatusRead;
+ }
+
+StatusRead:
+ dpram_recovery_clear_modem_command();
+ memcpy((void *)&upstatus, (void *)(dpram->dpram_vbase + DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS), 8);
+ if ((upstatus.Bop != START_INDEX) || (upstatus.Eop != END_INDEX)) {
+ printk(KERN_DEBUG "CP Update Failed by Bad Header!! \n");
+ printk(KERN_DEBUG "0x%x 0x%x \n", upstatus.Bop, upstatus.Eop);
+ ret = FALSE;
+ goto Exit;
+ } else {
+ *pPercent = upstatus.Percent;
+ printk(KERN_DEBUG "Region= 0x%x Percent = 0x%x \n", upstatus.Region, upstatus.Percent);
+ ret = TRUE;
+ }
+Exit:
+ /* Clear modem command for next IOCTL_CHK_STAT */
+ dpram_recovery_clear_modem_command();
+ return ret;
+
+}
+
+static int
+dpram_recovery_check_status(struct dpram_dev *dev, int __user *pct)
+{
+ u32 bUpStatusPer = 0, PrevbUpStatusPer = 0;
+ u8 UpDoneNotiFlag = 0;
+ u32 dwRet = 1;
+ int retval = 0;
+
+ /* Process for UPDATE STATUS Noti. phase. */
+ retval = dpram_recovery_StatusNotiPhase(&bUpStatusPer, &UpDoneNotiFlag);
+ if (retval == FALSE) {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] Wait Status Noti Phase Failed!!\n");
+ dwRet = -8;
+ } else {
+ printk(KERN_DEBUG "Progress:%d\n", bUpStatusPer);
+
+ if (bUpStatusPer > PrevbUpStatusPer)
+ PrevbUpStatusPer = bUpStatusPer;
+
+ *pct = bUpStatusPer;
+
+ if ((bUpStatusPer == 100) && (UpDoneNotiFlag == TRUE)) {
+ printk(KERN_DEBUG "Done!!!\n");
+ dwRet = 0;
+ }
+ }
+
+ return dwRet;
+}
+
+static int
+dpram_recovery_check_status_download(struct dpram_dev *dev, int __user *pct)
+{
+ u32 bUpStatusPer = 0, PrevbUpStatusPer = 0;
+ u8 UpDoneNotiFlag = 0;
+ u32 dwRet = 1;
+ int retval = 0;
+
+ /* Process for UPDATE STATUS Noti. phase. */
+ retval = dpram_recovery_StatusNotiPhase_download(&bUpStatusPer, &UpDoneNotiFlag);
+ if (retval == FALSE) {
+ printk(KERN_DEBUG "[DPRAM_DownloadControl] Wait Status Noti Phase Failed!!\n");
+ dwRet = -8;
+ } else {
+ printk(KERN_DEBUG "Progress:%d\n", bUpStatusPer);
+
+ if (bUpStatusPer > PrevbUpStatusPer)
+ PrevbUpStatusPer = bUpStatusPer;
+
+ *pct = bUpStatusPer;
+
+ if ((bUpStatusPer == 100) && (UpDoneNotiFlag == TRUE)) {
+ printk(KERN_DEBUG "Done!!!\n");
+ dwRet = 0;
+ }
+ }
+
+ return dwRet;
+}
+
+static ssize_t
+dpram_recovery_read(struct file *filp, char __user *buff,
+ size_t count, loff_t *fpos)
+{
+ return 0;
+}
+
+static ssize_t
+dpram_recovery_write(struct file *filp, const char __user *buff,
+ size_t size, loff_t *fpos)
+{
+ return 0;
+}
+
+static long
+dpram_recovery_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
+
+{
+ struct dpram_dev *dev;
+ int ret = 0, ret_check = 0;
+ u32 magic_code = 0x0;
+
+ printk(MSGDBG "%s" MSGEND, __func__);
+ printk(KERN_ERR "%s\n", __func__);
+
+ dev = container_of(filp->f_path.dentry->d_inode->i_cdev, struct dpram_dev, cdev);
+
+ switch (cmd) {
+ case IOCTL_WRITE_MAGIC_CODE:
+ dpram_recovery_dpram_Init();
+ break;
+
+ case IOCTL_ST_FW_UPDATE:
+ printk(KERN_ERR "%s IOCTL_ST_FW_UPDATE\n", __func__);
+
+ if (arg == 0) {
+ printk(MSGWARN "Firmware should be written prior to this call" MSGEND);
+ } else {
+ ret_check = copy_from_user((void *)&fw, (void *)arg, sizeof(fw));
+ if (ret_check) {
+ printk("[IOCTL_ST_FW_UPDATE]copy from user failed!");
+ return -EFAULT;
+ }
+ }
+
+ /* Dpram Phone off */
+ dpram_recovery_modem_pwroff();
+ if (fw.image_type == DPRAM_MODEM_DELTA_IMAGE) {
+ /* Enter FOTA Update Mode */
+ dpram_recovery_dpram_Init();
+ ret = dpram_recovery_write_modem_firmware(dev, fw.firmware, fw.size);
+ if (ret < 0) {
+ printk("firmware write failed\n");
+ }
+
+ } else {
+ /* Enter Download Mode */
+ dpram_recovery_download_Init();
+ ret = dpram_recovery_write_modem_full_firmware(dev, fw.firmware, fw.size);
+ if (ret < 0) {
+ printk("firmware write failed\n");
+ }
+ }
+ break;
+ case IOCTL_CHK_STAT:
+ {
+ struct stat_info *pst;
+
+ printk(KERN_ERR "%s IOCTL_CHK_STAT\n", __func__);
+ pst = (struct stat_info *)arg;
+ if (fw.image_type == DPRAM_MODEM_DELTA_IMAGE) {
+ ret = dpram_recovery_check_status(dev, &(pst->pct));
+ } else {
+ ret = dpram_recovery_check_status_download(dev, &(pst->pct));
+ }
+ }
+ break;
+
+ case IOCTL_MOD_PWROFF:
+ printk(KERN_ERR "%s IOCTL_MOD_PWROFF\n", __func__);
+
+ msleep(2000); /* Delay for display */
+
+ /* Clear Magic Code */
+ dpram_recovery_WriteMagicCode(magic_code);
+
+ dpram_recovery_modem_pwroff();
+ break;
+
+ default:
+ printk(KERN_ERR "Unknown command");
+ break;
+ }
+
+ return ret;
+}
+
+static int
+dpram_recovery_open(struct inode *inode, struct file *filp)
+{
+ struct dpram_dev *dev;
+
+ printk(KERN_ERR "%s\n", __func__);
+
+ dev = container_of(inode->i_cdev, struct dpram_dev, cdev);
+ filp->private_data = (void *)dev;
+
+ return 0;
+}
+
+static int
+dpram_recovery_release(struct inode *inode, struct file *filp)
+{
+ printk(KERN_DEBUG "dpram recovery device released.\n");
+ return 0;
+}
+
+
+static struct file_operations dpram_recovery_fops = {
+ .owner = THIS_MODULE,
+ .read = dpram_recovery_read,
+ .write = dpram_recovery_write,
+ .unlocked_ioctl = dpram_recovery_ioctl,
+ .open = dpram_recovery_open,
+ .release = dpram_recovery_release,
+};
+
+static int register_dpram_rec_device(void)
+{
+ struct device *dpram_rec_dev_t;
+ struct class *dpram_rec_class;
+ int ret;
+
+ ret = register_chrdev(MAJOR_NUM, DRIVER_NAME, &dpram_recovery_fops);
+ if (ret < 0) {
+ goto err;
+ }
+
+ dpram_rec_class = class_create(THIS_MODULE, "rec");
+ if (IS_ERR(dpram_rec_class)) {
+ ret = -EFAULT;
+ goto err1;
+ }
+
+ dpram_rec_dev_t = device_create(dpram_rec_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, DRIVER_NAME);
+ if (IS_ERR(dpram_rec_dev_t)) {
+ ret = -EFAULT;
+ goto err2;
+ }
+
+ return 0;
+
+err2:
+ class_destroy(dpram_rec_class);
+
+err1:
+ unregister_chrdev(MAJOR_NUM, DRIVER_NAME);
+
+err:
+ return ret;
+}
+
+/* Dpram Interrupt register */
+static irqreturn_t phone_active_irq_handler(int irq, void *dev_id)
+{
+
+ printk(KERN_ERR "Received interrupt for PHONE ACTIVE \n");
+ if (gpio_get_value(GPIO_QSC_PHONE_ACTIVE)) {
+ printk(KERN_ALERT "%s: Phone Active high and Modem is ON\n", __func__);
+ } else {
+ printk(KERN_ALERT "%s: Phone Active Low and Modem is OFF\n", __func__);
+ }
+ return IRQ_HANDLED;
+}
+
+static int register_interrupt_handler(void)
+{
+ int retval = 0, phone_active_irq;
+ phone_active_irq = gpio_to_irq(IRQ_QSC_PHONE_ACTIVE);
+
+ /* phone active interrupt */
+ retval = request_irq(phone_active_irq, phone_active_irq_handler, IRQF_DISABLED, "QSC_ACTIVE", NULL);
+ if (retval) {
+ printk(KERN_ERR "Phone active interrupt handler failed.\n");
+ }
+
+ return 0;
+}
+
+/*
+ * DPRAM DRIVER INITIALIZE FUNCTIONs
+ */
+int dpram_init_hw(void)
+{
+ int rv;
+ int phone_active_irq, dpram_wakeup_irq;
+
+ /* 1) Initialize the interrupt pins */
+ irq_set_irq_type(IRQ_DPRAM_AP_INT_N, IRQ_TYPE_LEVEL_LOW);
+ rv = gpio_request(IRQ_QSC_INT, "gpx1_0");
+ if (rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPX1_0\n", __func__);
+ goto err;
+ }
+ dpram_wakeup_irq = gpio_to_irq(IRQ_QSC_INT);
+ s3c_gpio_cfgpin(GPIO_C210_DPRAM_INT_N, S3C_GPIO_SFN(0xFF));
+ s3c_gpio_setpull(GPIO_C210_DPRAM_INT_N, S3C_GPIO_PULL_NONE);
+ irq_set_irq_type(dpram_wakeup_irq, IRQ_TYPE_EDGE_RISING);
+
+ rv = gpio_request(IRQ_QSC_PHONE_ACTIVE, "gpx1_6");
+ if (rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPX1_6\n", __func__);
+ goto err1;
+ }
+
+ phone_active_irq = gpio_to_irq(IRQ_QSC_PHONE_ACTIVE);
+
+ s3c_gpio_setpull(GPIO_QSC_PHONE_ACTIVE, S3C_GPIO_PULL_NONE);
+ s3c_gpio_setpull(GPIO_QSC_PHONE_RST, S3C_GPIO_PULL_NONE);
+ irq_set_irq_type(phone_active_irq, IRQ_TYPE_EDGE_FALLING);
+ /* 4)gpio e3-e4 are for Modem if */
+
+ s3c_gpio_cfgpin(S5PV310_GPE3_0_MDM_DATA_0, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_1_MDM_DATA_1, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_2_MDM_DATA_2, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_3_MDM_DATA_3, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_4_MDM_DATA_4, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_5_MDM_DATA_5, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_6_MDM_DATA_6, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE3_7_MDM_DATA_7, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+
+ s3c_gpio_cfgpin(S5PV310_GPE4_0_MDM_DATA_8, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_1_MDM_DATA_9, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_2_MDM_DATA_10, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_3_MDM_DATA_11, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_4_MDM_DATA_12, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_5_MDM_DATA_13, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_6_MDM_DATA_14, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE4_7_MDM_DATA_15, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+
+ s3c_gpio_cfgpin(S5PV310_GPE0_0_MDM_WEn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_1_MDM_CSn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_2_MDM_Rn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_3_MDM_IRQn, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+ s3c_gpio_cfgpin(S5PV310_GPE0_4_MDM_ADVN, S3C_GPIO_SFN(S5PV310_MDM_IF_SEL));
+
+ rv = gpio_request(GPIO_PDA_ACTIVE, "GPY4_2");
+ if (rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPY4_2\n", __func__);
+ goto err2;
+ }
+
+ rv = gpio_request(GPIO_QSC_PHONE_ON, "GPC1_1");
+ if (rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPC1_1\n", __func__);
+ goto err3;
+ }
+
+ rv = gpio_request(GPIO_QSC_PHONE_RST, "GPX1_4");
+ if (rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPX1_4\n", __func__);
+ goto err4;
+ }
+
+ s5p_gpio_set_drvstr(GPIO_QSC_PHONE_RST, S5P_GPIO_DRVSTR_LV4); /*To increase driving strength of this pin */
+
+ /*To config Not Connected pin GPY4_6 to I/P with no pullup */
+ rv = gpio_request(GPIO_CP_REQ_RESET, "GPY4_6");
+ if (rv < 0) {
+ printk("IDPRAM: [%s] failed to get gpio GPY4_6\n", __func__);
+ goto err5;
+ }
+
+ gpio_direction_input(GPIO_CP_REQ_RESET);
+ s3c_gpio_setpull(GPIO_CP_REQ_RESET, S3C_GPIO_PULL_NONE);
+
+ /* 5)PDA_ACTIVE, QSC_PHONE_ON, QSC_RESET_N */
+ gpio_direction_output(GPIO_PDA_ACTIVE, GPIO_LEVEL_HIGH);
+ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_HIGH);
+ s3c_gpio_setpull(GPIO_QSC_PHONE_ON, S3C_GPIO_PULL_NONE);
+ gpio_direction_output(GPIO_QSC_PHONE_RST, GPIO_LEVEL_LOW);
+
+ return 0;
+
+err5: gpio_free(GPIO_QSC_PHONE_RST);
+err4: gpio_free(GPIO_QSC_PHONE_ON);
+err3: gpio_free(GPIO_PDA_ACTIVE);
+err2: gpio_free(IRQ_QSC_PHONE_ACTIVE);
+err1: gpio_free(IRQ_QSC_INT);
+err: return rv;
+}
+
+static int __devinit dpram_recovery_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ g_TotFrame = 0;
+
+ printk(KERN_ERR "[DPRAM_RECOVERY] %s() ...\n", __func__);
+
+ dpram = kmalloc(sizeof(struct dpram_dev), GFP_KERNEL);
+ if (dpram == NULL) {
+ printk(KERN_ERR "dpram recovery device allocation failed!!\n");
+ err = -ENOMEM;
+ goto out;
+ }
+
+ if (dpram_recovery_ioremap(dpram) < 0) {
+ printk(KERN_ERR "Dpram recovery ioremap failed!\n");
+ err = -EFAULT;
+ goto out_err1;
+ }
+
+ err = register_dpram_rec_device();
+ if (err) {
+ printk(KERN_ERR "Failed to register dpram recovery device.\n");
+ goto out_err2;
+ }
+
+ err = dpram_init_hw();
+ if (err < 0) {
+ printk("dpram_init_hw() failed\n");
+ goto out_err2;
+ }
+
+ err = register_interrupt_handler();
+ if (err < 0) {
+ printk("register_interrupt_handler() failed!!!\n");
+ goto out_err3;
+ }
+
+ printk(KERN_ERR "%s %d\n", __func__, __LINE__);
+
+ return 0;
+
+out_err3:
+ gpio_free(IRQ_QSC_PHONE_ACTIVE);
+
+out_err2:
+ iounmap(dpram);
+
+out_err1:
+ kfree(dpram);
+
+out:
+ return err;
+}
+
+
+static int dpram_recovery_suspend(struct device *pdev)
+{
+ return 0;
+}
+
+static int dpram_recovery_resume(struct device *pdev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops dpram_recovery_pm_ops = {
+ .suspend = dpram_recovery_suspend,
+ .resume = dpram_recovery_resume,
+};
+
+static struct platform_driver dpram_recovery_driver = {
+ .probe = dpram_recovery_probe,
+ .driver = {
+ .name = "dpram-recovery",
+ .pm = &dpram_recovery_pm_ops,
+ },
+};
+
+static int __init dpram_recovery_init(void)
+{
+ return platform_driver_register(&dpram_recovery_driver);
+}
+
+module_init(dpram_recovery_init);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DPRAM Device Driver for recovery");
diff --git a/drivers/dpram/raffaello/dpram_recovery.h b/drivers/dpram/raffaello/dpram_recovery.h
new file mode 100644
index 0000000..38a76ae
--- /dev/null
+++ b/drivers/dpram/raffaello/dpram_recovery.h
@@ -0,0 +1,132 @@
+#ifndef __DPRAM_RECOVERY_H__
+#define __DPRAM_RECOVERY_H__
+
+
+
+/* interupt masks */
+#define MASK_CMD_FOTA_IMG_RECEIVE_READY_RESP 0x0100
+#define MASK_CMD_FOTA_IMG_SEND_RESP 0x0200
+#define MASK_CMD_FOTA_SEND_DONE_RESP 0x0300
+#define MASK_CMD_FOTA_UPDATE_START_RESP 0x0400
+#define MASK_CMD_FOTA_UPDATE_STATUS_IND 0x0500
+#define MASK_CMD_FOTA_UPDATE_END_IND 0x0C00
+
+/* FORMAT */
+#define CMD_FOTA_IMG_RECEIVE_READY_REQ 0x9100
+#define CMD_FOTA_IMG_SEND_REQ 0x9200
+#define CMD_FOTA_SEND_DONE_REQ 0x9300
+#define CMD_FOTA_UPDATE_START_REQ 0x9400
+#define CMD_FOTA_UPDATE_STATUS_IND 0x9500
+#define CMD_FOTA_INIT_START_REQ 0x9A00
+#define CMD_FOTA_INIT_START_RES 0x9B00
+#define CMD_FOTA_UPDATE_END_IND 0x9C00
+
+#define CMD_RETRY 0
+#define CMD_TRUE 1
+#define CMD_FALSE -1
+
+#define CMD_DL_SEND_DONE_REQ 0x9600
+#define CMD_PHONE_BOOT_UPDATE 0x0001
+#define MASK_CMD_SEND_DONE_RESPONSE 0x0700
+#define MASK_CMD_STATUS_UPDATE_NOTIFICATION 0x0800
+#define MASK_CMD_UPDATE_DONE_NOTIFICATION 0x0900
+#define MASK_CMD_IMAGE_SEND_RESPONSE 0x0500
+
+/* Result mask */
+#define MASK_CMD_RESULT_FAIL 0x0002
+#define MASK_CMD_RESULT_SUCCESS 0x0001
+
+#define MASK_CMD_VALID 0x8000
+#define MASK_PDA_CMD 0x1000
+#define MASK_PHONE_CMD 0x2000
+
+#define MAGIC_FODN 0x4E444F46 /* PDA initiate phone code */
+#define MAGIC_FOTA 0x41544C44 /* PDA initiate phone code */
+#define MAGIC_DMDL 0x444D444C
+#define MAGIC_ALARMBOOT 0x00410042
+
+/* DPRAM */
+#define DPRAM_BASE_ADDR S5P_PA_MODEMIF
+#define DPRAM_MAGIC_CODE_SIZE 0x4
+#define DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS (DPRAM_MAGIC_CODE_SIZE)
+#define DPRAM_PHONE2PDA_INTERRUPT_ADDRESS (0x3FFE)
+#define DPRAM_PDA2PHONE_INTERRUPT_ADDRESS (0x3FFC)
+#define DPRAM_BUFFER_SIZE (DPRAM_PDA2PHONE_INTERRUPT_ADDRESS - DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS)
+#define BSP_DPRAM_BASE_SIZE 0x4000 /* 16KB DPRAM in Mirage */
+#define DPRAM_END_OF_ADDRESS (BSP_DPRAM_BASE_SIZE - 1)
+#define DPRAM_INTERRUPT_SIZE 0x2
+#define DPRAM_INDEX_SIZE 0x2
+#define DELTA_PACKET_SIZE (0x4000 - 0x4 - 0x4)
+#define WRITEIMG_HEADER_SIZE 8
+#define WRITEIMG_TAIL_SIZE 4
+#define WRITEIMG_BODY_SIZE (DPRAM_BUFFER_SIZE - WRITEIMG_HEADER_SIZE - WRITEIMG_TAIL_SIZE)
+#define FODN_DEFAULT_WRITE_LEN WRITEIMG_BODY_SIZE
+#define DPRAM_START_ADDRESS 0
+#define DPRAM_END_OF_ADDRESS (BSP_DPRAM_BASE_SIZE - 1)
+#define DPRAM_SIZE BSP_DPRAM_BASE_SIZE
+
+/* ioctl commands */
+#define IOCTL_ST_FW_UPDATE _IO('D', 0x1)
+#define IOCTL_CHK_STAT _IO('D', 0x2)
+#define IOCTL_MOD_PWROFF _IO('D', 0x3)
+#define IOCTL_WRITE_MAGIC_CODE _IO('D', 0x4)
+#define IOCTL_ST_FW_DOWNLOAD _IO('D', 0x5)
+
+#define GPIO_QSC_INT GPIO_C210_DPRAM_INT_N
+#define IRQ_QSC_INT GPIO_QSC_INT
+
+/* Common */
+#define TRUE 1
+#define FALSE 0
+
+#define GPIO_IN 0
+#define GPIO_OUT 1
+#define GPIO_LOW 0
+#define GPIO_HIGH 1
+
+#define START_INDEX 0x007F
+#define END_INDEX 0x007E
+
+#define DPRAM_MODEM_MSG_SIZE 0x100
+
+typedef struct {
+ unsigned int int2ap;
+ unsigned int int2msm;
+ unsigned int mifcon;
+ unsigned int mifpcon;
+ unsigned int msmintclr;
+ unsigned int dma_tx_adr;
+ unsigned int dma_rx_adr;
+} IDPRAM_SFR;
+
+/* It is recommended that S5PC110 write data with half-word access on the interrupt port because
+S5PC100 overwrites tha data in INT2AP if there are INT2AP and INT2MSM sharing the same word */
+#define IDPRAM_INT2MSM_MASK 0xFF
+
+#define IDPRAM_MIFCON_INT2APEN (1<<2)
+#define IDPRAM_MIFCON_INT2MSMEN (1<<3)
+#define IDPRAM_MIFCON_DMATXREQEN_0 (1<<16)
+#define IDPRAM_MIFCON_DMATXREQEN_1 (1<<17)
+#define IDPRAM_MIFCON_DMARXREQEN_0 (1<<18)
+#define IDPRAM_MIFCON_DMARXREQEN_1 (1<<19)
+#define IDPRAM_MIFCON_FIXBIT (1<<20)
+
+#define IDPRAM_MIFPCON_ADM_MODE (1<<6) /* mux / demux mode */
+
+/* end */
+
+struct dpram_firmware {
+ char *firmware;
+ int size;
+ int image_type;
+};
+
+struct stat_info {
+ int pct;
+ char msg[DPRAM_MODEM_MSG_SIZE];
+};
+
+#define DPRAM_MODEM_DELTA_IMAGE 0
+#define DPRAM_MODEM_FULL_IMAGE 1
+
+#endif /* __DPRAM_RECOVERY_H__ */