diff options
Diffstat (limited to 'drivers/misc/modem_if_u1/modem_link_device_spi.c')
-rw-r--r-- | drivers/misc/modem_if_u1/modem_link_device_spi.c | 1787 |
1 files changed, 0 insertions, 1787 deletions
diff --git a/drivers/misc/modem_if_u1/modem_link_device_spi.c b/drivers/misc/modem_if_u1/modem_link_device_spi.c deleted file mode 100644 index 6faa24a..0000000 --- a/drivers/misc/modem_if_u1/modem_link_device_spi.c +++ /dev/null @@ -1,1787 +0,0 @@ -/* - * Copyright (C) 2011 Google, Inc. - * Copyright (C) 2010 Samsung Electronics. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/time.h> -#include <linux/interrupt.h> -#include <linux/timer.h> -#include <linux/wakelock.h> -#include <linux/delay.h> -#include <linux/wait.h> -#include <linux/sched.h> -#include <linux/vmalloc.h> -#include <linux/if_arp.h> -#include <linux/platform_device.h> -#include <linux/spi/spi.h> -#include <linux/suspend.h> -#include <linux/kthread.h> - -#include <linux/platform_data/modem.h> -#include "modem_prj.h" -#include "modem_link_device_spi.h" -#include "modem_utils.h" - -/* For function which has void parmeter */ -static struct spi_link_device *p_spild; -static struct spi_device *p_spi; - -static void spi_send_work(int spi_sigs, bool spi_work_t) -{ - struct spi_work_type *spi_wq; - - spi_wq = kmalloc(sizeof(struct spi_work_type), GFP_ATOMIC); - if (unlikely(!spi_wq)) { - pr_err("[LNK/E] <%s> Failed to kmalloc()\n", __func__); - return; - } - - spi_wq->signal_code = spi_sigs; - INIT_WORK(&spi_wq->work, spi_work); - - if (spi_work_t == SPI_WORK_FRONT) - queue_work_front(p_spild->spi_wq, (struct work_struct *)spi_wq); - else - queue_work(p_spild->spi_wq, (struct work_struct *)spi_wq); -} - -static irqreturn_t spi_srdy_irq_handler(int irq, void *p_ld) -{ - struct link_device *ld = (struct link_device *)p_ld; - struct spi_link_device *spild = to_spi_link_device(ld); - - irqreturn_t result = IRQ_HANDLED; - - if (!spild->boot_done) - return result; - - if (!wake_lock_active(&spild->spi_wake_lock) - && spild->send_modem_spi != 1) { - wake_lock(&spild->spi_wake_lock); - pr_debug("[SPI] [%s](%d) spi_wakelock locked . spild->spi_state[%d]\n", - __func__, __LINE__, (int)spild->spi_state); - } - - if (spild->send_modem_spi == 1) - up(&spild->srdy_sem); - - /* SRDY interrupt work on SPI_STATE_IDLE state for receive data */ - if (spild->spi_state == SPI_STATE_IDLE - || spild->spi_state == SPI_STATE_RX_TERMINATE - || spild->spi_state == SPI_STATE_TX_TERMINATE) - spi_send_work(SPI_WORK_RECEIVE, SPI_WORK_FRONT); - - return result; -} - -static irqreturn_t spi_subsrdy_irq_handler(int irq, void *p_ld) -{ - struct link_device *ld = (struct link_device *)p_ld; - struct spi_link_device *spild = to_spi_link_device(ld); - - irqreturn_t result = IRQ_HANDLED; - - /* SRDY interrupt work on SPI_STATE_TX_WAIT state for send data */ - if (spild->spi_state == SPI_STATE_TX_WAIT) - return result; - - pr_debug("%s spild->spi_state[%d]\n", - "[SPI] spi_main_subsrdy_rising_handler :", - (int)spild->spi_state); - - - return result; -} - -static int spi_send -( - struct link_device *ld, - struct io_device *iod, - struct sk_buff *skb -) -{ - struct sk_buff_head *txq; - enum dev_format fmt = iod->format; - - const u32 cmd_ready = 0x12341234; - const u32 cmd_start = 0x45674567; - int ret; - u32 data; - - switch (fmt) { - case IPC_FMT: - case IPC_RAW: - case IPC_RFS: - txq = ld->skb_txq[fmt]; - skb_queue_tail(txq, skb); - - ret = skb->len; - - break; - - case IPC_BOOT: - if (get_user(data, (u32 __user *)skb->data)) - return -EFAULT; - - if (data == cmd_ready) { - p_spild->ril_send_modem_img = 1; - p_spild->ril_send_cnt = 0; - } else if (data == cmd_start) { - p_spild->ril_send_modem_img = 0; - if (!queue_work(p_spild->ipc_spi_wq, - &p_spild->send_modem_w)) - pr_err("(%d) already exist w-q\n", - __LINE__); - } else { - if (p_spild->ril_send_modem_img) { - memcpy((void *)(p_spild->p_virtual_buff - + p_spild->ril_send_cnt), - skb->data, skb->len); - p_spild->ril_send_cnt += skb->len; - } - } - ret = skb->len; - dev_kfree_skb_any(skb); - - return ret; - - default: - pr_err("[LNK/E] <%s:%s> No TXQ for %s\n", - __func__, ld->name, iod->name); - dev_kfree_skb_any(skb); - return 0; - } - - spi_send_work(SPI_WORK_SEND, SPI_WORK); - - return ret; -} - - -static int spi_register_isr -( - unsigned irq, - irqreturn_t (*isr)(int, void*), - unsigned long flag, - const char *name, - struct link_device *ld -) -{ - int ret = 0; - - ret = request_irq(irq, isr, flag, name, ld); - if (ret) { - pr_err("[LNK/E] <%s> request_irq fail (%d)\n", - __func__, ret); - goto err; - } - - ret = enable_irq_wake(irq); - if (ret) { - pr_err("[LNK/E] <%s> enable_irq_wake fail (%d)\n", - __func__, ret); - free_irq(irq, ld); - goto err; - } - - pr_debug("[LNK] <%s> IRQ#%d handler is registered.\n", __func__, irq); - -err: - return ret; -} - -void spi_unregister_isr(unsigned irq, void *data) -{ - free_irq(irq, data); -} - -int spi_tx_rx_sync(u8 *tx_d, u8 *rx_d, unsigned len) -{ - struct spi_transfer t; - struct spi_message msg; - - memset(&t, 0, sizeof t); - - t.len = len; - - t.tx_buf = tx_d; - t.rx_buf = rx_d; - - t.cs_change = 0; - - t.bits_per_word = 32; - t.speed_hz = 12000000; - - spi_message_init(&msg); - spi_message_add_tail(&t, &msg); - - return spi_sync(p_spi, &msg); -} - -static int spi_buff_write -( - struct spi_link_device *spild, - int dev_id, - const char *buff, - unsigned size -) -{ - u32 templength, buf_length; - u32 spi_data_mux; - u32 spi_packet_free_length; - - u8 *spi_packet; - struct spi_data_packet_header *spi_packet_header; - - spi_packet_header = (struct spi_data_packet_header *)spild->buff; - spi_packet = (char *)spild->buff; - - spi_packet_free_length = SPI_DATA_PACKET_MAX_PACKET_BODY_SIZE - - spi_packet_header->current_data_size; - - buf_length = size + SPI_DATA_MUX_SIZE + SPI_DATA_LENGTH_SIZE; - - /* not enough space in spi packet */ - if (spi_packet_free_length < buf_length) { - spi_packet_header->more = 1; - return 0; - } - - /* check spi mux type */ - switch (dev_id) { - case IPC_FMT: - spi_data_mux = SPI_DATA_MUX_IPC; - break; - - case IPC_RAW: - spi_data_mux = SPI_DATA_MUX_RAW; - break; - - case IPC_RFS: - spi_data_mux = SPI_DATA_MUX_RFS; - break; - - default: - pr_err("%s %s\n", - "[SPI] ERROR : spi_buff_write:", - "invalid dev_id"); - return 0; - } - - /* copy spi mux field */ - memcpy(spi_packet + SPI_DATA_PACKET_HEADER_SIZE + - spi_packet_header->current_data_size, - &spi_data_mux, SPI_DATA_MUX_SIZE); - spi_packet_header->current_data_size += SPI_DATA_MUX_SIZE; - - /* copy spi data length field */ - templength = size-SPI_DATA_BOF_SIZE-SPI_DATA_EOF_SIZE; - memcpy(spi_packet + SPI_DATA_PACKET_HEADER_SIZE + - spi_packet_header->current_data_size, - &templength, SPI_DATA_LENGTH_SIZE); - spi_packet_header->current_data_size += SPI_DATA_LENGTH_SIZE; - - /* copy data field */ - memcpy(spi_packet + SPI_DATA_PACKET_HEADER_SIZE + - spi_packet_header->current_data_size, - buff, size); - spi_packet_header->current_data_size += size; - - return buf_length; -} - - -static void spi_prepare_tx_packet(void) -{ - struct link_device *ld; - struct sk_buff *skb; - int ret; - int i; - - ld = &p_spild->ld; - - for (i = 0; i < p_spild->max_ipc_dev; i++) { - while ((skb = skb_dequeue(ld->skb_txq[i]))) { - ret = spi_buff_write(p_spild, i, skb->data, skb->len); - if (!ret) { - skb_queue_head(ld->skb_txq[i], skb); - break; - } - dev_kfree_skb_any(skb); - } - } -} - - -static void spi_start_data_send(void) -{ - struct link_device *ld; - int i; - - ld = &p_spild->ld; - - for (i = 0; i < p_spild->max_ipc_dev; i++) { - if (skb_queue_len(ld->skb_txq[i]) > 0) - spi_send_work(SPI_WORK_SEND, SPI_WORK); - } -} - -static void spi_tx_work(void) -{ - struct spi_link_device *spild; - struct io_device *iod; - char *spi_packet_buf; - char *spi_sync_buf; - - spild = p_spild; - iod = link_get_iod_with_format(&spild->ld, IPC_FMT); - if (!iod) { - mif_err("no iodevice for modem control\n"); - return; - } - - if (iod->mc->phone_state == STATE_CRASH_EXIT) - return; - - /* check SUB SRDY, SRDY state */ - if (gpio_get_value(spild->gpio_ipc_sub_srdy) == - SPI_GPIOLEVEL_HIGH || - gpio_get_value(spild->gpio_ipc_srdy) == - SPI_GPIOLEVEL_HIGH) { - spi_start_data_send(); - return; - } - - if (get_console_suspended()) - return; - - if (spild->spi_state == SPI_STATE_END) - return; - - /* change state SPI_STATE_IDLE to SPI_STATE_TX_WAIT */ - spild->spi_state = SPI_STATE_TX_WAIT; - spild->spi_timer_tx_state = SPI_STATE_TIME_START; - - gpio_set_value(spild->gpio_ipc_mrdy, SPI_GPIOLEVEL_HIGH); - - /* Start TX timer */ - spild->spi_tx_timer.expires = - jiffies + ((SPI_TIMER_TX_WAIT_TIME * HZ) / 1000); - add_timer(&spild->spi_tx_timer); - /* check SUBSRDY state */ - while (gpio_get_value(spild->gpio_ipc_sub_srdy) == - SPI_GPIOLEVEL_LOW) { - if (spild->spi_timer_tx_state == SPI_STATE_TIME_OVER) { - pr_err("%s spild->spi_state=[%d]\n", - "[spi_tx_work] == spi Fail to receiving SUBSRDY CONF :" - , (int)spild->spi_state); - - spild->spi_timer_tx_state = SPI_STATE_TIME_START; - - gpio_set_value(spild->gpio_ipc_mrdy, - SPI_GPIOLEVEL_LOW); - - /* change state SPI_STATE_TX_WAIT */ - /* to SPI_STATE_IDLE */ - spild->spi_state = SPI_STATE_IDLE; - spi_send_work(SPI_WORK_SEND, SPI_WORK); - - return; - } - } - /* Stop TX timer */ - del_timer(&spild->spi_tx_timer); - - if (spild->spi_state != SPI_STATE_START - && spild->spi_state != SPI_STATE_END - && spild->spi_state != SPI_STATE_INIT) { - spi_packet_buf = spild->buff; - spi_sync_buf = spild->sync_buff; - - gpio_set_value(spild->gpio_ipc_sub_mrdy, SPI_GPIOLEVEL_HIGH); - gpio_set_value(spild->gpio_ipc_mrdy, SPI_GPIOLEVEL_LOW); - - /* change state SPI_STATE_TX_WAIT to - SPI_MAIN_STATE_TX_SENDING */ - spild->spi_state = SPI_STATE_TX_SENDING; - - memset(spi_packet_buf, 0, SPI_MAX_PACKET_SIZE); - memset(spi_sync_buf, 0, SPI_MAX_PACKET_SIZE); - - spi_prepare_tx_packet(); - - if (spi_tx_rx_sync((void *)spi_packet_buf, (void *)spi_sync_buf, - SPI_MAX_PACKET_SIZE)) { - /* TODO: save failed packet */ - /* back data to each queue */ - pr_err("[SPI] spi_dev_send fail\n"); - - /* add cp reset when spi sync fail */ - if (iod) - iod->modem_state_changed(iod, - STATE_CRASH_RESET); - } - - spild->spi_state = SPI_STATE_TX_TERMINATE; - - gpio_set_value(spild->gpio_ipc_sub_mrdy, SPI_GPIOLEVEL_LOW); - - /* change state SPI_MAIN_STATE_TX_SENDING to SPI_STATE_IDLE */ - spild->spi_state = SPI_STATE_IDLE; - spi_start_data_send(); - } else - pr_err("[SPI] ERR : _start_packet_tx:spild->spi_state[%d]", - (int)spild->spi_state); - - return; -} - -int spi_buff_read(struct spi_link_device *spild) -{ - struct link_device *ld; - struct spi_data_packet_header *spi_packet_header; - struct sk_buff *skb; - char *spi_packet; - int dev_id; - unsigned int spi_packet_length; - unsigned int spi_packet_cur_pos = SPI_DATA_PACKET_HEADER_SIZE; - - unsigned int spi_data_mux; - unsigned int spi_data_length; - unsigned int data_length; - u8 *spi_cur_data; - u8 *dst; - - spi_packet = spild->buff; - ld = &spild->ld; - - /* check spi packet header */ - if (*(unsigned int *)spi_packet == 0x00000000 - || *(unsigned int *)spi_packet == 0xFFFFFFFF) { - /* if spi header is invalid, */ - /* read spi header again with next 4 byte */ - spi_packet += SPI_DATA_PACKET_HEADER_SIZE; - } - - /* read spi packet header */ - spi_packet_header = (struct spi_data_packet_header *)spi_packet; - spi_packet_length = SPI_DATA_PACKET_HEADER_SIZE + - spi_packet_header->current_data_size; - - - do { - /* read spi data mux and set current queue */ - memcpy(&spi_data_mux, - spi_packet + spi_packet_cur_pos, SPI_DATA_MUX_SIZE); - - switch (spi_data_mux & SPI_DATA_MUX_NORMAL_MASK) { - case SPI_DATA_MUX_IPC: - dev_id = IPC_FMT; - break; - - case SPI_DATA_MUX_RAW: - dev_id = IPC_RAW; - break; - - case SPI_DATA_MUX_RFS: - dev_id = IPC_RFS; - break; - - default: - pr_err("%s len[%u], pos[%u]\n", - "[SPI] ERROR : spi_buff_read : MUX error", - spi_packet_length, spi_packet_cur_pos); - - return spi_packet_cur_pos - - SPI_DATA_PACKET_HEADER_SIZE; - } - - /* read spi data length */ - memcpy(&spi_data_length, spi_packet + - spi_packet_cur_pos + SPI_DATA_LENGTH_OFFSET, - SPI_DATA_LENGTH_SIZE); - - data_length = spi_data_length + SPI_DATA_BOF_SIZE + - SPI_DATA_EOF_SIZE; - - spi_data_length += SPI_DATA_HEADER_SIZE; - - /* read data and make spi data */ - spi_cur_data = spi_packet + spi_packet_cur_pos; - - /* enqueue spi data */ - skb = alloc_skb(data_length, GFP_ATOMIC); - if (unlikely(!skb)) { - pr_err("%s %s\n", - "[SPI] ERROR : spi_buff_read:", - "Can't allocate memory for SPI"); - return -ENOMEM; - } - - dst = skb_put(skb, data_length); - - memcpy(dst, spi_packet + - spi_packet_cur_pos + SPI_DATA_BOF_OFFSET, - data_length); - - skb_queue_tail(&spild->skb_rxq[dev_id], skb); - - /* move spi packet current posision */ - spi_packet_cur_pos += spi_data_length; - } while ((spi_packet_length - 1) > spi_packet_cur_pos); - - return 1; -} - -static void spi_rx_work(void) -{ - struct link_device *ld; - struct spi_link_device *spild; - struct sk_buff *skb; - struct io_device *iod; - char *spi_packet_buf; - char *spi_sync_buf; - int i; - - spild = p_spild; - ld = &spild->ld; - if (!spild) - pr_err("[LNK/E] <%s> dpld == NULL\n", __func__); - - iod = link_get_iod_with_format(&spild->ld, IPC_FMT); - if (!iod) { - mif_err("no iodevice for modem control\n"); - return; - } - - if (iod->mc->phone_state == STATE_CRASH_EXIT) - return; - - if (!wake_lock_active(&spild->spi_wake_lock) || - gpio_get_value(spild->gpio_ipc_srdy) == SPI_GPIOLEVEL_LOW || - get_console_suspended() || - spild->spi_state == SPI_STATE_END) - return; - - spild->spi_state = SPI_STATE_RX_WAIT; - spild->spi_timer_rx_state = SPI_STATE_TIME_START; - - gpio_set_value(spild->gpio_ipc_sub_mrdy, SPI_GPIOLEVEL_HIGH); - /* Start TX timer */ - spild->spi_rx_timer.expires = - jiffies + ((SPI_TIMER_RX_WAIT_TIME * HZ) / 1000); - add_timer(&spild->spi_rx_timer); - - /* check SUBSRDY state */ - while (gpio_get_value(spild->gpio_ipc_sub_srdy) == - SPI_GPIOLEVEL_LOW) { - if (spild->spi_timer_rx_state == SPI_STATE_TIME_OVER) { - pr_err("[SPI] ERROR(Failed MASTER RX:%d ms)", - SPI_TIMER_RX_WAIT_TIME); - - spild->spi_timer_rx_state = SPI_STATE_TIME_START; - - gpio_set_value(spild->gpio_ipc_sub_mrdy, - SPI_GPIOLEVEL_LOW); - - /* change state SPI_MAIN_STATE_RX_WAIT */ - /* to SPI_STATE_IDLE */ - spild->spi_state = SPI_STATE_IDLE; - - return; - } - } - /* Stop TX timer */ - del_timer(&spild->spi_rx_timer); - - if (spild->spi_state == SPI_STATE_START - || spild->spi_state == SPI_STATE_END - || spild->spi_state == SPI_STATE_INIT) - return; - - spi_packet_buf = spild->buff; - spi_sync_buf = spild->sync_buff; - - memset(spi_packet_buf, 0, SPI_MAX_PACKET_SIZE); - memset(spi_sync_buf, 0, SPI_MAX_PACKET_SIZE); - - if (spi_tx_rx_sync((void *)spi_sync_buf, (void *)spi_packet_buf, - SPI_MAX_PACKET_SIZE) == 0) { - /* parsing SPI packet */ - if (spi_buff_read(spild) > 0) { - /* call function for send data to IPC, RAW, RFS */ - for (i = 0; i < spild->max_ipc_dev; i++) { - iod = spild->iod[i]; - while ((skb = skb_dequeue(&spild->skb_rxq[i])) - != NULL) { - if (iod->recv(iod, ld, skb->data, - skb->len) < 0) - pr_err("[LNK/E] <%s:%s> recv fail\n", - __func__, ld->name); - dev_kfree_skb_any(skb); - } - } - } - } else { - pr_err("%s %s\n", "[SPI] ERROR : spi_rx_work :", - "spi sync failed"); - - /* add cp reset when spi sync fail */ - if (iod) - iod->modem_state_changed(iod, - STATE_CRASH_RESET); - } - - spild->spi_state = SPI_STATE_RX_TERMINATE; - - gpio_set_value(spild->gpio_ipc_sub_mrdy, SPI_GPIOLEVEL_LOW); - - /* change state SPI_MAIN_STATE_RX_WAIT to SPI_STATE_IDLE */ - spild->spi_state = SPI_STATE_IDLE; - spi_start_data_send(); -} - - -static int spi_init_ipc(struct spi_link_device *spild) -{ - struct link_device *ld = &spild->ld; - - int i; - - /* Make aliases to each IO device */ - for (i = 0; i < MAX_DEV_FORMAT; i++) - spild->iod[i] = link_get_iod_with_format(ld, i); - - spild->iod[IPC_RAW] = spild->iod[IPC_MULTI_RAW]; - - /* List up the IO devices connected to each IPC channel */ - for (i = 0; i < MAX_DEV_FORMAT; i++) { - if (spild->iod[i]) - pr_err("[LNK] <%s:%s> spild->iod[%d]->name = %s\n", - __func__, ld->name, i, spild->iod[i]->name); - else - pr_err("[LNK] <%s:%s> No spild->iod[%d]\n", - __func__, ld->name, i); - } - - ld->mode = LINK_MODE_IPC; - - return 0; -} - -unsigned int sprd_crc_calc(char *buf_ptr, unsigned int len) -{ - unsigned int i; - unsigned short crc = 0; - - while (len-- != 0) { - for (i = 0x80; i != 0 ; i = i>>1) { - if ((crc & 0x8000) != 0) { - crc = crc << 1 ; - crc = crc ^ 0x1021; - } else { - crc = crc << 1 ; - } - - if ((*buf_ptr & i) != 0) - crc = crc ^ 0x1021; - } - buf_ptr++; - } - - return crc; - -} - -unsigned short sprd_crc_calc_fdl(unsigned short *src, int len) -{ - unsigned int sum = 0; - unsigned short SourceValue, DestValue = 0; - unsigned short lowSourceValue, hiSourceValue = 0; - - /* Get sum value of the source.*/ - while (len > 1) { - SourceValue = *src++; - DestValue = 0; - lowSourceValue = (SourceValue & 0xFF00) >> 8; - hiSourceValue = (SourceValue & 0x00FF) << 8; - DestValue = lowSourceValue | hiSourceValue; - - sum += DestValue; - len -= 2; - } - - if (len == 1) - sum += *((unsigned char *) src); - - sum = (sum >> 16) + (sum & 0x0FFFF); - sum += (sum >> 16); - - return ~sum; -} - -int encode_msg(struct sprd_image_buf *img, int bcrc) -{ - u16 crc; /* CRC value*/ - u8 *src_ptr; /* source buffer pointer*/ - int dest_len; /* output buffer length*/ - u8 *dest_ptr; /* dest buffer pointer*/ - u8 high_crc, low_crc = 0; - register int curr; - - /* CRC Check. */ - src_ptr = img->tx_b; - - /* CRC Check. */ - if (bcrc) - crc = sprd_crc_calc(src_ptr, img->tx_size); - else - crc = sprd_crc_calc_fdl - ((unsigned short *)src_ptr, img->tx_size); - - high_crc = (crc>>8) & 0xFF; - low_crc = crc & 0xFF; - - /* Get the total size to be allocated.*/ - dest_len = 0; - - for (curr = 0; curr < img->tx_size; curr++) { - switch (*(src_ptr+curr)) { - case HDLC_FLAG: - case HDLC_ESCAPE: - dest_len += 2; - break; - default: - dest_len++; - break; - } - } - - switch (low_crc) { - case HDLC_FLAG: - case HDLC_ESCAPE: - dest_len += 2; - break; - default: - dest_len++; - } - - switch (high_crc) { - case HDLC_FLAG: - case HDLC_ESCAPE: - dest_len += 2; - break; - default: - dest_len++; - } - - dest_ptr = kmalloc(dest_len + 2, GFP_ATOMIC); - /* Memory Allocate fail.*/ - if (dest_ptr == NULL) - return -ENOMEM; - - *dest_ptr = HDLC_FLAG; - dest_len = 1; - - /* do escape*/ - for (curr = 0; curr < img->tx_size; curr++) { - switch (*(src_ptr+curr)) { - case HDLC_FLAG: - case HDLC_ESCAPE: - *(dest_ptr + dest_len++) = HDLC_ESCAPE; - *(dest_ptr + dest_len++) = - *(src_ptr + curr) ^ HDLC_ESCAPE_MASK; - break; - default: - *(dest_ptr + dest_len++) = *(src_ptr + curr); - break; - } - } - - switch (high_crc) { - case HDLC_FLAG: - case HDLC_ESCAPE: - *(dest_ptr + dest_len++) = HDLC_ESCAPE; - *(dest_ptr + dest_len++) = high_crc ^ HDLC_ESCAPE_MASK; - break; - default: - *(dest_ptr + dest_len++) = high_crc; - } - - switch (low_crc) { - case HDLC_FLAG: - case HDLC_ESCAPE: - *(dest_ptr + dest_len++) = HDLC_ESCAPE; - *(dest_ptr + dest_len++) = low_crc ^ HDLC_ESCAPE_MASK; - break; - default: - *(dest_ptr + dest_len++) = low_crc; - } - - - *(dest_ptr + dest_len++) = HDLC_FLAG; - - memcpy(img->encoded_tx_b, dest_ptr, dest_len); - img->encoded_tx_size = dest_len; - - kfree(dest_ptr); - return 0; -} - -int decode_msg(struct sprd_image_buf *img, int bcrc) -{ - u16 crc; /* CRC value*/ - u8 *src_ptr; /* source buffer pointer*/ - int dest_len; /* output buffer length*/ - u8 *dest_ptr; /* dest buffer pointer*/ - register int curr; - - /* Check if exist End Flag.*/ - src_ptr = img->rx_b; - - dest_len = 0; - - if (img->rx_size < 4) - return -EINVAL; - - /* Get the total size to be allocated for decoded message.*/ - for (curr = 1; curr < img->rx_size - 1; curr++) { - switch (*(src_ptr + curr)) { - case HDLC_ESCAPE: - curr++; - dest_len++; - break; - default: - dest_len++; - break; - } - } - - /* Allocate meomory for decoded message*/ - dest_ptr = kmalloc(dest_len, GFP_ATOMIC); - /* Memory allocate fail.*/ - if (dest_ptr == NULL) - return -ENOMEM; - - memset(dest_ptr, 0, dest_len); - - curr = 0; - dest_len = 0; - /* Do de-escape.*/ - for (curr = 1; curr < img->rx_size - 1; curr++) { - switch (*(src_ptr + curr)) { - case HDLC_ESCAPE: - curr++; - *(dest_ptr + dest_len) = - *(src_ptr + curr) ^ HDLC_ESCAPE_MASK; - break; - default: - *(dest_ptr + dest_len) = *(src_ptr + curr); - break; - } - - dest_len = dest_len + 1; - } - - /* CRC Check. */ - if (bcrc) - crc = sprd_crc_calc(dest_ptr, dest_len); - else - crc = sprd_crc_calc_fdl((unsigned short *)dest_ptr, dest_len); - - if (crc != CRC_16_L_OK) { - pr_err("CRC error : 0x%X", crc); - kfree(dest_ptr); - return -EPERM; - } - - memcpy(img->decoded_rx_b, dest_ptr, dest_len - CRC_CHECK_SIZE); - img->decoded_rx_size = dest_len - CRC_CHECK_SIZE ; - - kfree(dest_ptr); - return 0; -} - -static int spi_send_modem_bin_execute_cmd - (u8 *spi_ptr, u32 spi_size, u16 spi_type, - u16 spi_crc, struct sprd_image_buf *sprd_img) -{ - int i, retval; - u16 send_packet_size; - u8 *send_packet_data; - u16 d1_crc; - u16 d2_crc = spi_crc; - u16 type = spi_type; - - /* D1 */ - send_packet_size = spi_size; /* u32 -> u16 */ - sprd_img->tx_size = 6; - M_16_SWAP(d2_crc); - memcpy(sprd_img->tx_b, &send_packet_size, sizeof(send_packet_size)); - memcpy((sprd_img->tx_b+2), &type, sizeof(type)); - memcpy((sprd_img->tx_b+4), &d2_crc, sizeof(d2_crc)); - - d1_crc = sprd_crc_calc_fdl - ((unsigned short *)sprd_img->tx_b, sprd_img->tx_size); - M_16_SWAP(d1_crc); - memcpy((sprd_img->tx_b+6), &d1_crc, sizeof(d1_crc)); - sprd_img->tx_size += 2; - - if (down_timeout(&p_spild->srdy_sem, 2 * HZ)) { - pr_err("(%d) SRDY TimeOUT!!! SRDY : %d, SEM : %d\n", - __LINE__, - gpio_get_value(p_spild->gpio_modem_bin_srdy), - p_spild->srdy_sem.count); - goto err; - } - - retval = spi_tx_rx_sync - (sprd_img->tx_b, sprd_img->rx_b, sprd_img->tx_size); - if (retval != 0) { - pr_err("(%d) spi sync error : %d\n", - __LINE__, retval); - goto err; - } - - if ((type == 0x0003) || (type == 0x0004)) { - pr_err("D2 Skip!!\n"); - goto ACK; - } - - /* D2 */ - send_packet_data = spi_ptr; - - if (down_timeout(&p_spild->srdy_sem, 2 * HZ)) { - pr_err("(%d) SRDY TimeOUT!!! SRDY : %d, SEM : %d\n", __LINE__, - gpio_get_value(p_spild->gpio_modem_bin_srdy), - p_spild->srdy_sem.count); - goto err; - } - - retval = spi_tx_rx_sync - (send_packet_data, sprd_img->rx_b, send_packet_size); - if (retval != 0) { - pr_err("(%d) spi sync error : %d\n", __LINE__, retval); - goto err; - } - -ACK: - - if (p_spild->is_cp_reset) { - while (!gpio_get_value(p_spild->gpio_modem_bin_srdy)) - ; - } else { - if (down_timeout(&p_spild->srdy_sem, 2 * HZ)) { - pr_err("(%d) SRDY TimeOUT!!! SRDY : %d, SEM : %d\n", - __LINE__, - gpio_get_value(p_spild->gpio_modem_bin_srdy), - p_spild->srdy_sem.count); - - pr_err("[SPI DUMP] TX_D1(%d) : [%02x %02x %02x %02x %02x %02x %02x %02x]\n", - sprd_img->tx_size, sprd_img->tx_b[0], - sprd_img->tx_b[1], sprd_img->tx_b[2], - sprd_img->tx_b[3], sprd_img->tx_b[4], - sprd_img->tx_b[5], sprd_img->tx_b[6], - sprd_img->tx_b[7]); - pr_err("[SPI DUMP] TX_D2(%d) :[%02x %02x %02x %02x %02x %02x %02x %02x]\n", - send_packet_size, spi_ptr[0], spi_ptr[1], - spi_ptr[2], spi_ptr[3], spi_ptr[4], - spi_ptr[5], spi_ptr[6], spi_ptr[7]); - - /* WA (CP Reset) jongmoon.suh */ - if (gpio_get_value(p_spild->gpio_modem_bin_srdy)) - ; - else - goto err; - - } - } - - memset(sprd_img->tx_b, 0, SPRD_BLOCK_SIZE+10); - retval = spi_tx_rx_sync(sprd_img->tx_b, sprd_img->rx_b, 8); - if (retval != 0) { - pr_err("(%d) spi sync error : %d\n", - __LINE__, retval); - goto err; - } - - memcpy(sprd_img->decoded_rx_b, sprd_img->rx_b, 4); - - if ((*(sprd_img->decoded_rx_b+0) == 0x00) && \ - (*(sprd_img->decoded_rx_b+1) == 0x80) && \ - (*(sprd_img->decoded_rx_b+2) == 0x00) && \ - (*(sprd_img->decoded_rx_b+3) == 0x00)) { - pr_debug("[SPRD] CP sent ACK"); - } else { - pr_err("Transfer ACK error! srdy_sem = %d\n", - p_spild->srdy_sem.count); - pr_err("[SPI DUMP] RX(%d) : [ ", sprd_img->rx_size); - for (i = 0; i < 15; i++) - pr_err("%02x ", *((u8 *)(sprd_img->rx_b + i))); - pr_err("]"); - - goto err; - } - - return retval; - -err: - return -EINVAL; -} - -static int spi_send_modem_bin_xmit_img - (enum image_type type, struct image_buf *img) -{ - int retval = 0; - struct sprd_image_buf sprd_img; - unsigned int data_size; - unsigned int send_size = 0; - unsigned int rest_size = 0; - unsigned int spi_size = 0; - unsigned int address = 0; - unsigned int fdl1_size = 0; - /* No Translate */ - u16 crc = 0; - u16 spi_type = 0; - - unsigned char *spi_ptr; - unsigned char *ptr; - int i, j = 0; - - u16 sprd_packet_size = SPRD_BLOCK_SIZE; - - sprd_img.tx_b = kmalloc(SPRD_BLOCK_SIZE*2, GFP_ATOMIC); - if (!sprd_img.tx_b) { - pr_err("(%d) tx_b kmalloc fail.", - __LINE__); - return -ENOMEM; - } - memset(sprd_img.tx_b, 0, SPRD_BLOCK_SIZE*2); - - sprd_img.rx_b = kmalloc(SPRD_BLOCK_SIZE*2, GFP_ATOMIC); - if (!sprd_img.rx_b) { - pr_err("(%d) rx_b kmalloc fail.", - __LINE__); - retval = -ENOMEM; - goto err3; - } - memset(sprd_img.rx_b, 0, SPRD_BLOCK_SIZE*2); - - sprd_img.encoded_tx_b = kmalloc(SPRD_BLOCK_SIZE*2, GFP_ATOMIC); - if (!sprd_img.encoded_tx_b) { - pr_err("(%d) encoded_tx_b kmalloc fail.", - __LINE__); - retval = -ENOMEM; - goto err2; - } - memset(sprd_img.encoded_tx_b, 0, SPRD_BLOCK_SIZE*2); - - sprd_img.decoded_rx_b = kmalloc(SPRD_BLOCK_SIZE*2, GFP_ATOMIC); - if (!sprd_img.decoded_rx_b) { - pr_err("(%d) encoded_rx_b kmalloc fail.", - __LINE__); - retval = -ENOMEM; - goto err1; - } - memset(sprd_img.decoded_rx_b, 0, SPRD_BLOCK_SIZE*2); - - pr_debug("(%d) spi_send_modem_bin_xmit_img type : %d.\n", - __LINE__, type); - memcpy(&fdl1_size, (void *)(p_spild->p_virtual_buff + 4), 4); - - switch (type) { - case MODEM_MAIN: - memcpy(&img->address, - (void *)(p_spild->p_virtual_buff + 8), 4); - memcpy(&img->length, - (void *)(p_spild->p_virtual_buff + 12), 4); - img->buf = (unsigned char *) - (p_spild->p_virtual_buff + 0x30 + fdl1_size); - img->offset = img->length + fdl1_size + 0x30; - pr_debug("(%d) spi_send_modem_bin_xmit_img save MAIN to img.\n", - __LINE__); - - break; - - case MODEM_DSP: - memcpy(&img->address, - (void *)(p_spild->p_virtual_buff + 16), 4); - memcpy(&img->length, - (void *)(p_spild->p_virtual_buff + 20), 4); - img->buf = (unsigned char *) - (p_spild->p_virtual_buff + img->offset); - img->offset += img->length; - pr_debug("(%d) spi_send_modem_bin_xmit_img save DSP to img.\n", - __LINE__); - - break; - - case MODEM_NV: - memcpy(&img->address, - (void *)(p_spild->p_virtual_buff + 24), 4); - memcpy(&img->length, - (void *)(p_spild->p_virtual_buff + 28), 4); - img->buf = (unsigned char *) - (p_spild->p_virtual_buff + img->offset); - img->offset += img->length; - pr_debug("(%d) spi_send_modem_bin_xmit_img save NV to img.\n", - __LINE__); - - break; - - case MODEM_EFS: - memcpy(&img->address, - (void *)(p_spild->p_virtual_buff + 32), 4); - memcpy(&img->length, - (void *)(p_spild->p_virtual_buff + 36), 4); - img->buf = (unsigned char *) - (p_spild->p_virtual_buff + img->offset); - img->offset += img->length; - pr_debug("(%d) spi_send_modem_bin_xmit_img save EFS to img.\n", - __LINE__); - - break; - case MODEM_RUN: - memset(sprd_img.encoded_tx_b, 0, SPRD_BLOCK_SIZE*2); - sprd_img.encoded_tx_size = 0; - spi_type = 0x0004; - crc = 0; - - spi_ptr = sprd_img.encoded_tx_b; - spi_size = sprd_img.encoded_tx_size; - - retval = spi_send_modem_bin_execute_cmd - (spi_ptr, spi_size, spi_type, crc, &sprd_img); - if (retval < 0) { - pr_err("(%d) spi_send_modem_bin_execute_cmd fail : %d", - __LINE__, retval); - goto err0; - } - return retval; - - default: - pr_err("(%d) spi_send_modem_bin_xmit_img wrong : %d.", - __LINE__, type); - goto err0; - } - - pr_debug("(%d) Start send img. size : %d\n", - __LINE__, img->length); - - ptr = img->buf; - data_size = sprd_packet_size; - rest_size = img->length; - address = img->address; - - M_32_SWAP(img->address); - M_32_SWAP(img->length); - - /* Send Transfer Start */ - sprd_img.tx_size = 8; - memcpy((sprd_img.tx_b+0), &img->address, sizeof(img->address)); - memcpy((sprd_img.tx_b+4), &img->length, sizeof(img->length)); - - spi_type = 0x0001; - crc = sprd_crc_calc_fdl - ((unsigned short *)sprd_img.tx_b, sprd_img.tx_size); - memcpy(sprd_img.encoded_tx_b, sprd_img.tx_b, sprd_img.tx_size); - sprd_img.encoded_tx_size = sprd_img.tx_size; - - spi_ptr = sprd_img.encoded_tx_b; - spi_size = sprd_img.encoded_tx_size; - - pr_debug("(%d) [Transfer Start, Type = %d, Packet = %d]\n", - __LINE__, type, sprd_packet_size); - retval = spi_send_modem_bin_execute_cmd - (spi_ptr, spi_size, spi_type, crc, &sprd_img); - if (retval < 0) { - pr_err("(%d) spi_send_modem_bin_execute_cmd fail : %d", - __LINE__, retval); - goto err0; - } - M_32_SWAP(img->length); - - /* Send Data */ - for (i = 0; send_size < img->length; i++) { - if (rest_size < sprd_packet_size) - data_size = rest_size; - - sprd_img.encoded_tx_size = sprd_packet_size; - for (j = 0; j < data_size; j++) - *(sprd_img.encoded_tx_b+j) = *(ptr + j); - - spi_type = 0x0002; - crc = sprd_crc_calc_fdl - ((unsigned short *)sprd_img.encoded_tx_b, - sprd_img.encoded_tx_size); - - spi_ptr = sprd_img.encoded_tx_b; - spi_size = sprd_img.encoded_tx_size; - - retval = spi_send_modem_bin_execute_cmd - (spi_ptr, spi_size, spi_type, crc, &sprd_img); - if (retval < 0) { - pr_err("(%d) spi_send_modem_bin_execute_cmd fail : %d, %d", - __LINE__, retval, i); - goto err0; - } - - send_size += data_size; - rest_size -= data_size; - ptr += data_size; - - if (!(i % 100)) - pr_debug("(%d) [%d] 0x%x size done, rest size: 0x%x\n", - __LINE__, i, send_size, rest_size); - } - - /* Send Transfer End */ - memset(sprd_img.encoded_tx_b, 0, SPRD_BLOCK_SIZE * 2); - sprd_img.encoded_tx_size = 0; - - spi_type = 0x0003; - crc = 0; - - spi_ptr = sprd_img.encoded_tx_b; - spi_size = sprd_img.encoded_tx_size; - - pr_debug("(%d) [Transfer END]\n", __LINE__); - retval = spi_send_modem_bin_execute_cmd - (spi_ptr, spi_size, spi_type, crc, &sprd_img); - if (retval < 0) { - pr_err("(%d) spi_send_modem_bin_execute_cmd fail : %d", - __LINE__, retval); - goto err0; - } - -err0: - kfree(sprd_img.decoded_rx_b); -err1: - kfree(sprd_img.encoded_tx_b); -err2: - kfree(sprd_img.rx_b); -err3: - kfree(sprd_img.tx_b); - - return retval; - -} - -static void spi_send_modem_bin(struct work_struct *send_modem_w) -{ - struct spi_link_device *spild; - struct io_device *iod; - int retval; - struct image_buf img; - unsigned long tick1, tick2 = 0; - - spild = p_spild; - iod = link_get_iod_with_format(&spild->ld, IPC_FMT); - if (!iod) { - mif_err("no iodevice for modem control\n"); - return; - } - - tick1 = jiffies_to_msecs(jiffies); - - retval = spi_send_modem_bin_xmit_img(MODEM_MAIN, &img); - if (retval < 0) { - pr_err("(%d) spi_send_modem_bin_xmit_img fail : %d", - __LINE__, retval); - goto err; - } - - retval = spi_send_modem_bin_xmit_img(MODEM_DSP, &img); - if (retval < 0) { - pr_err("(%d) spi_send_modem_bin_xmit_img fail : %d", - __LINE__, retval); - goto err; - } - - retval = spi_send_modem_bin_xmit_img(MODEM_NV, &img); - if (retval < 0) { - pr_err("(%d) spi_send_modem_bin_xmit_img fail : %d", - __LINE__, retval); - goto err; - } - - retval = spi_send_modem_bin_xmit_img(MODEM_EFS, &img); - if (retval < 0) { - pr_err("(%d) spi_send_modem_bin_xmit_img fail : %d", - __LINE__, retval); - goto err; - } - - retval = spi_send_modem_bin_xmit_img(MODEM_RUN, &img); - if (retval < 0) { - pr_err("(%d) spi_send_modem_bin_xmit_img fail : %d", - __LINE__, retval); - goto err; - } - - p_spild->send_modem_spi = 0; - p_spild->is_cp_reset = 0; - tick2 = jiffies_to_msecs(jiffies); - pr_info("Downloading takes %lu msec\n", (tick2-tick1)); - - spi_init_ipc(p_spild); - - sprd_boot_done = 1; - p_spild->ril_send_cnt = 0; - p_spild->spi_state = SPI_STATE_IDLE; - - if (iod) - iod->modem_state_changed(iod, - STATE_ONLINE); - return; -err: - if (iod) - iod->modem_state_changed(iod, - STATE_OFFLINE); - return; - -} - -static inline int _request_mem(struct spi_v_buff *od) -{ - if (!p_spild->p_virtual_buff) { - od->mmio = vmalloc(od->size); - if (!od->mmio) { - pr_err("(%d) Failed to vmalloc size : %lu\n", __LINE__, - od->size); - - return -EBUSY; - } else { - pr_err("(%d) vmalloc Done. mmio : 0x%08x\n", __LINE__, - (u32)od->mmio); - } - } - - memset((void *)od->mmio, 0, od->size); - - p_spild->p_virtual_buff = od->mmio; - - return 0; -} - -void spi_tx_timer_callback(unsigned long param) -{ - if (p_spild->spi_state == SPI_STATE_TX_WAIT) { - p_spild->spi_timer_tx_state = SPI_STATE_TIME_OVER; - pr_debug("[SPI] spi_tx_timer_callback -timer expires\n"); - } -} - -void spi_rx_timer_callback(unsigned long param) -{ - if (p_spild->spi_state == SPI_STATE_RX_WAIT) { - p_spild->spi_timer_rx_state = SPI_STATE_TIME_OVER; - pr_debug("[SPI] spi_rx_timer_callback -timer expires\n"); - } -} - -int spi_sema_init(void) -{ - pr_info("[SPI] Srdy sema init\n"); - sema_init(&p_spild->srdy_sem, 0); - p_spild->send_modem_spi = 1; - return 0; -} - -static void spi_work(struct work_struct *work) -{ - int signal_code; - - struct spi_work_type *spi_wq = - container_of(work, struct spi_work_type, work); - - signal_code = spi_wq->signal_code; - - if (p_spild->spi_state == SPI_STATE_END - || p_spild->spi_state == SPI_STATE_START) { - kfree(spi_wq); - return; - } - - switch (signal_code) { - case SPI_WORK_SEND: - if (p_spild->spi_state == SPI_STATE_IDLE) - spi_tx_work(); - break; - case SPI_WORK_RECEIVE: - if (p_spild->spi_state == SPI_STATE_IDLE - || p_spild->spi_state == SPI_STATE_TX_TERMINATE - || p_spild->spi_state == SPI_STATE_RX_TERMINATE) - spi_rx_work(); - break; - - default: - pr_err("[SPI] ERROR(No signal_code in spi_work[%d])\n", - signal_code); - break; - } - - kfree(spi_wq); - if (wake_lock_active(&p_spild->spi_wake_lock)) { - wake_unlock(&p_spild->spi_wake_lock); - pr_debug("[SPI] [%s](%d) spi_wakelock unlocked .\n", - __func__, __LINE__); - } -} - -static int link_pm_notifier_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct io_device *iod; - struct link_pm_data *pm_data = - container_of(this, struct link_pm_data, pm_notifier); - - iod = link_get_iod_with_format(&pm_data->spild->ld, IPC_FMT); - if (!iod) { - pr_err("no iodevice for modem control\n"); - return NOTIFY_BAD; - } - - switch (event) { - case PM_SUSPEND_PREPARE: - /* set TD PDA Active High if previous state was LPA */ - mif_info("TD PDA active low to LPA suspend spot\n"); - gpio_set_value(iod->mc->gpio_pda_active, 0); - - return NOTIFY_OK; - case PM_POST_SUSPEND: - /* LPA to Kernel suspend and User Freezing task fail resume, - restore to LPA GPIO states. */ - mif_info("TD PDA active High to LPA GPIO state\n"); - gpio_set_value(iod->mc->gpio_pda_active, 1); - return NOTIFY_OK; - } - return NOTIFY_DONE; -} - -static int spi_probe(struct spi_device *spi) -{ - int ret; - - p_spi = spi; - p_spi->mode = SPI_MODE_1; - p_spi->bits_per_word = 32; - - ret = spi_setup(p_spi); - if (ret != 0) { - - pr_err("[%s] spi setup error\n", __func__); - - return ret; - } - - pr_info("[%s] spi probe done\n", __func__); - - return ret; -} - -static int spi_remove(struct spi_device *spi) -{ - return 0; -} - -static struct spi_driver spi_driver = { - .probe = spi_probe, - .remove = __devexit_p(spi_remove), - .driver = { - .name = "modem_if_spi", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, -}; - -static int spi_link_init(void) -{ - int ret; - struct spi_v_buff *od; - struct link_device *ld = &p_spild->ld; - - p_spild->gpio_modem_bin_srdy = p_spild->gpio_ipc_srdy; - - pr_info("(%d) gpio_mrdy : %d, gpio_srdy : %d(%d)\n", __LINE__, - p_spild->gpio_ipc_mrdy, p_spild->gpio_modem_bin_srdy, - gpio_get_value(p_spild->gpio_ipc_srdy)); - - od = kzalloc(sizeof(struct spi_v_buff), GFP_KERNEL); - if (!od) { - pr_err("(%d) failed to allocate device\n", __LINE__); - ret = -ENOMEM; - goto err; - } - - od->base = 0; - od->size = SZ_16M; /* 16M */ - if (p_spild->p_virtual_buff) - od->mmio = p_spild->p_virtual_buff; - ret = _request_mem(od); - if (ret) - goto err; - - sema_init(&p_spild->srdy_sem, 0); - - INIT_WORK(&p_spild->send_modem_w, - spi_send_modem_bin); - - wake_lock_init(&p_spild->spi_wake_lock, - WAKE_LOCK_SUSPEND, - "samsung-spiwakelock"); - - /* Register SPI Srdy interrupt handler */ - ret = spi_register_isr(gpio_to_irq(p_spild->gpio_ipc_srdy), - spi_srdy_irq_handler, IRQF_TRIGGER_RISING, - "spi_srdy_rising", ld); - - if (ret) - goto err; - - /* Register SPI SubSrdy interrupt handler */ - ret = spi_register_isr(gpio_to_irq(p_spild->gpio_ipc_sub_srdy), - spi_subsrdy_irq_handler, IRQF_TRIGGER_RISING, - "spi_subsrdy_rising", ld); - - if (ret) - goto err; - - p_spild->boot_done = 1; - - pr_info("[%s] Done\n", __func__); - return 0; - -err: - kfree(od); - return ret; -} - -/*===================================== -* Description spi restart for CP slient reset -=====================================*/ -void spi_set_restart(void) -{ - struct link_device *ld = &p_spild->ld; - - pr_info("[SPI] spi_set_restart(spi_main_state=[%d])\n", - (int)p_spild->spi_state); - - gpio_set_value(p_spild->gpio_ipc_sub_mrdy, SPI_GPIOLEVEL_LOW); - - p_spild->spi_state = SPI_STATE_END; - - /* Flush SPI work queue */ - flush_workqueue(p_spild->spi_wq); - - /* Unregister SPI Srdy interrupt handler */ - spi_unregister_isr(gpio_to_irq(p_spild->gpio_ipc_srdy), ld); - - /* Unregister SPI SubSrdy interrupt handler */ - spi_unregister_isr(gpio_to_irq(p_spild->gpio_ipc_sub_srdy), ld); - - if (wake_lock_active(&p_spild->spi_wake_lock)) { - wake_unlock(&p_spild->spi_wake_lock); - pr_err("[SPI] [%s](%d) spi_wakelock unlocked.\n", - __func__, __LINE__); - } - wake_lock_destroy(&p_spild->spi_wake_lock); -} - - -int spi_thread_restart(void) -{ - int retval; - - p_spild->send_modem_spi = 1; - p_spild->is_cp_reset = 1; - sprd_boot_done = 0; - - pr_info("[modem_if_spi] spi_thread_restart\n"); - - spi_set_restart(); - - /* Create SPI device */ - retval = spi_link_init(); - if (retval) - goto exit; - - return 0; - -exit: - return retval; -} -EXPORT_SYMBOL(spi_thread_restart); - -static int spi_link_pm_init(struct spi_link_device *spild, - struct platform_device *pdev) -{ - struct modem_data *pdata = - (struct modem_data *)pdev->dev.platform_data; - struct modemlink_pm_data *pm_pdata; - struct link_pm_data *pm_data = - kzalloc(sizeof(struct link_pm_data), GFP_KERNEL); - - if (!pdata || !pdata->link_pm_data) { - mif_err("platform data is NULL\n"); - return -EINVAL; - } - pm_pdata = pdata->link_pm_data; - - if (!pm_data) { - mif_err("link_pm_data is NULL\n"); - return -ENOMEM; - } - - pm_data->spild = spild; - spild->link_pm_data = pm_data; - - pm_data->pm_notifier.notifier_call = link_pm_notifier_event; - register_pm_notifier(&pm_data->pm_notifier); - - return 0; -} - -struct link_device *spi_create_link_device(struct platform_device *pdev) -{ - struct spi_link_device *spild = NULL; - struct link_device *ld; - struct modem_data *pdata; - - int ret; - int i; - - /* Get the platform data */ - pdata = (struct modem_data *)pdev->dev.platform_data; - if (!pdata) { - pr_err("[LNK/E] <%s> pdata == NULL\n", __func__); - goto err; - } - - pr_info("[LNK] <%s> link device = %s\n", __func__, pdata->link_name); - pr_info("[LNK] <%s> modem = %s\n", __func__, pdata->name); - - /* Alloc SPI link device structure */ - p_spild = spild = kzalloc(sizeof(struct spi_link_device), GFP_KERNEL); - if (!spild) { - pr_err("[LNK/E] <%s> Failed to kzalloc()\n", __func__); - goto err; - } - ld = &spild->ld; - - /* Extract modem data and SPI control data from the platform data */ - ld->mdm_data = pdata; - ld->name = "spi"; - - if (ld->aligned) - pr_err("[LNK] <%s> Aligned access is required!!!\n", __func__); - - - ld->send = spi_send; - - INIT_LIST_HEAD(&ld->list); - - skb_queue_head_init(&ld->sk_fmt_tx_q); - skb_queue_head_init(&ld->sk_raw_tx_q); - skb_queue_head_init(&ld->sk_rfs_tx_q); - ld->skb_txq[IPC_FMT] = &ld->sk_fmt_tx_q; - ld->skb_txq[IPC_RAW] = &ld->sk_raw_tx_q; - ld->skb_txq[IPC_RFS] = &ld->sk_rfs_tx_q; - - spild->spi_wq = create_singlethread_workqueue("spi_wq"); - if (!spild->spi_wq) { - pr_err("[LNK/E] <%s> Fail to create workqueue for spi_wq\n", - __func__); - goto err; - } - - spild->spi_state = SPI_STATE_END; - spild->max_ipc_dev = IPC_RFS+1; /* FMT, RAW, RFS */ - - for (i = 0; i < spild->max_ipc_dev; i++) - skb_queue_head_init(&spild->skb_rxq[i]); - - /* Prepare a clean buffer for SPI access */ - spild->buff = kzalloc(SPI_MAX_PACKET_SIZE, GFP_KERNEL); - spild->sync_buff = kzalloc(SPI_MAX_PACKET_SIZE, GFP_KERNEL); - - memset(spild->buff , 0, SPI_MAX_PACKET_SIZE); - memset(spild->sync_buff , 0, SPI_MAX_PACKET_SIZE); - - if (!spild->buff) { - pr_err("[LNK/E] <%s> Failed to alloc spild->buff\n", __func__); - goto err; - } - - /* Initialize SPI pin value */ - spild->gpio_ipc_mrdy = pdata->gpio_ipc_mrdy; - spild->gpio_ipc_srdy = pdata->gpio_ipc_srdy; - spild->gpio_ipc_sub_mrdy = pdata->gpio_ipc_sub_mrdy; - spild->gpio_ipc_sub_srdy = pdata->gpio_ipc_sub_srdy; - - spild->gpio_ap_cp_int1 = pdata->gpio_ap_cp_int1; - spild->gpio_ap_cp_int2 = pdata->gpio_ap_cp_int2; - - /* Create SPI Timer */ - init_timer(&spild->spi_tx_timer); - - spild->spi_tx_timer.expires = - jiffies + ((SPI_TIMER_TX_WAIT_TIME * HZ) / 1000); - - spild->spi_tx_timer.data = 0; - spild->spi_tx_timer.function = spi_tx_timer_callback; - - init_timer(&spild->spi_rx_timer); - - spild->spi_rx_timer.expires = - jiffies + ((SPI_TIMER_RX_WAIT_TIME * HZ) / 1000); - - spild->spi_rx_timer.data = 0; - spild->spi_rx_timer.function = spi_rx_timer_callback; - - ret = spi_register_driver(&spi_driver); - if (ret < 0) { - pr_err("spi_register_driver() fail : %d\n", ret); - goto err; - } - - /* create link pm device */ - ret = spi_link_pm_init(spild, pdev); - if (ret) - goto err; - - /* Create SPI device */ - ret = spi_link_init(); - if (ret) - goto err; - - /* creat work queue thread */ - p_spild->ipc_spi_wq = create_singlethread_workqueue("ipc_spi_wq"); - - if (!p_spild->ipc_spi_wq) { - pr_err("[%s] get workqueue thread fail\n", - __func__); - - ret = -ENOMEM; - goto err; - } - - return ld; - -err: - kfree(spild->buff); - kfree(spild); - return NULL; -} |