diff options
author | Chanho Park <chanho61.park@samsung.com> | 2014-04-15 13:42:22 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-11-18 11:47:30 +0900 |
commit | c8f38e22848411f7c74bdd73d03decdbc5436130 (patch) | |
tree | 476c0a29faf395f9349f32107d955beab14dc8bb /drivers | |
parent | 3d9d0681f245f141c89aa0daf6a549788a1388f7 (diff) | |
download | linux-3.10-c8f38e22848411f7c74bdd73d03decdbc5436130.tar.gz linux-3.10-c8f38e22848411f7c74bdd73d03decdbc5436130.tar.bz2 linux-3.10-c8f38e22848411f7c74bdd73d03decdbc5436130.zip |
misc: modem_if: regress to old tizen modem driver
Tizen modem utility and xmm626x modem uses old style modem I/F. I
brought the driver from linux-3.0 kernel[1] because the driver
should be matched with telephony and modem-util package.
Kamil brought the driver from linux-3.4-exynos, but the driver didn't
match the current telephony daemon and modem util. Data communication
didn't work with the driver. So, I decided to regress to old driver.
Tizen Modem Team doesn't have any plan to update latest version of
modem package. To maintain consistency of the interface, I picked
the driver from linux-3.0 tree.
[1] : https://review.tizen.org/gerrit/gitweb?p=kernel%2Flinux-3.0.git;a=summary
Change-Id: I6123f4dc149dcc38e1ae339f950f94fdc0c033f9
Signed-off-by: Chanho Park <chanho61.park@samsung.com>
Diffstat (limited to 'drivers')
38 files changed, 861 insertions, 15222 deletions
diff --git a/drivers/misc/modem_if/Kconfig b/drivers/misc/modem_if/Kconfig index 234de2fad2b..0a06a3908c0 100644 --- a/drivers/misc/modem_if/Kconfig +++ b/drivers/misc/modem_if/Kconfig @@ -1,8 +1,6 @@ menuconfig SEC_MODEM bool "Samsung Mobile Modem Interface" default n - ---help--- - Samsung Modem Interface Driver. config UMTS_MODEM_XMM6260 bool "modem chip : IMC XMM6260" @@ -49,10 +47,6 @@ config LINK_DEVICE_DPRAM depends on SEC_MODEM default n -config LINK_DEVICE_PLD - bool "modem driver link device PLD" - depends on SEC_MODEM - default n config LINK_DEVICE_USB bool "modem driver link device USB" depends on SEC_MODEM diff --git a/drivers/misc/modem_if/Makefile b/drivers/misc/modem_if/Makefile index 9bedbe1c139..15ef0c85917 100644 --- a/drivers/misc/modem_if/Makefile +++ b/drivers/misc/modem_if/Makefile @@ -1,9 +1,8 @@ # Makefile of modem_if -EXTRA_CFLAGS += -Idrivers/misc/modem_if +EXTRA_CFLAGS += -Idrivers/misc/modem_if_tizen -obj-y += sipc5_modem.o sipc5_io_device.o -obj-y += sipc4_modem.o sipc4_io_device.o +obj-y += tizen_modem.o tizen_io_device.o obj-y += modem_net_flowcontrol_device.o modem_utils.o obj-$(CONFIG_UMTS_MODEM_XMM6260) += modem_modemctl_device_xmm6260.o @@ -16,7 +15,6 @@ obj-$(CONFIG_GSM_MODEM_ESC6270) += modem_modemctl_device_esc6270.o obj-$(CONFIG_LINK_DEVICE_MIPI) += modem_link_device_mipi.o obj-$(CONFIG_LINK_DEVICE_DPRAM) += modem_link_device_dpram.o modem_link_device_dpram_ext_op.o -obj-$(CONFIG_LINK_DEVICE_PLD) += modem_link_device_pld.o modem_link_device_pld_ext_op.o obj-$(CONFIG_LINK_DEVICE_USB) += modem_link_device_usb.o modem_link_pm_usb.o obj-$(CONFIG_LINK_DEVICE_HSIC) += modem_link_device_hsic.o obj-$(CONFIG_LINK_DEVICE_C2C) += modem_link_device_c2c.o diff --git a/drivers/misc/modem_if/lte_modem_bootloader.c b/drivers/misc/modem_if/lte_modem_bootloader.c deleted file mode 100644 index f259aaeb214..00000000000 --- a/drivers/misc/modem_if/lte_modem_bootloader.c +++ /dev/null @@ -1,313 +0,0 @@ -/* Lte modem bootloader support for Samsung Tuna Board. - * - * Copyright (C) 2011 Google, Inc. - * Copyright (C) 2011 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/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/miscdevice.h> - -#include <linux/uaccess.h> -#include <linux/fs.h> -#include <linux/wait.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/wakelock.h> -#include <linux/delay.h> -#include <linux/spi/spi.h> - -#include <linux/platform_data/modem.h> -#include <linux/platform_data/lte_modem_bootloader.h> - -#define LEN_XMIT_DELEY 100 - -#ifdef AIRPLAIN_MODE_TEST -int lte_airplain_mode; -#endif - -enum xmit_bootloader_status { - XMIT_BOOT_READY = 0, - XMIT_LOADER_READY, -}; - -struct lte_modem_bootloader { - struct spi_device *spi_dev; - struct miscdevice dev; - - struct mutex lock; - - unsigned int gpio_lte2ap_status; - enum xmit_bootloader_status xmit_status; -}; -#define to_loader(misc) container_of(misc, struct lte_modem_bootloader, dev); - -static inline -int spi_xmit(struct lte_modem_bootloader *loader, - const unsigned char val) -{ - unsigned char buf[1]; - int ret; - struct spi_message msg; - - struct spi_transfer xfer = { - .len = 1, - .tx_buf = buf, - }; - - buf[0] = val; - - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - - ret = spi_sync(loader->spi_dev, &msg); - - if (ret < 0) - mif_err("error %d\n", ret); - - return ret; -} - -static -int bootloader_write(struct lte_modem_bootloader *loader, - const char *addr, const int len) -{ - int i; - int ret = 0; - unsigned char lenbuf[4]; - - if (loader->xmit_status == XMIT_LOADER_READY) { - memcpy(lenbuf, &len, ARRAY_SIZE(lenbuf)); - for (i = 0 ; i < ARRAY_SIZE(lenbuf) ; i++) { - ret = spi_xmit(loader, lenbuf[i]); - if (ret < 0) - return ret; - } - msleep(LEN_XMIT_DELEY); - } - - for (i = 0 ; i < len ; i++) { - ret = spi_xmit(loader, addr[i]); - if (ret < 0) - return ret; - } - - return 0; -} - - -static -int bootloader_open(struct inode *inode, struct file *flip) -{ - struct lte_modem_bootloader *loader = to_loader(flip->private_data); - flip->private_data = loader; - - return 0; -} - -static -long bootloader_ioctl(struct file *flip, - unsigned int cmd, unsigned long arg) -{ - int ret = 0; - int status; - struct lte_modem_bootloader_param param; - struct lte_modem_bootloader *loader = flip->private_data; - - mutex_lock(&loader->lock); - switch (cmd) { - case IOCTL_LTE_MODEM_XMIT_BOOT: - - ret = copy_from_user(¶m, (const void __user *)arg, - sizeof(param)); - if (ret) { - mif_err("can not copy userdata\n"); - ret = -EFAULT; - goto exit_err; - } - - dev_info(&loader->spi_dev->dev, - "IOCTL_LTE_MODEM_XMIT_BOOT - bin size: %d\n", - param.len); - - ret = bootloader_write(loader, param.buf, param.len); - if (ret < 0) - mif_err("failed to xmit boot bin\n"); - else { - if (loader->xmit_status == XMIT_BOOT_READY) - loader->xmit_status = XMIT_LOADER_READY; - else - loader->xmit_status = XMIT_BOOT_READY; - } - - break; - case IOCTL_LTE_MODEM_LTE2AP_STATUS: - status = gpio_get_value(loader->gpio_lte2ap_status); - mif_debug("LTE2AP status :%d\n", status); - ret = copy_to_user((unsigned int *)arg, &status, - sizeof(status)); - - break; -#ifdef AIRPLAIN_MODE_TEST - case IOCTL_LTE_MODEM_AIRPLAIN_ON: - lte_airplain_mode = 1; - mif_info("IOCTL_LTE_MODEM LPM_ON\n"); - break; - case IOCTL_LTE_MODEM_AIRPLAIN_OFF: - mif_info("IOCTL_LTE_MODEM LPM_OFF\n"); - lte_airplain_mode = 0; - break; -#endif - default: - mif_err("ioctl cmd error\n"); - ret = -ENOIOCTLCMD; - - break; - } - mutex_unlock(&loader->lock); - -exit_err: - return ret; -} - -static const struct file_operations lte_modem_bootloader_fops = { - .owner = THIS_MODULE, - .open = bootloader_open, - .unlocked_ioctl = bootloader_ioctl, -}; - -static -int bootloader_gpio_setup(struct lte_modem_bootloader *loader) -{ - if (!loader->gpio_lte2ap_status) - return -EINVAL; - - gpio_request(loader->gpio_lte2ap_status, "GPIO_LTE2AP_STATUS"); - gpio_direction_input(loader->gpio_lte2ap_status); - - return 0; -} - -static -int __devinit lte_modem_bootloader_probe(struct spi_device *spi) -{ - int ret; - - struct lte_modem_bootloader *loader; - struct lte_modem_bootloader_platform_data *pdata; - - loader = kzalloc(sizeof(*loader), GFP_KERNEL); - if (!loader) { - mif_err("failed to allocate for lte_modem_bootloader\n"); - ret = -ENOMEM; - goto err_alloc; - } - mutex_init(&loader->lock); - - spi->bits_per_word = 8; - - if (spi_setup(spi)) { - mif_err("failed to setup spi for lte_modem_bootloader\n"); - ret = -EINVAL; - goto err_setup; - } - - loader->spi_dev = spi; - - if (!spi->dev.platform_data) { - mif_err("failed to get platform data for lte_modem_bootloader\n"); - ret = -EINVAL; - goto err_setup; - } - pdata = (struct lte_modem_bootloader_platform_data *) - spi->dev.platform_data; - loader->gpio_lte2ap_status = pdata->gpio_lte2ap_status; - - ret = bootloader_gpio_setup(loader); - if (ret) { - mif_err("failed to set gpio for lte_modem_boot_loader\n"); - goto err_setup; - } - - loader->gpio_lte2ap_status = pdata->gpio_lte2ap_status; - loader->xmit_status = XMIT_BOOT_READY; - - spi_set_drvdata(spi, loader); - - loader->dev.minor = MISC_DYNAMIC_MINOR; - loader->dev.name = "lte_spi"; - loader->dev.fops = <e_modem_bootloader_fops; - ret = misc_register(&loader->dev); - if (ret) { - mif_err("failed to register misc dev for lte_modem_bootloader\n"); - goto err_setup; - } - mif_info("lte_modem_bootloader successfully probed\n"); -#ifdef AIRPLAIN_MODE_TEST - lte_airplain_mode = 0; -#endif - return 0; - -err_setup: - mutex_destroy(&loader->lock); - kfree(loader); - -err_alloc: - - return ret; -} - -static -int __devexit lte_modem_bootloader_remove(struct spi_device *spi) -{ - struct lte_modem_bootloader *loader = spi_get_drvdata(spi); - - misc_deregister(&loader->dev); - mutex_destroy(&loader->lock); - kfree(loader); - - return 0; -} - -static -struct spi_driver lte_modem_bootloader_driver = { - .driver = { - .name = "lte_modem_spi", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = lte_modem_bootloader_probe, - .remove = __devexit_p(lte_modem_bootloader_remove), -}; - -static -int __init lte_modem_bootloader_init(void) -{ - return spi_register_driver(<e_modem_bootloader_driver); -} - -static -void __exit lte_modem_bootloader_exit(void) -{ - spi_unregister_driver(<e_modem_bootloader_driver); -} - -module_init(lte_modem_bootloader_init); -module_exit(lte_modem_bootloader_exit); - -MODULE_DESCRIPTION("LTE Modem Bootloader driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/misc/modem_if/modem_link_device_c2c.c b/drivers/misc/modem_if/modem_link_device_c2c.c deleted file mode 100644 index acbaadf0f93..00000000000 --- a/drivers/misc/modem_if/modem_link_device_c2c.c +++ /dev/null @@ -1,61 +0,0 @@ -/* /linux/drivers/new_modem_if/link_dev_c2c.c - * - * Copyright (C) 2010 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/init.h> -#include <linux/irq.h> -#include <linux/gpio.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/proc_fs.h> -#include <linux/if_arp.h> -#include <linux/platform_device.h> - -#include <linux/platform_data/modem.h> -#include <linux/platform_data/c2c.h> -#include "modem_prj.h" -#include "modem_link_device_c2c.h" - -struct link_device *c2c_create_link_device(struct platform_device *pdev) -{ - struct c2c_link_device *dpld; - struct link_device *ld; - struct modem_data *pdata; - - pdata = pdev->dev.platform_data; - - dpld = kzalloc(sizeof(struct c2c_link_device), GFP_KERNEL); - if (!dpld) { - mif_err("dpld == NULL\n"); - return NULL; - } - - wake_lock_init(&dpld->c2c_wake_lock, WAKE_LOCK_SUSPEND, "c2c_wakelock"); - wake_lock(&dpld->c2c_wake_lock); - - ld = &dpld->ld; - dpld->pdata = pdata; - - ld->name = "c2c"; - - mif_info("%s is created!!!\n", dpld->ld.name); - - return ld; -} diff --git a/drivers/misc/modem_if/modem_link_device_c2c.h b/drivers/misc/modem_if/modem_link_device_c2c.h deleted file mode 100644 index 7ec9aa635aa..00000000000 --- a/drivers/misc/modem_if/modem_link_device_c2c.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2010 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/wakelock.h> - -#ifndef __MODEM_LINK_DEVICE_C2C_H__ -#define __MODEM_LINK_DEVICE_C2C_H__ - -#define DPRAM_ERR_MSG_LEN 128 -#define DPRAM_ERR_DEVICE "c2cerr" - -#define MAX_IDX 2 - -#define DPRAM_BASE_PTR 0x4000000 - -#define DPRAM_START_ADDRESS 0 -#define DPRAM_MAGIC_CODE_ADDRESS DPRAM_START_ADDRESS -#define DPRAM_GOTA_MAGIC_CODE_SIZE 0x4 -#define DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS \ - (DPRAM_START_ADDRESS + DPRAM_GOTA_MAGIC_CODE_SIZE) -#define BSP_DPRAM_BASE_SIZE 0x1ff8 -#define DPRAM_END_OF_ADDRESS (BSP_DPRAM_BASE_SIZE - 1) -#define DPRAM_INTERRUPT_SIZE 0x2 -#define DPRAM_PDA2PHONE_INTERRUPT_ADDRESS \ - (DPRAM_START_ADDRESS + BSP_DPRAM_BASE_SIZE - DPRAM_INTERRUPT_SIZE*2) -#define DPRAM_PHONE2PDA_INTERRUPT_ADDRESS \ - (DPRAM_START_ADDRESS + BSP_DPRAM_BASE_SIZE) -#define DPRAM_BUFFER_SIZE \ - (DPRAM_PHONE2PDA_INTERRUPT_ADDRESS -\ - DPRAM_PDA2PHONE_FORMATTED_START_ADDRESS) -#define DPRAM_INDEX_SIZE 0x2 - -#define MAGIC_DMDL 0x4445444C -#define MAGIC_UMDL 0x4445444D - -#define DPRAM_PACKET_DATA_SIZE 0x3f00 -#define DPRAM_PACKET_HEADER_SIZE 0x7 - -#define INT_GOTA_MASK_VALID 0xA000 -#define INT_DPRAM_DUMP_MASK_VALID 0xA000 -#define MASK_CMD_RECEIVE_READY_NOTIFICATION 0xA100 -#define MASK_CMD_DOWNLOAD_START_REQUEST 0xA200 -#define MASK_CMD_DOWNLOAD_START_RESPONSE 0xA301 -#define MASK_CMD_IMAGE_SEND_REQUEST 0xA400 -#define MASK_CMD_IMAGE_SEND_RESPONSE 0xA500 -#define MASK_CMD_SEND_DONE_REQUEST 0xA600 -#define MASK_CMD_SEND_DONE_RESPONSE 0xA701 -#define MASK_CMD_STATUS_UPDATE_NOTIFICATION 0xA800 -#define MASK_CMD_UPDATE_DONE_NOTIFICATION 0xA900 -#define MASK_CMD_EFS_CLEAR_RESPONSE 0xAB00 -#define MASK_CMD_ALARM_BOOT_OK 0xAC00 -#define MASK_CMD_ALARM_BOOT_FAIL 0xAD00 - -#define WRITEIMG_HEADER_SIZE 8 -#define WRITEIMG_TAIL_SIZE 4 -#define WRITEIMG_BODY_SIZE \ - (DPRAM_BUFFER_SIZE - WRITEIMG_HEADER_SIZE - WRITEIMG_TAIL_SIZE) - -#define DPDN_DEFAULT_WRITE_LEN WRITEIMG_BODY_SIZE -#define CMD_DL_START_REQ 0x9200 -#define CMD_IMG_SEND_REQ 0x9400 -#define CMD_DL_SEND_DONE_REQ 0x9600 - -#define CMD_UL_START_REQ 0x9200 -#define CMD_UL_START_READY 0x9400 -#define CMD_UL_SEND_RESP 0x9601 -#define CMD_UL_SEND_DONE_RESP 0x9801 -#define CMD_UL_SEND_REQ 0xA500 -#define CMD_UL_START_RESPONSE 0xA301 -#define CMD_UL_SEND_DONE_REQ 0xA700 -#define CMD_RECEIVE_READY_NOTIFICATION 0xA100 - -#define MASK_CMD_RESULT_FAIL 0x0002 -#define MASK_CMD_RESULT_SUCCESS 0x0001 - -#define START_INDEX 0x007F -#define END_INDEX 0x007E - -#define CMD_IMG_SEND_REQ 0x9400 - -#define CRC_TAB_SIZE 256 -#define CRC_16_L_SEED 0xFFFF - -struct c2c_device { - /* DPRAM memory addresses */ - u16 *in_head_addr; - u16 *in_tail_addr; - u8 *in_buff_addr; - unsigned long in_buff_size; - - u16 *out_head_addr; - u16 *out_tail_addr; - u8 *out_buff_addr; - unsigned long out_buff_size; - - unsigned long in_head_saved; - unsigned long in_tail_saved; - unsigned long out_head_saved; - unsigned long out_tail_saved; - - u16 mask_req_ack; - u16 mask_res_ack; - u16 mask_send; -}; - -struct memory_region { - u8 *control; - u8 *fmt_out; - u8 *raw_out; - u8 *fmt_in; - u8 *raw_in; - u8 *mbx; -}; - -struct UldDataHeader { - u8 bop; - u16 total_frame; - u16 curr_frame; - u16 len; -}; - -struct c2c_link_device { - struct link_device ld; - - struct modem_data *pdata; - - /*only c2c*/ - struct wake_lock c2c_wake_lock; - atomic_t raw_txq_req_ack_rcvd; - atomic_t fmt_txq_req_ack_rcvd; - u8 net_stop_flag; - int phone_sync; - u8 phone_status; - - struct work_struct xmit_work_struct; - - struct workqueue_struct *gota_wq; - struct work_struct gota_cmd_work; - - struct c2c_device dev_map[MAX_IDX]; - - struct wake_lock dumplock; - - u8 c2c_read_data[131072]; - - int c2c_init_cmd_wait_condition; - wait_queue_head_t c2c_init_cmd_wait_q; - - int modem_pif_init_wait_condition; - wait_queue_head_t modem_pif_init_done_wait_q; - - struct completion gota_download_start_complete; - - int gota_send_done_cmd_wait_condition; - wait_queue_head_t gota_send_done_cmd_wait_q; - - int gota_update_done_cmd_wait_condition; - wait_queue_head_t gota_update_done_cmd_wait_q; - - int upload_send_req_wait_condition; - wait_queue_head_t upload_send_req_wait_q; - - int upload_send_done_wait_condition; - wait_queue_head_t upload_send_done_wait_q; - - int upload_start_req_wait_condition; - wait_queue_head_t upload_start_req_wait_q; - - int upload_packet_start_condition; - wait_queue_head_t upload_packet_start_wait_q; - - u16 gota_irq_handler_cmd; - - u16 c2c_dump_handler_cmd; - - int dump_region_number; - - unsigned int is_c2c_err ; - - int c2c_dump_start; - int gota_start; - - char c2c_err_buf[DPRAM_ERR_MSG_LEN]; - - struct fasync_struct *c2c_err_async_q; - - void (*clear_interrupt)(struct c2c_link_device *); - - struct memory_region m_region; - - unsigned long fmt_out_buff_size; - unsigned long raw_out_buff_size; - unsigned long fmt_in_buff_size; - unsigned long raw_in_buff_size; - - struct delayed_work delayed_tx; - struct sk_buff *delayed_skb; - u8 delayed_count; -}; - -/* converts from struct link_device* to struct xxx_link_device* */ -#define to_c2c_link_device(linkdev) \ - container_of(linkdev, struct c2c_link_device, ld) - -#endif diff --git a/drivers/misc/modem_if/modem_link_device_dpram.c b/drivers/misc/modem_if/modem_link_device_dpram.c deleted file mode 100644 index ea0b21e33bd..00000000000 --- a/drivers/misc/modem_if/modem_link_device_dpram.c +++ /dev/null @@ -1,2111 +0,0 @@ -/* - * 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/kallsyms.h> -#include <linux/platform_data/modem.h> - -#include "modem_prj.h" -#include "modem_link_device_dpram.h" -#include "modem_utils.h" - -/* -** Function prototypes for basic DPRAM operations -*/ -static inline void clear_intr(struct dpram_link_device *dpld); -static inline u16 recv_intr(struct dpram_link_device *dpld); -static inline void send_intr(struct dpram_link_device *dpld, u16 mask); - -static inline u16 get_magic(struct dpram_link_device *dpld); -static inline void set_magic(struct dpram_link_device *dpld, u16 val); -static inline u16 get_access(struct dpram_link_device *dpld); -static inline void set_access(struct dpram_link_device *dpld, u16 val); - -static inline u32 get_tx_head(struct dpram_link_device *dpld, int id); -static inline u32 get_tx_tail(struct dpram_link_device *dpld, int id); -static inline void set_tx_head(struct dpram_link_device *dpld, int id, u32 in); -static inline void set_tx_tail(struct dpram_link_device *dpld, int id, u32 out); -static inline u8 *get_tx_buff(struct dpram_link_device *dpld, int id); -static inline u32 get_tx_buff_size(struct dpram_link_device *dpld, int id); - -static inline u32 get_rx_head(struct dpram_link_device *dpld, int id); -static inline u32 get_rx_tail(struct dpram_link_device *dpld, int id); -static inline void set_rx_head(struct dpram_link_device *dpld, int id, u32 in); -static inline void set_rx_tail(struct dpram_link_device *dpld, int id, u32 out); -static inline u8 *get_rx_buff(struct dpram_link_device *dpld, int id); -static inline u32 get_rx_buff_size(struct dpram_link_device *dpld, int id); - -static inline u16 get_mask_req_ack(struct dpram_link_device *dpld, int id); -static inline u16 get_mask_res_ack(struct dpram_link_device *dpld, int id); -static inline u16 get_mask_send(struct dpram_link_device *dpld, int id); - -static inline void reset_tx_circ(struct dpram_link_device *dpld, int dev); -static inline void reset_rx_circ(struct dpram_link_device *dpld, int dev); - -static int trigger_force_cp_crash(struct dpram_link_device *dpld); - -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP -static inline void log_dpram_status(struct dpram_link_device *dpld, char *str) -{ - struct utc_time utc; - - get_utc_time(&utc); - - pr_info("%s%s: %s: [%02d:%02d:%02d.%03d] " - "ACC{%X %d} FMT{TI:%u TO:%u RI:%u RO:%u} " - "RAW{TI:%u TO:%u RI:%u RO:%u} INTR{0x%X}\n", - LOG_TAG, dpld->ld.mc->name, str, - utc.hour, utc.min, utc.sec, utc.msec, - get_magic(dpld), get_access(dpld), - get_tx_head(dpld, IPC_FMT), get_tx_tail(dpld, IPC_FMT), - get_rx_head(dpld, IPC_FMT), get_rx_tail(dpld, IPC_FMT), - get_tx_head(dpld, IPC_RAW), get_tx_tail(dpld, IPC_RAW), - get_rx_head(dpld, IPC_RAW), get_rx_tail(dpld, IPC_RAW), - recv_intr(dpld)); -} - -static void pr_trace(struct dpram_link_device *dpld, int dev, - struct timespec *ts, u8 *buff, u32 rcvd) -{ - struct link_device *ld = &dpld->ld; - struct utc_time utc; - - ts2utc(ts, &utc); - - pr_info("%s[%d-%02d-%02d %02d:%02d:%02d.%03d] %s trace (%s)\n", - LOG_TAG, utc.year, utc.mon, utc.day, utc.hour, utc.min, utc.sec, - utc.msec, get_dev_name(dev), ld->name); - - mif_print_dump(buff, rcvd, 4); - - return; -} - -static void save_dpram_dump_work(struct work_struct *work) -{ - struct dpram_link_device *dpld; - struct link_device *ld; - struct trace_queue *trq; - struct trace_data *trd; - struct file *fp; - struct timespec *ts; - u8 *dump; - int rcvd; - char *path; - struct utc_time utc; - - dpld = container_of(work, struct dpram_link_device, dump_dwork.work); - ld = &dpld->ld; - trq = &dpld->dump_list; - path = dpld->dump_path; - - while (1) { - trd = trq_get_data_slot(trq); - if (!trd) - break; - - ts = &trd->ts; - dump = trd->data; - rcvd = trd->size; - - ts2utc(ts, &utc); - snprintf(path, MIF_MAX_PATH_LEN, - "%s/%s_dump_%d%02d%02d-%02d%02d%02d", - MIF_LOG_DIR, ld->name, utc.year, utc.mon, utc.day, - utc.hour, utc.min, utc.sec); - - fp = mif_open_file(path); - if (fp) { - mif_save_file(fp, dump, rcvd); - mif_close_file(fp); - } else { - mif_err("%s: ERR! %s open fail\n", ld->name, path); - mif_print_dump(dump, rcvd, 16); - } - - kfree(dump); - } -} - -static void save_dpram_dump(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - struct trace_data *trd; - u8 *buff; - struct timespec ts; - - buff = kzalloc(dpld->size, GFP_ATOMIC); - if (!buff) { - mif_err("%s: ERR! kzalloc fail\n", ld->name); - return; - } - - getnstimeofday(&ts); - - memcpy(buff, dpld->base, dpld->size); - - trd = trq_get_free_slot(&dpld->dump_list); - if (!trd) { - mif_err("%s: ERR! trq_get_free_slot fail\n", ld->name); - mif_print_dump(buff, dpld->size, 16); - kfree(buff); - return; - } - - memcpy(&trd->ts, &ts, sizeof(struct timespec)); - trd->data = buff; - trd->size = dpld->size; - - queue_delayed_work(system_nrt_wq, &dpld->dump_dwork, 0); -} - -static void save_ipc_trace_work(struct work_struct *work) -{ - struct dpram_link_device *dpld; - struct link_device *ld; - struct trace_queue *trq; - struct trace_data *trd; - struct file *fp; - struct timespec *ts; - int dev; - u8 *dump; - int rcvd; - u8 *buff; - char *path; - struct utc_time utc; - - dpld = container_of(work, struct dpram_link_device, trace_dwork.work); - ld = &dpld->ld; - trq = &dpld->trace_list; - path = dpld->trace_path; - - buff = kzalloc(dpld->size << 3, GFP_KERNEL); - if (!buff) { - while (1) { - trd = trq_get_data_slot(trq); - if (!trd) - break; - - ts = &trd->ts; - dev = trd->dev; - dump = trd->data; - rcvd = trd->size; - pr_trace(dpld, dev, ts, dump, rcvd); - - kfree(dump); - } - return; - } - - while (1) { - trd = trq_get_data_slot(trq); - if (!trd) - break; - - ts = &trd->ts; - dev = trd->dev; - dump = trd->data; - rcvd = trd->size; - - ts2utc(ts, &utc); - snprintf(path, MIF_MAX_PATH_LEN, - "%s/%s_%s_%d%02d%02d-%02d%02d%02d", - MIF_LOG_DIR, ld->name, get_dev_name(dev), - utc.year, utc.mon, utc.day, utc.hour, utc.min, utc.sec); - - fp = mif_open_file(path); - if (fp) { - int len; - - snprintf(buff, MIF_MAX_PATH_LEN, - "[%d-%02d-%02d %02d:%02d:%02d.%03d]\n", - utc.year, utc.mon, utc.day, utc.hour, utc.min, - utc.sec, utc.msec); - len = strlen(buff); - mif_dump2format4(dump, rcvd, (buff + len), NULL); - strcat(buff, "\n"); - len = strlen(buff); - - mif_save_file(fp, buff, len); - - memset(buff, 0, len); - mif_close_file(fp); - } else { - mif_err("%s: %s open fail\n", ld->name, path); - pr_trace(dpld, dev, ts, dump, rcvd); - } - - kfree(dump); - } - - kfree(buff); -} - -static void print_ipc_trace(struct dpram_link_device *dpld, int dev, - u8 __iomem *src, u32 qsize, u32 in, u32 out, u32 rcvd) -{ - u8 *buff = dpld->buff; - struct timespec ts; - - getnstimeofday(&ts); - - memset(buff, 0, dpld->size); - circ_read(buff, src, qsize, out, rcvd); - - pr_trace(dpld, dev, &ts, buff, rcvd); -} - -static void save_ipc_trace(struct dpram_link_device *dpld, int dev, - u8 __iomem *src, u32 qsize, u32 in, u32 out, u32 rcvd) -{ - struct link_device *ld = &dpld->ld; - struct trace_data *trd; - u8 *buff; - struct timespec ts; - - buff = kzalloc(rcvd, GFP_ATOMIC); - if (!buff) { - mif_err("%s: %s: ERR! kzalloc fail\n", - ld->name, get_dev_name(dev)); - print_ipc_trace(dpld, dev, src, qsize, in, out, rcvd); - return; - } - - getnstimeofday(&ts); - - circ_read(buff, src, qsize, out, rcvd); - - trd = trq_get_free_slot(&dpld->trace_list); - if (!trd) { - mif_err("%s: %s: ERR! trq_get_free_slot fail\n", - ld->name, get_dev_name(dev)); - pr_trace(dpld, dev, &ts, buff, rcvd); - kfree(buff); - return; - } - - memcpy(&trd->ts, &ts, sizeof(struct timespec)); - trd->dev = dev; - trd->data = buff; - trd->size = rcvd; - - queue_delayed_work(system_nrt_wq, &dpld->trace_dwork, 0); -} -#endif - -static void set_dpram_map(struct dpram_link_device *dpld, - struct mif_irq_map *map) -{ - map->magic = get_magic(dpld); - map->access = get_access(dpld); - - map->fmt_tx_in = get_tx_head(dpld, IPC_FMT); - map->fmt_tx_out = get_tx_tail(dpld, IPC_FMT); - map->fmt_rx_in = get_rx_head(dpld, IPC_FMT); - map->fmt_rx_out = get_rx_tail(dpld, IPC_FMT); - map->raw_tx_in = get_tx_head(dpld, IPC_RAW); - map->raw_tx_out = get_tx_tail(dpld, IPC_RAW); - map->raw_rx_in = get_rx_head(dpld, IPC_RAW); - map->raw_rx_out = get_rx_tail(dpld, IPC_RAW); - - map->cp2ap = recv_intr(dpld); -} - -/* -** DPRAM operations -*/ -static int register_isr(unsigned irq, irqreturn_t (*isr)(int, void*), - unsigned long flag, const char *name, - struct dpram_link_device *dpld) -{ - int ret; - - ret = request_irq(irq, isr, flag, name, dpld); - if (ret) { - mif_info("%s: ERR! request_irq fail (err %d)\n", name, ret); - return ret; - } - - ret = enable_irq_wake(irq); - if (ret) - mif_info("%s: ERR! enable_irq_wake fail (err %d)\n", name, ret); - - mif_info("%s (#%d) handler registered\n", name, irq); - - return 0; -} - -static inline void clear_intr(struct dpram_link_device *dpld) -{ - if (likely(dpld->need_intr_clear)) - dpld->ext_op->clear_intr(dpld); -} - -static inline u16 recv_intr(struct dpram_link_device *dpld) -{ - return ioread16(dpld->mbx2ap); -} - -static inline void send_intr(struct dpram_link_device *dpld, u16 mask) -{ - iowrite16(mask, dpld->mbx2cp); -} - -static inline u16 get_magic(struct dpram_link_device *dpld) -{ - return ioread16(dpld->magic); -} - -static inline void set_magic(struct dpram_link_device *dpld, u16 val) -{ - iowrite16(val, dpld->magic); -} - -static inline u16 get_access(struct dpram_link_device *dpld) -{ - return ioread16(dpld->access); -} - -static inline void set_access(struct dpram_link_device *dpld, u16 val) -{ - iowrite16(val, dpld->access); -} - -static inline u32 get_tx_head(struct dpram_link_device *dpld, int id) -{ - return ioread16(dpld->dev[id]->txq.head); -} - -static inline u32 get_tx_tail(struct dpram_link_device *dpld, int id) -{ - return ioread16(dpld->dev[id]->txq.tail); -} - -static inline void set_tx_head(struct dpram_link_device *dpld, int id, u32 in) -{ - int cnt = 0; - u32 val = 0; - - iowrite16((u16)in, dpld->dev[id]->txq.head); - - while (1) { - /* Check head value written */ - val = ioread16(dpld->dev[id]->txq.head); - if (likely(val == in)) - return; - - cnt++; - mif_err("ERR: %s txq.head(%d) != in(%d), count %d\n", - get_dev_name(id), val, in, cnt); - if (cnt >= MAX_RETRY_CNT) - break; - - /* Write head value again */ - udelay(100); - iowrite16((u16)in, dpld->dev[id]->txq.head); - } - - trigger_force_cp_crash(dpld); -} - -static inline void set_tx_tail(struct dpram_link_device *dpld, int id, u32 out) -{ - int cnt = 0; - u32 val = 0; - - iowrite16((u16)out, dpld->dev[id]->txq.tail); - - while (1) { - /* Check tail value written */ - val = ioread16(dpld->dev[id]->txq.tail); - if (likely(val == out)) - return; - - cnt++; - mif_err("ERR: %s txq.tail(%d) != out(%d), count %d\n", - get_dev_name(id), val, out, cnt); - if (cnt >= MAX_RETRY_CNT) - break; - - /* Write tail value again */ - udelay(100); - iowrite16((u16)out, dpld->dev[id]->txq.tail); - } - - trigger_force_cp_crash(dpld); -} - -static inline u8 *get_tx_buff(struct dpram_link_device *dpld, int id) -{ - return dpld->dev[id]->txq.buff; -} - -static inline u32 get_tx_buff_size(struct dpram_link_device *dpld, int id) -{ - return dpld->dev[id]->txq.size; -} - -static inline u32 get_rx_head(struct dpram_link_device *dpld, int id) -{ - return ioread16(dpld->dev[id]->rxq.head); -} - -static inline u32 get_rx_tail(struct dpram_link_device *dpld, int id) -{ - return ioread16(dpld->dev[id]->rxq.tail); -} - -static inline void set_rx_head(struct dpram_link_device *dpld, int id, u32 in) -{ - int cnt = 0; - u32 val = 0; - - iowrite16((u16)in, dpld->dev[id]->rxq.head); - - while (1) { - /* Check head value written */ - val = ioread16(dpld->dev[id]->rxq.head); - if (val == in) - return; - - cnt++; - mif_err("ERR: %s rxq.head(%d) != in(%d), count %d\n", - get_dev_name(id), val, in, cnt); - if (cnt >= MAX_RETRY_CNT) - break; - - /* Write head value again */ - udelay(100); - iowrite16((u16)in, dpld->dev[id]->rxq.head); - } - - trigger_force_cp_crash(dpld); -} - -static inline void set_rx_tail(struct dpram_link_device *dpld, int id, u32 out) -{ - int cnt = 0; - u32 val = 0; - - iowrite16((u16)out, dpld->dev[id]->rxq.tail); - - while (1) { - /* Check tail value written */ - val = ioread16(dpld->dev[id]->rxq.tail); - if (val == out) - return; - - cnt++; - mif_err("ERR: %s rxq.tail(%d) != out(%d), count %d\n", - get_dev_name(id), val, out, cnt); - if (cnt >= MAX_RETRY_CNT) - break; - - /* Write tail value again */ - udelay(100); - iowrite16((u16)out, dpld->dev[id]->rxq.tail); - } - - trigger_force_cp_crash(dpld); -} - -static inline u8 *get_rx_buff(struct dpram_link_device *dpld, int id) -{ - return dpld->dev[id]->rxq.buff; -} - -static inline u32 get_rx_buff_size(struct dpram_link_device *dpld, int id) -{ - return dpld->dev[id]->rxq.size; -} - -static inline u16 get_mask_req_ack(struct dpram_link_device *dpld, int id) -{ - return dpld->dev[id]->mask_req_ack; -} - -static inline u16 get_mask_res_ack(struct dpram_link_device *dpld, int id) -{ - return dpld->dev[id]->mask_res_ack; -} - -static inline u16 get_mask_send(struct dpram_link_device *dpld, int id) -{ - return dpld->dev[id]->mask_send; -} - -/* Get free space in the TXQ as well as in & out pointers */ -static int get_txq_space(struct dpram_link_device *dpld, int dev, u32 qsize, - u32 *in, u32 *out) -{ - struct link_device *ld = &dpld->ld; - int cnt = 0; - u32 head; - u32 tail; - int space; - - while (1) { - head = get_tx_head(dpld, dev); - tail = get_tx_tail(dpld, dev); - - space = circ_get_space(qsize, head, tail); - mif_debug("%s: %s_TXQ qsize[%u] in[%u] out[%u] space[%u]\n", - ld->name, get_dev_name(dev), qsize, head, tail, space); - - if (circ_valid(qsize, head, tail)) { - *in = head; - *out = tail; - return space; - } - - cnt++; - mif_err("%s: ERR! <%pf> " - "%s_TXQ invalid (size:%d in:%d out:%d), count %d\n", - ld->name, __builtin_return_address(0), - get_dev_name(dev), qsize, head, tail, cnt); - if (cnt >= MAX_RETRY_CNT) - break; - - udelay(100); - } - - *in = 0; - *out = 0; - return -EINVAL; -} - -/* Get data size in the RXQ as well as in & out pointers */ -static int get_rxq_rcvd(struct dpram_link_device *dpld, int dev, u32 qsize, - u32 *in, u32 *out) -{ - struct link_device *ld = &dpld->ld; - int cnt = 0; - u32 head; - u32 tail; - u32 rcvd; - - while (1) { - head = get_rx_head(dpld, dev); - tail = get_rx_tail(dpld, dev); - if (head == tail) { - *in = head; - *out = tail; - return 0; - } - - rcvd = circ_get_usage(qsize, head, tail); - mif_debug("%s: %s_RXQ qsize[%u] in[%u] out[%u] rcvd[%u]\n", - ld->name, get_dev_name(dev), qsize, head, tail, rcvd); - - if (circ_valid(qsize, head, tail)) { - *in = head; - *out = tail; - return rcvd; - } - - cnt++; - mif_err("%s: ERR! <%pf> " - "%s_RXQ invalid (size:%d in:%d out:%d), count %d\n", - ld->name, __builtin_return_address(0), - get_dev_name(dev), qsize, head, tail, cnt); - if (cnt >= MAX_RETRY_CNT) - break; - - udelay(100); - } - - *in = 0; - *out = 0; - return -EINVAL; -} - -static inline void reset_tx_circ(struct dpram_link_device *dpld, int dev) -{ - set_tx_head(dpld, dev, 0); - set_tx_tail(dpld, dev, 0); - if (dev == IPC_FMT) - trigger_force_cp_crash(dpld); -} - -static inline void reset_rx_circ(struct dpram_link_device *dpld, int dev) -{ -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - trigger_force_cp_crash(dpld); -#else - set_rx_tail(dpld, dev, get_rx_head(dpld, dev)); - if (dev == IPC_FMT) - trigger_force_cp_crash(dpld); -#endif -} - -/* -** CAUTION : dpram_allow_sleep() MUST be invoked after dpram_wake_up() success -*/ -static inline bool dpram_can_sleep(struct dpram_link_device *dpld) -{ - return dpld->need_wake_up; -} - -static int dpram_wake_up(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - - if (unlikely(!dpram_can_sleep(dpld))) - return 0; - - if (dpld->ext_op->wakeup(dpld) < 0) { - mif_err("%s: ERR! <%pf> DPRAM wakeup fail once\n", - ld->name, __builtin_return_address(0)); - - dpld->ext_op->sleep(dpld); - - udelay(10); - - if (dpld->ext_op->wakeup(dpld) < 0) { - mif_err("%s: ERR! <%pf> DPRAM wakeup fail twice\n", - ld->name, __builtin_return_address(0)); - return -EACCES; - } - } - - atomic_inc(&dpld->accessing); - return 0; -} - -static void dpram_allow_sleep(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - - if (unlikely(!dpram_can_sleep(dpld))) - return; - - if (atomic_dec_return(&dpld->accessing) <= 0) { - dpld->ext_op->sleep(dpld); - atomic_set(&dpld->accessing, 0); - mif_debug("%s: DPRAM sleep possible\n", ld->name); - } -} - -static int check_access(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - int i; - u16 magic = get_magic(dpld); - u16 access = get_access(dpld); - - if (likely(magic == DPRAM_MAGIC_CODE && access == 1)) - return 0; - - for (i = 1; i <= 100; i++) { - mif_info("%s: ERR! magic:%X access:%X -> retry:%d\n", - ld->name, magic, access, i); - udelay(100); - - magic = get_magic(dpld); - access = get_access(dpld); - if (likely(magic == DPRAM_MAGIC_CODE && access == 1)) - return 0; - } - - mif_info("%s: !CRISIS! magic:%X access:%X\n", ld->name, magic, access); - return -EACCES; -} - -static bool ipc_active(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - - /* Check DPRAM mode */ - if (ld->mode != LINK_MODE_IPC) { - mif_info("%s: <%pf> ld->mode != LINK_MODE_IPC\n", - ld->name, __builtin_return_address(0)); - return false; - } - - if (check_access(dpld) < 0) { - mif_info("%s: ERR! <%pf> check_access fail\n", - ld->name, __builtin_return_address(0)); - return false; - } - - return true; -} - -static void dpram_ipc_write(struct dpram_link_device *dpld, int dev, u32 qsize, - u32 in, u32 out, struct sk_buff *skb) -{ - struct link_device *ld = &dpld->ld; - u8 __iomem *buff = get_tx_buff(dpld, dev); - u8 *src = skb->data; - u32 len = skb->len; - u32 inp; - struct mif_irq_map map; - - circ_write(buff, src, qsize, in, len); - - /* update new in pointer */ - inp = in + len; - if (inp >= qsize) - inp -= qsize; - set_tx_head(dpld, dev, inp); - - if (dev == IPC_FMT) { -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - char tag[MIF_MAX_STR_LEN]; - snprintf(tag, MIF_MAX_STR_LEN, "%s: MIF2CP", ld->mc->name); - pr_ipc(tag, src, (len > 20 ? 20 : len)); - log_dpram_status(dpld, "MIF2CP"); -#endif - set_dpram_map(dpld, &map); - mif_irq_log(ld->mc->msd, map, "ipc_write", sizeof("ipc_write")); - mif_ipc_log(MIF_IPC_AP2CP, ld->mc->msd, skb->data, skb->len); - } - -#if 1 - if (ld->aligned && memcmp16_to_io((buff + in), src, 4)) { - mif_err("%s: memcmp16_to_io fail\n", ld->name); - trigger_force_cp_crash(dpld); - } -#endif -} - -static int dpram_ipc_tx(struct dpram_link_device *dpld, int dev) -{ - struct link_device *ld = &dpld->ld; - struct sk_buff_head *txq = ld->skb_txq[dev]; - struct sk_buff *skb; - unsigned long int flags; - u32 qsize = get_tx_buff_size(dpld, dev); - u32 in; - u32 out; - int space; - int copied = 0; - - spin_lock_irqsave(&dpld->tx_lock[dev], flags); - - while (1) { - space = get_txq_space(dpld, dev, qsize, &in, &out); - if (unlikely(space < 0)) { - spin_unlock_irqrestore(&dpld->tx_lock[dev], flags); - reset_tx_circ(dpld, dev); - return space; - } - - skb = skb_dequeue(txq); - if (unlikely(!skb)) - break; - - if (unlikely(space < skb->len)) { - atomic_set(&dpld->res_required[dev], 1); - skb_queue_head(txq, skb); - spin_unlock_irqrestore(&dpld->tx_lock[dev], flags); - mif_info("%s: %s " - "qsize[%u] in[%u] out[%u] free[%u] < len[%u]\n", - ld->name, get_dev_name(dev), - qsize, in, out, space, skb->len); - return -ENOSPC; - } - - /* TX if there is enough room in the queue */ - dpram_ipc_write(dpld, dev, qsize, in, out, skb); - copied += skb->len; - dev_kfree_skb_any(skb); - } - - spin_unlock_irqrestore(&dpld->tx_lock[dev], flags); - - return copied; -} - -static int dpram_wait_for_res_ack(struct dpram_link_device *dpld, int dev) -{ - struct link_device *ld = &dpld->ld; - struct completion *cmpl = &dpld->res_ack_cmpl[dev]; - unsigned long timeout = RES_ACK_WAIT_TIMEOUT; - int ret; - u16 mask; - - mask = get_mask_req_ack(dpld, dev); - mif_info("%s: Send REQ_ACK 0x%04X\n", ld->name, mask); - send_intr(dpld, INT_NON_CMD(mask)); - - ret = wait_for_completion_interruptible_timeout(cmpl, timeout); - /* ret == 0 on timeout, ret < 0 if interrupted */ - if (ret == 0) { - mif_err("%s: %s: TIMEOUT\n", ld->name, get_dev_name(dev)); - queue_delayed_work(ld->tx_wq, ld->tx_dwork[dev], 0); - } else if (ret < 0) { - mif_err("%s: %s: interrupted (ret %d)\n", - ld->name, get_dev_name(dev), ret); - } - - return ret; -} - -static int dpram_process_res_ack(struct dpram_link_device *dpld, int dev) -{ - struct link_device *ld = &dpld->ld; - int ret; - u16 mask; - - ret = dpram_ipc_tx(dpld, dev); - if (ret < 0) { - if (ret == -ENOSPC) { - /* dpld->res_required[dev] is set in dpram_ipc_tx() */ - queue_delayed_work(ld->tx_wq, ld->tx_dwork[dev], 0); - } else { - mif_err("%s: ERR! ipc_tx fail (%d)\n", ld->name, ret); - } - } else { - if (ret > 0) { - mask = get_mask_send(dpld, dev); - send_intr(dpld, INT_NON_CMD(mask)); - mif_debug("%s: send intr 0x%04X\n", ld->name, mask); - } - atomic_set(&dpld->res_required[dev], 0); - } - - return ret; -} - -static void dpram_fmt_tx_work(struct work_struct *work) -{ - struct link_device *ld; - struct dpram_link_device *dpld; - int ret; - - ld = container_of(work, struct link_device, fmt_tx_dwork.work); - dpld = to_dpram_link_device(ld); - - ret = dpram_wait_for_res_ack(dpld, IPC_FMT); - /* ret == 0 on timeout, ret < 0 if interrupted */ - if (ret <= 0) - return; - - ret = dpram_process_res_ack(dpld, IPC_FMT); -} - -static void dpram_raw_tx_work(struct work_struct *work) -{ - struct link_device *ld; - struct dpram_link_device *dpld; - int ret; - - ld = container_of(work, struct link_device, raw_tx_dwork.work); - dpld = to_dpram_link_device(ld); - - ret = dpram_wait_for_res_ack(dpld, IPC_RAW); - /* ret == 0 on timeout, ret < 0 if interrupted */ - if (ret <= 0) - return; - - ret = dpram_process_res_ack(dpld, IPC_RAW); - if (ret > 0) - mif_netif_wake(ld); -} - -static void dpram_rfs_tx_work(struct work_struct *work) -{ - struct link_device *ld; - struct dpram_link_device *dpld; - int ret; - - ld = container_of(work, struct link_device, rfs_tx_dwork.work); - dpld = to_dpram_link_device(ld); - - ret = dpram_wait_for_res_ack(dpld, IPC_RFS); - /* ret == 0 on timeout, ret < 0 if interrupted */ - if (ret <= 0) - return; - - ret = dpram_process_res_ack(dpld, IPC_RFS); -} - -static void dpram_ipc_rx_task(unsigned long data) -{ - struct dpram_link_device *dpld = (struct dpram_link_device *)data; - struct link_device *ld = &dpld->ld; - struct io_device *iod; - struct mif_rxb *rxb; - unsigned qlen; - int i; - - for (i = 0; i < ld->max_ipc_dev; i++) { - iod = dpld->iod[i]; - qlen = rxbq_size(&dpld->rxbq[i]); - while (qlen > 0) { - rxb = rxbq_get_data_rxb(&dpld->rxbq[i]); - iod->recv(iod, ld, rxb->data, rxb->len); - rxb_clear(rxb); - qlen--; - } - } -} - -/* - ret < 0 : error - ret == 0 : no data - ret > 0 : valid data -*/ -static int dpram_recv_ipc_with_rxb(struct dpram_link_device *dpld, int dev) -{ - struct link_device *ld = &dpld->ld; - struct mif_rxb *rxb; - u8 __iomem *src = get_rx_buff(dpld, dev); - u32 qsize = get_rx_buff_size(dpld, dev); - u32 in; - u32 out; - u32 rcvd; - struct mif_irq_map map; - - rcvd = get_rxq_rcvd(dpld, dev, qsize, &in, &out); - if (rcvd <= 0) - return rcvd; - - if (dev == IPC_FMT) { - set_dpram_map(dpld, &map); - mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv")); - } - - /* Allocate an rxb */ - rxb = rxbq_get_free_rxb(&dpld->rxbq[dev]); - if (!rxb) { - mif_info("%s: ERR! %s rxbq_get_free_rxb fail\n", - ld->name, get_dev_name(dev)); - return -ENOMEM; - } - - /* Read data from each DPRAM buffer */ - circ_read(rxb_put(rxb, rcvd), src, qsize, out, rcvd); - - /* Update tail (out) pointer */ - set_rx_tail(dpld, dev, in); - - return rcvd; -} - -/* - ret < 0 : error - ret == 0 : no data - ret > 0 : valid data -*/ -static int dpram_recv_ipc_with_skb(struct dpram_link_device *dpld, int dev) -{ - struct link_device *ld = &dpld->ld; - struct io_device *iod = dpld->iod[dev]; - struct sk_buff *skb; - u8 __iomem *src = get_rx_buff(dpld, dev); - u32 qsize = get_rx_buff_size(dpld, dev); - u32 in; - u32 out; - u32 rcvd; - int rest; - u8 *frm; - u8 *dst; - unsigned int len; - unsigned int pad; - unsigned int tot; - struct mif_irq_map map; - - rcvd = get_rxq_rcvd(dpld, dev, qsize, &in, &out); - if (rcvd <= 0) - return rcvd; - - if (dev == IPC_FMT) { -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - log_dpram_status(dpld, "CP2MIF"); -#endif - set_dpram_map(dpld, &map); - mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv")); - } - - rest = rcvd; - while (rest > 0) { - /* Calculate the start of an SIPC5 frame */ - frm = src + out; - - /* Check the SIPC5 frame */ - len = sipc5_check_frame_in_dev(ld, dev, frm, rest); - if (len <= 0) { -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - u32 tail = get_rx_tail(dpld, dev); - log_dpram_status(dpld, "CP2MIF"); - save_ipc_trace(dpld, dev, src, qsize, in, tail, rcvd); - save_dpram_dump(dpld); -#endif - return -EBADMSG; - } - - /* Calculate total length with padding in DPRAM */ - pad = sipc5_calc_padding_size(len); - tot = len + pad; - - /* Allocate an skb */ - skb = dev_alloc_skb(tot); - if (!skb) { - mif_err("%s: ERR! %s dev_alloc_skb fail\n", - ld->name, get_dev_name(dev)); - return -ENOMEM; - } - - /* Read data from each DPRAM buffer */ - dst = skb_put(skb, tot); - circ_read(dst, src, qsize, out, tot); - skb_trim(skb, len); -#if 1 - if (ld->aligned && memcmp16_to_io((src + out), dst, 4)) { - mif_err("%s: memcmp16_to_io fail\n", ld->name); - trigger_force_cp_crash(dpld); - } -#endif -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - if (unlikely(dev == IPC_FMT)) { - char str[MIF_MAX_STR_LEN]; - snprintf(str, MIF_MAX_STR_LEN, "%s: CP2MIF", - ld->mc->name); - pr_ipc(str, skb->data, (skb->len > 20 ? 20 : skb->len)); - } -#endif - - /* Pass the IPC frame to IOD */ - iod->recv_skb(iod, ld, skb); - - /* Calculate new 'out' pointer */ - rest -= tot; - out += tot; - if (out >= qsize) - out -= qsize; - } - - /* Update tail (out) pointer */ - set_rx_tail(dpld, dev, in); - - return rcvd; -} - -static void non_command_handler(struct dpram_link_device *dpld, u16 intr) -{ - struct link_device *ld = &dpld->ld; - int i = 0; - int ret = 0; - u16 mask = 0; - - if (!ipc_active(dpld)) - return; - - /* Read data from DPRAM */ - for (i = 0; i < ld->max_ipc_dev; i++) { - if (dpld->use_skb) - ret = dpram_recv_ipc_with_skb(dpld, i); - else - ret = dpram_recv_ipc_with_rxb(dpld, i); - if (ret < 0) - reset_rx_circ(dpld, i); - - /* Check and process REQ_ACK (at this time, in == out) */ - if (intr & get_mask_req_ack(dpld, i)) { - mif_debug("%s: send %s_RES_ACK\n", - ld->name, get_dev_name(i)); - mask |= get_mask_res_ack(dpld, i); - } - } - - if (!dpld->use_skb) { - /* Schedule soft IRQ for RX */ - tasklet_hi_schedule(&dpld->rx_tsk); - } - - if (mask) { - send_intr(dpld, INT_NON_CMD(mask)); - mif_debug("%s: send intr 0x%04X\n", ld->name, mask); - } - - if (intr && INT_MASK_RES_ACK_SET) { - if (intr && INT_MASK_RES_ACK_R) - complete_all(&dpld->res_ack_cmpl[IPC_RAW]); - else if (intr && INT_MASK_RES_ACK_F) - complete_all(&dpld->res_ack_cmpl[IPC_FMT]); - else - complete_all(&dpld->res_ack_cmpl[IPC_RFS]); - } -} - -static void handle_cp_crash(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - struct io_device *iod; - int i; - - mif_netif_stop(ld); - - for (i = 0; i < ld->max_ipc_dev; i++) { - mif_info("%s: purging %s_skb_txq\n", ld->name, get_dev_name(i)); - skb_queue_purge(ld->skb_txq[i]); - } - - iod = link_get_iod_with_format(ld, IPC_FMT); - iod->modem_state_changed(iod, STATE_CRASH_EXIT); - - iod = link_get_iod_with_format(ld, IPC_BOOT); - iod->modem_state_changed(iod, STATE_CRASH_EXIT); -} - -static void handle_no_crash_ack(unsigned long arg) -{ - struct dpram_link_device *dpld = (struct dpram_link_device *)arg; - struct link_device *ld = &dpld->ld; - - mif_err("%s: ERR! No CRASH_EXIT ACK from CP\n", ld->mc->name); - - if (!wake_lock_active(&dpld->wlock)) - wake_lock(&dpld->wlock); - - handle_cp_crash(dpld); -} - -static int trigger_force_cp_crash(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - - if (ld->mode == LINK_MODE_ULOAD) { - mif_err("%s: CP crash is already in progress\n", ld->mc->name); - return 0; - } - - disable_irq_nosync(dpld->irq); - - ld->mode = LINK_MODE_ULOAD; - mif_err("%s: called by %pf\n", ld->name, __builtin_return_address(0)); - - dpram_wake_up(dpld); -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - save_dpram_dump(dpld); -#endif - - enable_irq(dpld->irq); - - send_intr(dpld, INT_CMD(INT_CMD_CRASH_EXIT)); - - mif_add_timer(&dpld->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT, - handle_no_crash_ack, (unsigned long)dpld); - - return 0; -} - -static int dpram_init_ipc(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - int i; - - if (ld->mode == LINK_MODE_IPC && - get_magic(dpld) == DPRAM_MAGIC_CODE && - get_access(dpld) == 1) - mif_info("%s: IPC already initialized\n", ld->name); - - /* Clear pointers in every circular queue */ - for (i = 0; i < ld->max_ipc_dev; i++) { - set_tx_head(dpld, i, 0); - set_tx_tail(dpld, i, 0); - set_rx_head(dpld, i, 0); - set_rx_tail(dpld, i, 0); - } - - /* Initialize variables for efficient TX/RX processing */ - for (i = 0; i < ld->max_ipc_dev; i++) - dpld->iod[i] = link_get_iod_with_format(ld, i); - dpld->iod[IPC_RAW] = link_get_iod_with_format(ld, IPC_MULTI_RAW); - - if (dpld->iod[IPC_RAW]->recv_skb) - dpld->use_skb = true; - - for (i = 0; i < ld->max_ipc_dev; i++) { - spin_lock_init(&dpld->tx_lock[i]); - atomic_set(&dpld->res_required[i], 0); - } - - /* Enable IPC */ - atomic_set(&dpld->accessing, 0); - - set_magic(dpld, DPRAM_MAGIC_CODE); - set_access(dpld, 1); - if (get_magic(dpld) != DPRAM_MAGIC_CODE || get_access(dpld) != 1) - return -EACCES; - - ld->mode = LINK_MODE_IPC; - - if (wake_lock_active(&dpld->wlock)) - wake_unlock(&dpld->wlock); - - return 0; -} - -static void cmd_req_active_handler(struct dpram_link_device *dpld) -{ - send_intr(dpld, INT_CMD(INT_CMD_RES_ACTIVE)); -} - -static void cmd_crash_reset_handler(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - struct io_device *iod = NULL; - - ld->mode = LINK_MODE_ULOAD; - - if (!wake_lock_active(&dpld->wlock)) - wake_lock(&dpld->wlock); - - mif_err("%s: Recv 0xC7 (CRASH_RESET)\n", ld->name); - - iod = link_get_iod_with_format(ld, IPC_FMT); - iod->modem_state_changed(iod, STATE_CRASH_RESET); - - iod = link_get_iod_with_format(ld, IPC_BOOT); - iod->modem_state_changed(iod, STATE_CRASH_RESET); -} - -static void cmd_crash_exit_handler(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - - ld->mode = LINK_MODE_ULOAD; - - if (!wake_lock_active(&dpld->wlock)) - wake_lock(&dpld->wlock); - - del_timer(&dpld->crash_ack_timer); - - dpram_wake_up(dpld); -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - save_dpram_dump(dpld); -#endif - - if (dpld->ext_op && dpld->ext_op->crash_log) - dpld->ext_op->crash_log(dpld); - - mif_err("%s: Recv 0xC9 (CRASH_EXIT)\n", ld->name); - - handle_cp_crash(dpld); -} - -static void cmd_phone_start_handler(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - struct io_device *iod = NULL; - - mif_info("%s: Recv 0xC8 (CP_START)\n", ld->name); - - dpram_init_ipc(dpld); - - iod = link_get_iod_with_format(ld, IPC_FMT); - if (!iod) { - mif_info("%s: ERR! no iod\n", ld->name); - return; - } - - if (dpld->ext_op && dpld->ext_op->cp_start_handler) - dpld->ext_op->cp_start_handler(dpld); - - if (ld->mc->phone_state != STATE_ONLINE) { - mif_info("%s: phone_state: %d -> ONLINE\n", - ld->name, ld->mc->phone_state); - iod->modem_state_changed(iod, STATE_ONLINE); - } - - mif_info("%s: Send 0xC2 (INIT_END)\n", ld->name); - send_intr(dpld, INT_CMD(INT_CMD_INIT_END)); -} - -static void command_handler(struct dpram_link_device *dpld, u16 cmd) -{ - struct link_device *ld = &dpld->ld; - - switch (INT_CMD_MASK(cmd)) { - case INT_CMD_REQ_ACTIVE: - cmd_req_active_handler(dpld); - break; - - case INT_CMD_CRASH_RESET: - dpld->init_status = DPRAM_INIT_STATE_NONE; - cmd_crash_reset_handler(dpld); - break; - - case INT_CMD_CRASH_EXIT: - dpld->init_status = DPRAM_INIT_STATE_NONE; - cmd_crash_exit_handler(dpld); - break; - - case INT_CMD_PHONE_START: - dpld->init_status = DPRAM_INIT_STATE_READY; - cmd_phone_start_handler(dpld); - complete_all(&dpld->dpram_init_cmd); - break; - - case INT_CMD_NV_REBUILDING: - mif_info("%s: NV_REBUILDING\n", ld->name); - break; - - case INT_CMD_PIF_INIT_DONE: - complete_all(&dpld->modem_pif_init_done); - break; - - case INT_CMD_SILENT_NV_REBUILDING: - mif_info("%s: SILENT_NV_REBUILDING\n", ld->name); - break; - - case INT_CMD_NORMAL_PWR_OFF: - /*ToDo:*/ - /*kernel_sec_set_cp_ack()*/; - break; - - case INT_CMD_REQ_TIME_SYNC: - case INT_CMD_CP_DEEP_SLEEP: - case INT_CMD_EMER_DOWN: - break; - - default: - mif_info("%s: unknown command 0x%04X\n", ld->name, cmd); - } -} - -static void ext_command_handler(struct dpram_link_device *dpld, u16 cmd) -{ - struct link_device *ld = &dpld->ld; - u16 resp; - - switch (EXT_CMD_MASK(cmd)) { - case EXT_CMD_SET_SPEED_LOW: - if (dpld->dpctl->setup_speed) { - dpld->dpctl->setup_speed(DPRAM_SPEED_LOW); - resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_LOW); - send_intr(dpld, resp); - } - break; - - case EXT_CMD_SET_SPEED_MID: - if (dpld->dpctl->setup_speed) { - dpld->dpctl->setup_speed(DPRAM_SPEED_MID); - resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_MID); - send_intr(dpld, resp); - } - break; - - case EXT_CMD_SET_SPEED_HIGH: - if (dpld->dpctl->setup_speed) { - dpld->dpctl->setup_speed(DPRAM_SPEED_HIGH); - resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_HIGH); - send_intr(dpld, resp); - } - break; - - default: - mif_info("%s: unknown command 0x%04X\n", ld->name, cmd); - break; - } -} - -static void udl_command_handler(struct dpram_link_device *dpld, u16 cmd) -{ - struct link_device *ld = &dpld->ld; - - if (cmd & UDL_RESULT_FAIL) { - mif_info("%s: ERR! Command failed: %04x\n", ld->name, cmd); - return; - } - - switch (UDL_CMD_MASK(cmd)) { - case UDL_CMD_RECV_READY: - mif_debug("%s: Send CP-->AP RECEIVE_READY\n", ld->name); - send_intr(dpld, CMD_IMG_START_REQ); - break; - default: - complete_all(&dpld->udl_cmd_complete); - } -} - -static inline void dpram_ipc_rx(struct dpram_link_device *dpld, u16 intr) -{ - if (unlikely(INT_CMD_VALID(intr))) - command_handler(dpld, intr); - else - non_command_handler(dpld, intr); -} - -static inline void dpram_intr_handler(struct dpram_link_device *dpld, u16 intr) -{ - char *name = dpld->ld.name; - - if (unlikely(intr == INT_POWERSAFE_FAIL)) { - mif_info("%s: intr == INT_POWERSAFE_FAIL\n", name); - return; - } - - if (unlikely(EXT_UDL_CMD(intr))) { - if (likely(EXT_INT_VALID(intr))) { - if (UDL_CMD_VALID(intr)) - udl_command_handler(dpld, intr); - else if (EXT_CMD_VALID(intr)) - ext_command_handler(dpld, intr); - else - mif_info("%s: ERR! invalid intr 0x%04X\n", - name, intr); - } else { - mif_info("%s: ERR! invalid intr 0x%04X\n", name, intr); - } - return; - } - - if (likely(INT_VALID(intr))) - dpram_ipc_rx(dpld, intr); - else - mif_info("%s: ERR! invalid intr 0x%04X\n", name, intr); -} - -static irqreturn_t ap_idpram_irq_handler(int irq, void *data) -{ - struct dpram_link_device *dpld = (struct dpram_link_device *)data; - struct link_device *ld = (struct link_device *)&dpld->ld; - u16 int2ap = recv_intr(dpld); - - if (unlikely(ld->mode == LINK_MODE_OFFLINE)) - return IRQ_HANDLED; - - dpram_intr_handler(dpld, int2ap); - - return IRQ_HANDLED; -} - -static irqreturn_t cp_idpram_irq_handler(int irq, void *data) -{ - struct dpram_link_device *dpld = (struct dpram_link_device *)data; - struct link_device *ld = (struct link_device *)&dpld->ld; - u16 int2ap; - - if (unlikely(ld->mode == LINK_MODE_OFFLINE)) - return IRQ_HANDLED; - - if (dpram_wake_up(dpld) < 0) { - trigger_force_cp_crash(dpld); - return IRQ_HANDLED; - } - - int2ap = recv_intr(dpld); - - dpram_intr_handler(dpld, int2ap); - - clear_intr(dpld); - - dpram_allow_sleep(dpld); - - return IRQ_HANDLED; -} - -static irqreturn_t ext_dpram_irq_handler(int irq, void *data) -{ - struct dpram_link_device *dpld = (struct dpram_link_device *)data; - struct link_device *ld = (struct link_device *)&dpld->ld; - u16 int2ap = recv_intr(dpld); - - if (unlikely(ld->mode == LINK_MODE_OFFLINE)) - return IRQ_HANDLED; - - dpram_intr_handler(dpld, int2ap); - - return IRQ_HANDLED; -} - -static void dpram_send_ipc(struct link_device *ld, int dev, - struct io_device *iod, struct sk_buff *skb) -{ - struct dpram_link_device *dpld = to_dpram_link_device(ld); - struct sk_buff_head *txq = ld->skb_txq[dev]; - int ret; - u16 mask; - - if (unlikely(txq->qlen >= MAX_SKB_TXQ_DEPTH)) { - mif_err("%s: %s txq->qlen %d >= %d\n", ld->name, - get_dev_name(dev), txq->qlen, MAX_SKB_TXQ_DEPTH); - if (iod->io_typ == IODEV_NET || iod->format == IPC_MULTI_RAW) { - dev_kfree_skb_any(skb); - return; - } - } - - skb_queue_tail(txq, skb); - - if (dpram_wake_up(dpld) < 0) { - trigger_force_cp_crash(dpld); - return; - } - - if (!ipc_active(dpld)) { - mif_info("%s: IPC is NOT active\n", ld->name); - goto exit; - } - - if (atomic_read(&dpld->res_required[dev]) > 0) { - mif_info("%s: %s_TXQ is full\n", ld->name, get_dev_name(dev)); - goto exit; - } - - ret = dpram_ipc_tx(dpld, dev); - if (ret > 0) { - mask = get_mask_send(dpld, dev); - send_intr(dpld, INT_NON_CMD(mask)); - } else if (ret == -ENOSPC) { - /* - ** dpld->res_required[dev] is set in dpram_ipc_tx() - */ - if (dev == IPC_RAW) - mif_netif_stop(ld); - queue_delayed_work(ld->tx_wq, ld->tx_dwork[dev], 0); - } else { - mif_info("%s: dpram_ipc_tx fail (err %d)\n", ld->name, ret); - } - -exit: - dpram_allow_sleep(dpld); -} - -static int dpram_send_cp_binary(struct link_device *ld, struct sk_buff *skb) -{ - struct dpram_link_device *dpld = to_dpram_link_device(ld); - - if (dpld->ext_op && dpld->ext_op->download_binary) - return dpld->ext_op->download_binary(dpld, skb); - else - return -ENODEV; -} - -static int dpram_send(struct link_device *ld, struct io_device *iod, - struct sk_buff *skb) -{ - enum dev_format dev = iod->format; - int len = skb->len; - - switch (dev) { - case IPC_FMT: - case IPC_RAW: - case IPC_RFS: - if (likely(ld->mode == LINK_MODE_IPC)) { - dpram_send_ipc(ld, dev, iod, skb); - } else { - mif_info("%s: ld->mode != LINK_MODE_IPC\n", ld->name); - dev_kfree_skb_any(skb); - } - return len; - - case IPC_BOOT: - return dpram_send_cp_binary(ld, skb); - - default: - mif_info("%s: ERR! no TXQ for %s\n", ld->name, iod->name); - dev_kfree_skb_any(skb); - return -ENODEV; - } -} - -static int dpram_force_dump(struct link_device *ld, struct io_device *iod) -{ - struct dpram_link_device *dpld = to_dpram_link_device(ld); - trigger_force_cp_crash(dpld); - return 0; -} - -static int dpram_dump_start(struct link_device *ld, struct io_device *iod) -{ - struct dpram_link_device *dpld = to_dpram_link_device(ld); - - if (dpld->ext_op && dpld->ext_op->dump_start) - return dpld->ext_op->dump_start(dpld); - else - return -ENODEV; -} - -static int dpram_dump_update(struct link_device *ld, struct io_device *iod, - unsigned long arg) -{ - struct dpram_link_device *dpld = to_dpram_link_device(ld); - - if (dpld->ext_op && dpld->ext_op->dump_update) - return dpld->ext_op->dump_update(dpld, (void *)arg); - else - return -ENODEV; -} - -static int dpram_ioctl(struct link_device *ld, struct io_device *iod, - unsigned int cmd, unsigned long arg) -{ - struct dpram_link_device *dpld = to_dpram_link_device(ld); - int err = 0; - - mif_info("%s: cmd 0x%08X\n", ld->name, cmd); - - switch (cmd) { - case IOCTL_DPRAM_INIT_STATUS: - mif_debug("%s: get dpram init status\n", ld->name); - return dpld->init_status; - - default: - if (dpld->ext_ioctl) { - err = dpld->ext_ioctl(dpld, iod, cmd, arg); - } else { - mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd); - err = -EINVAL; - } - - break; - } - - return err; -} - -static void dpram_dump_memory(struct link_device *ld, char *buff) -{ - struct dpram_link_device *dpld = to_dpram_link_device(ld); - dpram_wake_up(dpld); - memcpy(buff, dpld->base, dpld->size); - dpram_allow_sleep(dpld); -} - -static void dpram_remap_std_16k_region(struct dpram_link_device *dpld) -{ - struct dpram_ipc_16k_map *dpram_map; - struct dpram_ipc_device *dev; - - dpram_map = (struct dpram_ipc_16k_map *)dpld->base; - - /* magic code and access enable fields */ - dpld->ipc_map.magic = (u16 __iomem *)&dpram_map->magic; - dpld->ipc_map.access = (u16 __iomem *)&dpram_map->access; - - /* FMT */ - dev = &dpld->ipc_map.dev[IPC_FMT]; - - strcpy(dev->name, "FMT"); - dev->id = IPC_FMT; - - dev->txq.head = (u16 __iomem *)&dpram_map->fmt_tx_head; - dev->txq.tail = (u16 __iomem *)&dpram_map->fmt_tx_tail; - dev->txq.buff = (u8 __iomem *)&dpram_map->fmt_tx_buff[0]; - dev->txq.size = DP_16K_FMT_TX_BUFF_SZ; - - dev->rxq.head = (u16 __iomem *)&dpram_map->fmt_rx_head; - dev->rxq.tail = (u16 __iomem *)&dpram_map->fmt_rx_tail; - dev->rxq.buff = (u8 __iomem *)&dpram_map->fmt_rx_buff[0]; - dev->rxq.size = DP_16K_FMT_RX_BUFF_SZ; - - dev->mask_req_ack = INT_MASK_REQ_ACK_F; - dev->mask_res_ack = INT_MASK_RES_ACK_F; - dev->mask_send = INT_MASK_SEND_F; - - /* RAW */ - dev = &dpld->ipc_map.dev[IPC_RAW]; - - strcpy(dev->name, "RAW"); - dev->id = IPC_RAW; - - dev->txq.head = (u16 __iomem *)&dpram_map->raw_tx_head; - dev->txq.tail = (u16 __iomem *)&dpram_map->raw_tx_tail; - dev->txq.buff = (u8 __iomem *)&dpram_map->raw_tx_buff[0]; - dev->txq.size = DP_16K_RAW_TX_BUFF_SZ; - - dev->rxq.head = (u16 __iomem *)&dpram_map->raw_rx_head; - dev->rxq.tail = (u16 __iomem *)&dpram_map->raw_rx_tail; - dev->rxq.buff = (u8 __iomem *)&dpram_map->raw_rx_buff[0]; - dev->rxq.size = DP_16K_RAW_RX_BUFF_SZ; - - dev->mask_req_ack = INT_MASK_REQ_ACK_R; - dev->mask_res_ack = INT_MASK_RES_ACK_R; - dev->mask_send = INT_MASK_SEND_R; - - /* interrupt ports */ - dpld->ipc_map.mbx_cp2ap = (u16 __iomem *)&dpram_map->mbx_cp2ap; - dpld->ipc_map.mbx_ap2cp = (u16 __iomem *)&dpram_map->mbx_ap2cp; -} - -static int dpram_table_init(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - u8 __iomem *dp_base; - int i; - - if (!dpld->base) { - mif_info("%s: ERR! dpld->base == NULL\n", ld->name); - return -EINVAL; - } - dp_base = dpld->base; - - /* Map for booting */ - if (dpld->ext_op && dpld->ext_op->init_boot_map) { - dpld->ext_op->init_boot_map(dpld); - } else { - dpld->bt_map.magic = (u32 *)(dp_base); - dpld->bt_map.buff = (u8 *)(dp_base + DP_BOOT_BUFF_OFFSET); - dpld->bt_map.size = dpld->size - 8; - } - - /* Map for download (FOTA, UDL, etc.) */ - if (dpld->ext_op && dpld->ext_op->init_dl_map) { - dpld->ext_op->init_dl_map(dpld); - } else { - dpld->dl_map.magic = (u32 *)(dp_base); - dpld->dl_map.buff = (u8 *)(dp_base + DP_DLOAD_BUFF_OFFSET); - } - - /* Map for upload mode */ - if (dpld->ext_op && dpld->ext_op->init_ul_map) { - dpld->ext_op->init_ul_map(dpld); - } else { - dpld->ul_map.magic = (u32 *)(dp_base); - dpld->ul_map.buff = (u8 *)(dp_base + DP_ULOAD_BUFF_OFFSET); - } - - /* Map for IPC */ - if (dpld->ext_op && dpld->ext_op->init_ipc_map) { - dpld->ext_op->init_ipc_map(dpld); - } else if (dpld->dpctl->ipc_map) { - memcpy(&dpld->ipc_map, dpld->dpctl->ipc_map, - sizeof(struct dpram_ipc_map)); - } else { - if (dpld->size == DPRAM_SIZE_16KB) - dpram_remap_std_16k_region(dpld); - else - return -EINVAL; - } - - dpld->magic = dpld->ipc_map.magic; - dpld->access = dpld->ipc_map.access; - for (i = 0; i < ld->max_ipc_dev; i++) - dpld->dev[i] = &dpld->ipc_map.dev[i]; - dpld->mbx2ap = dpld->ipc_map.mbx_cp2ap; - dpld->mbx2cp = dpld->ipc_map.mbx_ap2cp; - - return 0; -} - -static void dpram_setup_common_op(struct dpram_link_device *dpld) -{ - dpld->recv_intr = recv_intr; - dpld->send_intr = send_intr; - dpld->get_magic = get_magic; - dpld->set_magic = set_magic; - dpld->get_access = get_access; - dpld->set_access = set_access; - dpld->get_tx_head = get_tx_head; - dpld->get_tx_tail = get_tx_tail; - dpld->set_tx_head = set_tx_head; - dpld->set_tx_tail = set_tx_tail; - dpld->get_tx_buff = get_tx_buff; - dpld->get_tx_buff_size = get_tx_buff_size; - dpld->get_rx_head = get_rx_head; - dpld->get_rx_tail = get_rx_tail; - dpld->set_rx_head = set_rx_head; - dpld->set_rx_tail = set_rx_tail; - dpld->get_rx_buff = get_rx_buff; - dpld->get_rx_buff_size = get_rx_buff_size; - dpld->get_mask_req_ack = get_mask_req_ack; - dpld->get_mask_res_ack = get_mask_res_ack; - dpld->get_mask_send = get_mask_send; - dpld->ipc_rx_handler = dpram_intr_handler; -} - -static int dpram_link_init(struct link_device *ld, struct io_device *iod) -{ - return 0; -} - -static void dpram_link_terminate(struct link_device *ld, struct io_device *iod) -{ - if (iod->format == IPC_FMT && ld->mode == LINK_MODE_IPC) { - if (!atomic_read(&iod->opened)) { - ld->mode = LINK_MODE_OFFLINE; - mif_err("%s: %s: link mode is changed: IPC->OFFLINE\n", - iod->name, ld->name); - } - } - - return; -} - -struct link_device *dpram_create_link_device(struct platform_device *pdev) -{ - struct dpram_link_device *dpld = NULL; - struct link_device *ld = NULL; - struct modem_data *modem = NULL; - struct modemlink_dpram_control *dpctl = NULL; - struct resource *res = NULL; - resource_size_t res_size; - unsigned long task_data; - int ret = 0; - int i = 0; - int bsize; - int qsize; - - /* - ** Alloc an instance of the DPRAM link device structure - */ - dpld = kzalloc(sizeof(struct dpram_link_device), GFP_KERNEL); - if (!dpld) { - mif_err("ERR! kzalloc dpld fail\n"); - goto err; - } - ld = &dpld->ld; - - /* - ** Get the modem (platform) data - */ - modem = (struct modem_data *)pdev->dev.platform_data; - if (!modem) { - mif_err("ERR! modem == NULL\n"); - goto err; - } - mif_info("modem = %s\n", modem->name); - mif_info("link device = %s\n", modem->link_name); - - /* - ** Retrieve modem data and DPRAM control data from the modem data - */ - ld->mdm_data = modem; - ld->name = modem->link_name; - ld->ipc_version = modem->ipc_version; - - if (!modem->dpram_ctl) { - mif_err("ERR! modem->dpram_ctl == NULL\n"); - goto err; - } - dpctl = modem->dpram_ctl; - - dpld->dpctl = dpctl; - dpld->type = dpctl->dp_type; - - if (ld->ipc_version < SIPC_VER_50) { - if (!dpctl->max_ipc_dev) { - mif_err("%s: ERR! no max_ipc_dev\n", ld->name); - goto err; - } - - ld->aligned = dpctl->aligned; - ld->max_ipc_dev = dpctl->max_ipc_dev; - } else { - ld->aligned = 1; - ld->max_ipc_dev = MAX_SIPC5_DEV; - } - - /* - ** Set attributes as a link device - */ - ld->init_comm = dpram_link_init; - ld->terminate_comm = dpram_link_terminate; - ld->send = dpram_send; - ld->force_dump = dpram_force_dump; - ld->dump_start = dpram_dump_start; - ld->dump_update = dpram_dump_update; - ld->ioctl = dpram_ioctl; - - 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; - - /* - ** Set up function pointers - */ - dpram_setup_common_op(dpld); - dpld->dpram_dump = dpram_dump_memory; - dpld->ext_op = dpram_get_ext_op(modem->modem_type); - if (dpld->ext_op && dpld->ext_op->ioctl) - dpld->ext_ioctl = dpld->ext_op->ioctl; - if (dpld->ext_op && dpld->ext_op->wakeup && dpld->ext_op->sleep) - dpld->need_wake_up = true; - if (dpld->ext_op && dpld->ext_op->clear_intr) - dpld->need_intr_clear = true; - - /* - ** Retrieve DPRAM resource - */ - if (!dpctl->dp_base) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - STR_DPRAM_BASE); - if (!res) { - mif_err("%s: ERR! no DPRAM resource\n", ld->name); - goto err; - } - res_size = resource_size(res); - - dpctl->dp_base = ioremap_nocache(res->start, res_size); - if (!dpctl->dp_base) { - mif_err("%s: ERR! ioremap_nocache for BASE fail\n", - ld->name); - goto err; - } - dpctl->dp_size = res_size; - } - dpld->base = dpctl->dp_base; - dpld->size = dpctl->dp_size; - - mif_info("%s: type %d, aligned %d, base 0x%08X, size %d\n", - ld->name, dpld->type, ld->aligned, (int)dpld->base, dpld->size); - - /* - ** Retrieve DPRAM SFR resource if exists - */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - STR_DPRAM_SFR_BASE); - if (res) { - res_size = resource_size(res); - dpld->sfr_base = ioremap_nocache(res->start, res_size); - if (!dpld->sfr_base) { - mif_err("%s: ERR! ioremap_nocache for SFR fail\n", - ld->name); - goto err; - } - } - - /* Initialize DPRAM map (physical map -> logical map) */ - ret = dpram_table_init(dpld); - if (ret < 0) { - mif_err("%s: ERR! dpram_table_init fail (err %d)\n", - ld->name, ret); - goto err; - } - - /* Disable IPC */ - set_magic(dpld, 0); - set_access(dpld, 0); - dpld->init_status = DPRAM_INIT_STATE_NONE; - - /* Initialize locks, completions, and bottom halves */ - snprintf(dpld->wlock_name, MIF_MAX_NAME_LEN, "%s_wlock", ld->name); - wake_lock_init(&dpld->wlock, WAKE_LOCK_SUSPEND, dpld->wlock_name); - - init_completion(&dpld->dpram_init_cmd); - init_completion(&dpld->modem_pif_init_done); - init_completion(&dpld->udl_start_complete); - init_completion(&dpld->udl_cmd_complete); - init_completion(&dpld->crash_start_complete); - init_completion(&dpld->crash_recv_done); - for (i = 0; i < ld->max_ipc_dev; i++) - init_completion(&dpld->res_ack_cmpl[i]); - - task_data = (unsigned long)dpld; - tasklet_init(&dpld->rx_tsk, dpram_ipc_rx_task, task_data); - - ld->tx_wq = create_singlethread_workqueue("dpram_tx_wq"); - if (!ld->tx_wq) { - mif_err("%s: ERR! fail to create tx_wq\n", ld->name); - goto err; - } - INIT_DELAYED_WORK(&ld->fmt_tx_dwork, dpram_fmt_tx_work); - INIT_DELAYED_WORK(&ld->raw_tx_dwork, dpram_raw_tx_work); - INIT_DELAYED_WORK(&ld->rfs_tx_dwork, dpram_rfs_tx_work); - ld->tx_dwork[IPC_FMT] = &ld->fmt_tx_dwork; - ld->tx_dwork[IPC_RAW] = &ld->raw_tx_dwork; - ld->tx_dwork[IPC_RFS] = &ld->rfs_tx_dwork; - -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - INIT_DELAYED_WORK(&dpld->dump_dwork, save_dpram_dump_work); - INIT_DELAYED_WORK(&dpld->trace_dwork, save_ipc_trace_work); - spin_lock_init(&dpld->dump_list.lock); - spin_lock_init(&dpld->trace_list.lock); -#endif - - /* Prepare RXB queue */ - qsize = DPRAM_MAX_RXBQ_SIZE; - for (i = 0; i < ld->max_ipc_dev; i++) { - bsize = rxbq_get_page_size(get_rx_buff_size(dpld, i)); - dpld->rxbq[i].size = qsize; - dpld->rxbq[i].in = 0; - dpld->rxbq[i].out = 0; - dpld->rxbq[i].rxb = rxbq_create_pool(bsize, qsize); - if (!dpld->rxbq[i].rxb) { - mif_err("%s: ERR! %s rxbq_create_pool fail\n", - ld->name, get_dev_name(i)); - goto err; - } - mif_info("%s: %s rxbq_pool created (bsize:%d, qsize:%d)\n", - ld->name, get_dev_name(i), bsize, qsize); - } - - /* Prepare a multi-purpose miscellaneous buffer */ - dpld->buff = kzalloc(dpld->size, GFP_KERNEL); - if (!dpld->buff) { - mif_err("%s: ERR! kzalloc dpld->buff fail\n", ld->name); - goto err; - } - - /* - ** Retrieve DPRAM IRQ GPIO#, IRQ#, and IRQ flags - */ - dpld->gpio_dpram_int = modem->gpio_dpram_int; - - if (dpctl->dpram_irq) { - dpld->irq = dpctl->dpram_irq; - } else { - dpld->irq = platform_get_irq_byname(pdev, STR_DPRAM_IRQ); - if (dpld->irq < 0) { - mif_err("%s: ERR! no DPRAM IRQ resource\n", ld->name); - goto err; - } - } - - if (dpctl->dpram_irq_flags) - dpld->irq_flags = dpctl->dpram_irq_flags; - else - dpld->irq_flags = (IRQF_NO_SUSPEND | IRQF_TRIGGER_LOW); - - /* - ** Register DPRAM interrupt handler - */ - snprintf(dpld->irq_name, MIF_MAX_NAME_LEN, "%s_irq", ld->name); - if (dpld->ext_op && dpld->ext_op->irq_handler) - dpld->irq_handler = dpld->ext_op->irq_handler; - else if (dpld->type == CP_IDPRAM) - dpld->irq_handler = cp_idpram_irq_handler; - else if (dpld->type == AP_IDPRAM) - dpld->irq_handler = ap_idpram_irq_handler; - else - dpld->irq_handler = ext_dpram_irq_handler; - - ret = register_isr(dpld->irq, dpld->irq_handler, dpld->irq_flags, - dpld->irq_name, dpld); - if (ret) - goto err; - - return ld; - -err: - if (dpld) { - if (dpld->buff) - kfree(dpld->buff); - kfree(dpld); - } - - return NULL; -} - diff --git a/drivers/misc/modem_if/modem_link_device_dpram.h b/drivers/misc/modem_if/modem_link_device_dpram.h deleted file mode 100644 index 8706fd0f339..00000000000 --- a/drivers/misc/modem_if/modem_link_device_dpram.h +++ /dev/null @@ -1,252 +0,0 @@ -/* - * 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. - * - */ -#ifndef __MODEM_LINK_DEVICE_DPRAM_H__ -#define __MODEM_LINK_DEVICE_DPRAM_H__ - -#include "modem_link_device_memory.h" - -/* - magic_code + - access_enable + - fmt_tx_head + fmt_tx_tail + fmt_tx_buff + - raw_tx_head + raw_tx_tail + raw_tx_buff + - fmt_rx_head + fmt_rx_tail + fmt_rx_buff + - raw_rx_head + raw_rx_tail + raw_rx_buff + - mbx_cp2ap + - mbx_ap2cp - = 2 + - 2 + - 2 + 2 + 1336 + - 2 + 2 + 4564 + - 2 + 2 + 1336 + - 2 + 2 + 9124 + - 2 + - 2 - = 16384 -*/ -#define DP_16K_FMT_TX_BUFF_SZ 1336 -#define DP_16K_RAW_TX_BUFF_SZ 4564 -#define DP_16K_FMT_RX_BUFF_SZ 1336 -#define DP_16K_RAW_RX_BUFF_SZ 9124 - -struct dpram_ipc_16k_map { - u16 magic; - u16 access; - - u16 fmt_tx_head; - u16 fmt_tx_tail; - u8 fmt_tx_buff[DP_16K_FMT_TX_BUFF_SZ]; - - u16 raw_tx_head; - u16 raw_tx_tail; - u8 raw_tx_buff[DP_16K_RAW_TX_BUFF_SZ]; - - u16 fmt_rx_head; - u16 fmt_rx_tail; - u8 fmt_rx_buff[DP_16K_FMT_RX_BUFF_SZ]; - - u16 raw_rx_head; - u16 raw_rx_tail; - u8 raw_rx_buff[DP_16K_RAW_RX_BUFF_SZ]; - - u16 mbx_cp2ap; - u16 mbx_ap2cp; -}; - -struct dpram_sfr { - u16 __iomem *int2cp; - u16 __iomem *int2ap; - u16 __iomem *clr_int2ap; - u16 __iomem *reset; - u16 __iomem *msg2cp; - u16 __iomem *msg2ap; -}; - -struct dpram_ext_op; - -struct dpram_link_device { - struct link_device ld; - - /* DPRAM address and size */ - enum dpram_type type; /* DPRAM type */ - u8 __iomem *base; /* Virtual address of DPRAM */ - u32 size; /* DPRAM size */ - - /* Whether or not this DPRAM can go asleep */ - bool need_wake_up; - - /* Whether or not this DPRAM needs interrupt clearing */ - bool need_intr_clear; - - /* DPRAM SFR */ - u8 __iomem *sfr_base; /* Virtual address of SFR */ - struct dpram_sfr sfr; - - /* DPRAM IRQ GPIO# */ - unsigned gpio_dpram_int; - - /* DPRAM IRQ from CP */ - int irq; - unsigned long irq_flags; - char irq_name[MIF_MAX_NAME_LEN]; - - /* Link to DPRAM control functions dependent on each platform */ - struct modemlink_dpram_control *dpctl; - - /* Physical configuration -> logical configuration */ - union { - struct dpram_boot_map bt_map; - struct qc_dpram_boot_map qc_bt_map; - }; - - struct dpram_dload_map dl_map; - struct dpram_uload_map ul_map; - - /* IPC device map */ - struct dpram_ipc_map ipc_map; - - /* Pointers (aliases) to IPC device map */ - u16 __iomem *magic; - u16 __iomem *access; - struct dpram_ipc_device *dev[MAX_IPC_DEV]; - u16 __iomem *mbx2ap; - u16 __iomem *mbx2cp; - - /* Wakelock for DPRAM device */ - struct wake_lock wlock; - char wlock_name[MIF_MAX_NAME_LEN]; - - /* For booting */ - unsigned boot_start_complete; - struct completion dpram_init_cmd; - struct completion modem_pif_init_done; - - /* For UDL */ - struct tasklet_struct ul_tsk; - struct tasklet_struct dl_tsk; - struct completion udl_start_complete; - struct completion udl_cmd_complete; - struct dpram_udl_check udl_check; - struct dpram_udl_param udl_param; - - /* For CP crash dump */ - struct timer_list crash_ack_timer; - struct completion crash_start_complete; - struct completion crash_recv_done; - struct timer_list crash_timer; - int crash_rcvd; /* Count of CP crash dump packets received */ - - /* For locking TX process */ - spinlock_t tx_lock[MAX_IPC_DEV]; - - /* For TX under DPRAM flow control */ - struct completion res_ack_cmpl[MAX_IPC_DEV]; - - /* For efficient RX process */ - struct tasklet_struct rx_tsk; - struct mif_rxb_queue rxbq[MAX_IPC_DEV]; - struct io_device *iod[MAX_IPC_DEV]; - bool use_skb; - - /* For retransmission after buffer full state */ - atomic_t res_required[MAX_IPC_DEV]; - - /* For wake-up/sleep control */ - atomic_t accessing; - - /* Multi-purpose miscellaneous buffer */ - u8 *buff; - - /* DPRAM IPC initialization status */ - int init_status; - - /* Alias to device-specific IOCTL function */ - int (*ext_ioctl)(struct dpram_link_device *dpld, struct io_device *iod, - unsigned int cmd, unsigned long arg); - - /* Alias to DPRAM IRQ handler */ - irqreturn_t (*irq_handler)(int irq, void *data); - - /* For DPRAM dump */ - u8 *dump_buff; - char dump_path[MIF_MAX_PATH_LEN]; - char trace_path[MIF_MAX_PATH_LEN]; - struct trace_queue dump_list; - struct trace_queue trace_list; - struct delayed_work dump_dwork; - struct delayed_work trace_dwork; - void (*dpram_dump)(struct link_device *ld, char *buff); - - /* Common operations for each DPRAM */ - u16 (*recv_intr)(struct dpram_link_device *dpld); - void (*send_intr)(struct dpram_link_device *dpld, u16 mask); - u16 (*get_magic)(struct dpram_link_device *dpld); - void (*set_magic)(struct dpram_link_device *dpld, u16 value); - u16 (*get_access)(struct dpram_link_device *dpld); - void (*set_access)(struct dpram_link_device *dpld, u16 value); - u32 (*get_tx_head)(struct dpram_link_device *dpld, int id); - u32 (*get_tx_tail)(struct dpram_link_device *dpld, int id); - void (*set_tx_head)(struct dpram_link_device *dpld, int id, u32 head); - void (*set_tx_tail)(struct dpram_link_device *dpld, int id, u32 tail); - u8 *(*get_tx_buff)(struct dpram_link_device *dpld, int id); - u32 (*get_tx_buff_size)(struct dpram_link_device *dpld, int id); - u32 (*get_rx_head)(struct dpram_link_device *dpld, int id); - u32 (*get_rx_tail)(struct dpram_link_device *dpld, int id); - void (*set_rx_head)(struct dpram_link_device *dpld, int id, u32 head); - void (*set_rx_tail)(struct dpram_link_device *dpld, int id, u32 tail); - u8 *(*get_rx_buff)(struct dpram_link_device *dpld, int id); - u32 (*get_rx_buff_size)(struct dpram_link_device *dpld, int id); - u16 (*get_mask_req_ack)(struct dpram_link_device *dpld, int id); - u16 (*get_mask_res_ack)(struct dpram_link_device *dpld, int id); - u16 (*get_mask_send)(struct dpram_link_device *dpld, int id); - void (*ipc_rx_handler)(struct dpram_link_device *dpld, u16 int2ap); - - /* Extended operations for various modems */ - struct dpram_ext_op *ext_op; -}; - -/* converts from struct link_device* to struct xxx_link_device* */ -#define to_dpram_link_device(linkdev) \ - container_of(linkdev, struct dpram_link_device, ld) - -struct dpram_ext_op { - int exist; - - void (*init_boot_map)(struct dpram_link_device *dpld); - void (*init_dl_map)(struct dpram_link_device *dpld); - void (*init_ul_map)(struct dpram_link_device *dpld); - void (*init_ipc_map)(struct dpram_link_device *dpld); - - int (*download_binary)(struct dpram_link_device *dpld, - struct sk_buff *skb); - - void (*cp_start_handler)(struct dpram_link_device *dpld); - - void (*crash_log)(struct dpram_link_device *dpld); - int (*dump_start)(struct dpram_link_device *dpld); - int (*dump_update)(struct dpram_link_device *dpld, void *arg); - - int (*ioctl)(struct dpram_link_device *dpld, struct io_device *iod, - unsigned int cmd, unsigned long arg); - - irqreturn_t (*irq_handler)(int irq, void *data); - void (*clear_intr)(struct dpram_link_device *dpld); - - int (*wakeup)(struct dpram_link_device *dpld); - void (*sleep)(struct dpram_link_device *dpld); -}; - -struct dpram_ext_op *dpram_get_ext_op(enum modem_t modem); - -#endif diff --git a/drivers/misc/modem_if/modem_link_device_dpram_ext_op.c b/drivers/misc/modem_if/modem_link_device_dpram_ext_op.c deleted file mode 100644 index 83f2cc302d8..00000000000 --- a/drivers/misc/modem_if/modem_link_device_dpram_ext_op.c +++ /dev/null @@ -1,1306 +0,0 @@ -/* - * 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/kallsyms.h> -#include <linux/platform_data/modem.h> - -#include "modem_prj.h" -#include "modem_link_device_dpram.h" -#include "modem_utils.h" - -#if defined(CONFIG_LTE_MODEM_CMC221) -/* -** For host (flashless) booting via DPRAM -*/ -#define CMC22x_AP_BOOT_DOWN_DONE 0x54329876 -#define CMC22x_CP_REQ_MAIN_BIN 0xA5A5A5A5 -#define CMC22x_CP_REQ_NV_DATA 0x5A5A5A5A -#define CMC22x_CP_DUMP_MAGIC 0xDEADDEAD - -#define CMC22x_HOST_DOWN_START 0x1234 -#define CMC22x_HOST_DOWN_END 0x4321 -#define CMC22x_REG_NV_DOWN_END 0xABCD -#define CMC22x_CAL_NV_DOWN_END 0xDCBA - -#define CMC22x_1ST_BUFF_READY 0xAAAA -#define CMC22x_2ND_BUFF_READY 0xBBBB -#define CMC22x_1ST_BUFF_FULL 0x1111 -#define CMC22x_2ND_BUFF_FULL 0x2222 - -#define CMC22x_CP_RECV_NV_END 0x8888 -#define CMC22x_CP_CAL_OK 0x4F4B -#define CMC22x_CP_CAL_BAD 0x4552 -#define CMC22x_CP_DUMP_END 0xFADE - -#define CMC22x_DUMP_BUFF_SIZE 8192 /* 8 KB */ -#endif - -#if defined(CONFIG_CDMA_MODEM_CBP72) -static void cbp72_init_boot_map(struct dpram_link_device *dpld) -{ - struct dpram_boot_map *bt_map = &dpld->bt_map; - - bt_map->magic = (u32 *)dpld->base; - bt_map->buff = (u8 *)(dpld->base + DP_BOOT_BUFF_OFFSET); - bt_map->size = dpld->size - 4; -} - -static void cbp72_init_dl_map(struct dpram_link_device *dpld) -{ - dpld->dl_map.magic = (u32 *)dpld->base; - dpld->dl_map.buff = (u8 *)(dpld->base + DP_DLOAD_BUFF_OFFSET); -} - -static int _cbp72_edpram_wait_resp(struct dpram_link_device *dpld, u32 resp) -{ - struct link_device *ld = &dpld->ld; - int ret; - int int2cp; - - ret = wait_for_completion_interruptible_timeout( - &dpld->udl_cmd_complete, UDL_TIMEOUT); - if (!ret) { - mif_info("%s: ERR! No UDL_CMD_RESP!!!\n", ld->name); - return -ENXIO; - } - - int2cp = dpld->recv_intr(dpld); - mif_debug("%s: int2cp = 0x%x\n", ld->name, int2cp); - if (resp == int2cp || int2cp == 0xA700) - return int2cp; - else - return -EINVAL; -} - -static int _cbp72_edpram_download_bin(struct dpram_link_device *dpld, - struct sk_buff *skb) -{ - struct link_device *ld = &dpld->ld; - struct dpram_boot_frame *bf = (struct dpram_boot_frame *)skb->data; - u8 __iomem *buff = dpld->bt_map.buff; - int err = 0; - - if (bf->len > dpld->bt_map.size) { - mif_info("%s: ERR! Out of DPRAM boundary\n", ld->name); - err = -EINVAL; - goto exit; - } - - if (bf->len) - memcpy(buff, bf->data, bf->len); - - init_completion(&dpld->udl_cmd_complete); - - if (bf->req) - dpld->send_intr(dpld, (u16)bf->req); - - if (bf->resp) { - err = _cbp72_edpram_wait_resp(dpld, bf->resp); - if (err < 0) { - mif_info("%s: ERR! wait_response fail (%d)\n", - ld->name, err); - goto exit; - } else if (err == bf->resp) { - err = skb->len; - } - } - -exit: - dev_kfree_skb_any(skb); - return err; -} - -static int cbp72_download_binary(struct dpram_link_device *dpld, - struct sk_buff *skb) -{ - if (dpld->type == EXT_DPRAM) - return _cbp72_edpram_download_bin(dpld, skb); - else - return -ENODEV; -} - -static int cbp72_dump_start(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - u8 *dest = dpld->ul_map.buff; - int ret; - - ld->mode = LINK_MODE_ULOAD; - - ret = del_timer(&dpld->crash_timer); - wake_lock(&dpld->wlock); - - iowrite32(DP_MAGIC_UMDL, dpld->ul_map.magic); - - iowrite8((u8)START_FLAG, dest + 0); - iowrite8((u8)0x1, dest + 1); - iowrite8((u8)0x1, dest + 2); - iowrite8((u8)0x0, dest + 3); - iowrite8((u8)END_FLAG, dest + 4); - - init_completion(&dpld->crash_start_complete); - - return 0; -} - -static int _cbp72_edpram_upload(struct dpram_link_device *dpld, - struct dpram_dump_arg *dump, unsigned char __user *target) -{ - struct link_device *ld = &dpld->ld; - struct ul_header header; - u8 *dest = NULL; - u8 *buff = NULL; - u16 plen = 0; - int err = 0; - int ret = 0; - int buff_size = 0; - - mif_debug("\n"); - - init_completion(&dpld->udl_cmd_complete); - - mif_debug("%s: req %x, resp %x", ld->name, dump->req, dump->resp); - - if (dump->req) - dpld->send_intr(dpld, (u16)dump->req); - - if (dump->resp) { - err = _cbp72_edpram_wait_resp(dpld, dump->resp); - if (err < 0) { - mif_info("%s: ERR! wait_response fail (%d)\n", - ld->name, err); - goto exit; - } - } - - if (dump->cmd) - return err; - - dest = (u8 *)dpld->ul_map.buff; - - header.bop = *(u8 *)(dest); - header.total_frame = *(u16 *)(dest + 1); - header.curr_frame = *(u16 *)(dest + 3); - header.len = *(u16 *)(dest + 5); - - mif_debug("%s: total frame:%d, current frame:%d, data len:%d\n", - ld->name, header.total_frame, header.curr_frame, header.len); - - plen = min_t(u16, header.len, DP_DEFAULT_DUMP_LEN); - - buff = vmalloc(DP_DEFAULT_DUMP_LEN); - if (!buff) { - err = -ENOMEM; - goto exit; - } - - memcpy(buff, dest + sizeof(struct ul_header), plen); - ret = copy_to_user(dump->buff, buff, plen); - if (ret < 0) { - mif_info("%s: ERR! dump copy_to_user fail\n", ld->name); - err = -EIO; - goto exit; - } - buff_size = plen; - - ret = copy_to_user(target + 4, &buff_size, sizeof(int)); - if (ret < 0) { - mif_info("%s: ERR! size copy_to_user fail\n", ld->name); - err = -EIO; - goto exit; - } - - vfree(buff); - return err; - -exit: - if (buff) - vfree(buff); - iowrite32(0, dpld->ul_map.magic); - wake_unlock(&dpld->wlock); - return err; -} - -static int cbp72_dump_update(struct dpram_link_device *dpld, void *arg) -{ - struct link_device *ld = &dpld->ld; - struct dpram_dump_arg dump; - int ret; - - ret = copy_from_user(&dump, (void __user *)arg, sizeof(dump)); - if (ret < 0) { - mif_info("%s: ERR! copy_from_user fail\n", ld->name); - return ret; - } - - return _cbp72_edpram_upload(dpld, &dump, (unsigned char __user *)arg); -} - -static int cbp72_set_dl_magic(struct link_device *ld, struct io_device *iod) -{ - struct dpram_link_device *dpld = to_dpram_link_device(ld); - - ld->mode = LINK_MODE_DLOAD; - - iowrite32(DP_MAGIC_DMDL, dpld->dl_map.magic); - - return 0; -} - -static int cbp72_ioctl(struct dpram_link_device *dpld, struct io_device *iod, - unsigned int cmd, unsigned long arg) -{ - struct link_device *ld = &dpld->ld; - int err = 0; - - switch (cmd) { - case IOCTL_MODEM_DL_START: - err = cbp72_set_dl_magic(ld, iod); - if (err < 0) - mif_err("%s: ERR! set_dl_magic fail\n", ld->name); - break; - - default: - mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd); - err = -EINVAL; - break; - } - - return err; -} -#endif - -#if defined(CONFIG_LTE_MODEM_CMC221) -/* For CMC221 SFR for IDPRAM */ -#define CMC_INT2CP_REG 0x10 /* Interrupt to CP */ -#define CMC_INT2AP_REG 0x50 -#define CMC_CLR_INT_REG 0x28 /* Clear Interrupt to AP */ -#define CMC_RESET_REG 0x3C -#define CMC_PUT_REG 0x40 /* AP->CP reg for hostbooting */ -#define CMC_GET_REG 0x50 /* CP->AP reg for hostbooting */ - -static void cmc221_init_boot_map(struct dpram_link_device *dpld) -{ - struct dpram_boot_map *bt_map = &dpld->bt_map; - - bt_map->buff = dpld->base; - bt_map->size = dpld->size; - bt_map->req = (u32 *)(dpld->base + DP_BOOT_REQ_OFFSET); - bt_map->resp = (u32 *)(dpld->base + DP_BOOT_RESP_OFFSET); -} - -static void cmc221_init_dl_map(struct dpram_link_device *dpld) -{ - dpld->dl_map.magic = (u32 *)dpld->base; - dpld->dl_map.buff = (u8 *)dpld->base; -} - -static void cmc221_init_ul_map(struct dpram_link_device *dpld) -{ - dpld->ul_map.magic = (u32 *)dpld->base; - dpld->ul_map.buff = (u8 *)dpld->base; -} - -static void cmc221_init_ipc_map(struct dpram_link_device *dpld) -{ - struct dpram_ipc_16k_map *dpram_map; - struct dpram_ipc_device *dev; - u8 __iomem *sfr_base = dpld->sfr_base; - - dpram_map = (struct dpram_ipc_16k_map *)dpld->base; - - /* Magic code and access enable fields */ - dpld->ipc_map.magic = (u16 __iomem *)&dpram_map->magic; - dpld->ipc_map.access = (u16 __iomem *)&dpram_map->access; - - /* FMT */ - dev = &dpld->ipc_map.dev[IPC_FMT]; - - strcpy(dev->name, "FMT"); - dev->id = IPC_FMT; - - dev->txq.head = (u16 __iomem *)&dpram_map->fmt_tx_head; - dev->txq.tail = (u16 __iomem *)&dpram_map->fmt_tx_tail; - dev->txq.buff = (u8 __iomem *)&dpram_map->fmt_tx_buff[0]; - dev->txq.size = DP_16K_FMT_TX_BUFF_SZ; - - dev->rxq.head = (u16 __iomem *)&dpram_map->fmt_rx_head; - dev->rxq.tail = (u16 __iomem *)&dpram_map->fmt_rx_tail; - dev->rxq.buff = (u8 __iomem *)&dpram_map->fmt_rx_buff[0]; - dev->rxq.size = DP_16K_FMT_RX_BUFF_SZ; - - dev->mask_req_ack = INT_MASK_REQ_ACK_F; - dev->mask_res_ack = INT_MASK_RES_ACK_F; - dev->mask_send = INT_MASK_SEND_F; - - /* RAW */ - dev = &dpld->ipc_map.dev[IPC_RAW]; - - strcpy(dev->name, "RAW"); - dev->id = IPC_RAW; - - dev->txq.head = (u16 __iomem *)&dpram_map->raw_tx_head; - dev->txq.tail = (u16 __iomem *)&dpram_map->raw_tx_tail; - dev->txq.buff = (u8 __iomem *)&dpram_map->raw_tx_buff[0]; - dev->txq.size = DP_16K_RAW_TX_BUFF_SZ; - - dev->rxq.head = (u16 __iomem *)&dpram_map->raw_rx_head; - dev->rxq.tail = (u16 __iomem *)&dpram_map->raw_rx_tail; - dev->rxq.buff = (u8 __iomem *)&dpram_map->raw_rx_buff[0]; - dev->rxq.size = DP_16K_RAW_RX_BUFF_SZ; - - dev->mask_req_ack = INT_MASK_REQ_ACK_R; - dev->mask_res_ack = INT_MASK_RES_ACK_R; - dev->mask_send = INT_MASK_SEND_R; - - /* SFR */ - dpld->sfr.int2cp = (u16 __iomem *)(sfr_base + CMC_INT2CP_REG); - dpld->sfr.int2ap = (u16 __iomem *)(sfr_base + CMC_INT2AP_REG); - dpld->sfr.clr_int2ap = (u16 __iomem *)(sfr_base + CMC_CLR_INT_REG); - dpld->sfr.reset = (u16 __iomem *)(sfr_base + CMC_RESET_REG); - dpld->sfr.msg2cp = (u16 __iomem *)(sfr_base + CMC_PUT_REG); - dpld->sfr.msg2ap = (u16 __iomem *)(sfr_base + CMC_GET_REG); - - /* Interrupt ports */ - dpld->ipc_map.mbx_cp2ap = dpld->sfr.int2ap; - dpld->ipc_map.mbx_ap2cp = dpld->sfr.int2cp; -} - -static inline void cmc221_idpram_reset(struct dpram_link_device *dpld) -{ - iowrite16(1, dpld->sfr.reset); -} - -static inline u16 cmc221_idpram_recv_msg(struct dpram_link_device *dpld) -{ - return ioread16(dpld->sfr.msg2ap); -} - -static inline void cmc221_idpram_send_msg(struct dpram_link_device *dpld, - u16 msg) -{ - iowrite16(msg, dpld->sfr.msg2cp); -} - -static int _cmc221_idpram_wait_resp(struct dpram_link_device *dpld, u32 resp) -{ - struct link_device *ld = &dpld->ld; - int count = 50000; - u32 rcvd = 0; - - if (resp == CMC22x_CP_REQ_NV_DATA) { - while (1) { - rcvd = ioread32(dpld->bt_map.resp); - if (rcvd == resp) - break; - - rcvd = cmc221_idpram_recv_msg(dpld); - if (rcvd == 0x9999) { - mif_info("%s: Invalid resp 0x%04X\n", - ld->name, rcvd); - panic("CP Crash ... BAD CRC in CP"); - } - - if (count-- < 0) { - mif_info("%s: Invalid resp 0x%08X\n", - ld->name, rcvd); - return -EAGAIN; - } - - udelay(100); - } - } else { - while (1) { - rcvd = cmc221_idpram_recv_msg(dpld); - - if (rcvd == resp) - break; - - if (resp == CMC22x_CP_RECV_NV_END && - rcvd == CMC22x_CP_CAL_BAD) { - mif_info("%s: CMC22x_CP_CAL_BAD\n", ld->name); - break; - } - - if (count-- < 0) { - mif_info("%s: Invalid resp 0x%04X\n", - ld->name, rcvd); - return -EAGAIN; - } - - udelay(100); - } - } - - return rcvd; -} - -static int _cmc221_idpram_send_boot(struct dpram_link_device *dpld, void *arg) -{ - struct link_device *ld = &dpld->ld; - u8 __iomem *bt_buff = dpld->bt_map.buff; - struct dpram_boot_img cp_img; - u8 *img_buff = NULL; - int err = 0; - int cnt = 0; - - ld->mode = LINK_MODE_BOOT; - - dpld->dpctl->setup_speed(DPRAM_SPEED_LOW); - - /* Test memory... After testing, memory is cleared. */ - if (mif_test_dpram(ld->name, bt_buff, dpld->bt_map.size) < 0) { - mif_info("%s: ERR! mif_test_dpram fail!\n", ld->name); - ld->mode = LINK_MODE_OFFLINE; - return -EIO; - } - - memset(&cp_img, 0, sizeof(struct dpram_boot_img)); - - /* Get information about the boot image */ - err = copy_from_user(&cp_img, arg, sizeof(cp_img)); - mif_info("%s: CP image addr = 0x%08X, size = %d\n", - ld->name, (int)cp_img.addr, cp_img.size); - - /* Alloc a buffer for the boot image */ - img_buff = kzalloc(dpld->bt_map.size, GFP_KERNEL); - if (!img_buff) { - mif_info("%s: ERR! kzalloc fail\n", ld->name); - ld->mode = LINK_MODE_OFFLINE; - return -ENOMEM; - } - - /* Copy boot image from the user space to the image buffer */ - err = copy_from_user(img_buff, cp_img.addr, cp_img.size); - - /* Copy boot image to DPRAM and verify it */ - memcpy(bt_buff, img_buff, cp_img.size); - if (memcmp16_to_io(bt_buff, img_buff, cp_img.size)) { - mif_info("%s: ERR! Boot may be broken!!!\n", ld->name); - goto err; - } - - cmc221_idpram_reset(dpld); - usleep_range(1000, 2000); - - if (cp_img.mode == HOST_BOOT_MODE_NORMAL) { - mif_info("%s: HOST_BOOT_MODE_NORMAL\n", ld->name); - mif_info("%s: Send req 0x%08X\n", ld->name, cp_img.req); - iowrite32(cp_img.req, dpld->bt_map.req); - - /* Wait for cp_img.resp for up to 2 seconds */ - mif_info("%s: Wait resp 0x%08X\n", ld->name, cp_img.resp); - while (ioread32(dpld->bt_map.resp) != cp_img.resp) { - cnt++; - usleep_range(1000, 2000); - - if (cnt > 1000) { - mif_info("%s: ERR! Invalid resp 0x%08X\n", - ld->name, ioread32(dpld->bt_map.resp)); - goto err; - } - } - } else { - mif_info("%s: HOST_BOOT_MODE_DUMP\n", ld->name); - } - - kfree(img_buff); - - mif_info("%s: Send BOOT done\n", ld->name); - - dpld->dpctl->setup_speed(DPRAM_SPEED_HIGH); - - return 0; - -err: - ld->mode = LINK_MODE_OFFLINE; - kfree(img_buff); - - mif_info("%s: ERR! Boot send fail!!!\n", ld->name); - return -EIO; -} - -static int cmc221_download_boot(struct dpram_link_device *dpld, void *arg) -{ - if (dpld->type == CP_IDPRAM) - return _cmc221_idpram_send_boot(dpld, arg); - else - return -ENODEV; -} - -static int _cmc221_idpram_download_bin(struct dpram_link_device *dpld, - struct sk_buff *skb) -{ - int err = 0; - int ret = 0; - struct link_device *ld = &dpld->ld; - struct dpram_boot_frame *bf = (struct dpram_boot_frame *)skb->data; - u8 __iomem *buff = (dpld->bt_map.buff + bf->offset); - - if ((bf->offset + bf->len) > dpld->bt_map.size) { - mif_info("%s: ERR! Out of DPRAM boundary\n", ld->name); - err = -EINVAL; - goto exit; - } - - if (bf->len) - memcpy(buff, bf->data, bf->len); - - if (bf->req) - cmc221_idpram_send_msg(dpld, (u16)bf->req); - - if (bf->resp) { - err = _cmc221_idpram_wait_resp(dpld, bf->resp); - if (err < 0) - mif_info("%s: ERR! wait_response fail (err %d)\n", - ld->name, err); - } - - if (bf->req == CMC22x_CAL_NV_DOWN_END) - mif_info("%s: CMC22x_CAL_NV_DOWN_END\n", ld->name); - -exit: - if (err < 0) - ret = err; - else - ret = skb->len; - - dev_kfree_skb_any(skb); - - return ret; -} - -static int cmc221_download_binary(struct dpram_link_device *dpld, - struct sk_buff *skb) -{ - if (dpld->type == CP_IDPRAM) - return _cmc221_idpram_download_bin(dpld, skb); - else - return -ENODEV; -} - -static int cmc221_dump_start(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - int ret; - - ld->mode = LINK_MODE_ULOAD; - - ret = del_timer(&dpld->crash_timer); - wake_lock(&dpld->wlock); - - dpld->crash_rcvd = 0; - iowrite32(CMC22x_CP_DUMP_MAGIC, dpld->ul_map.magic); - - init_completion(&dpld->crash_start_complete); - - return 0; -} - -static void _cmc221_idpram_wait_dump(unsigned long arg) -{ - struct dpram_link_device *dpld = (struct dpram_link_device *)arg; - u16 msg; - - msg = cmc221_idpram_recv_msg(dpld); - if (msg == CMC22x_CP_DUMP_END) { - complete_all(&dpld->crash_recv_done); - return; - } - - if (((dpld->crash_rcvd & 0x1) == 0) && (msg == CMC22x_1ST_BUFF_FULL)) { - complete_all(&dpld->crash_recv_done); - return; - } - - if (((dpld->crash_rcvd & 0x1) == 1) && (msg == CMC22x_2ND_BUFF_FULL)) { - complete_all(&dpld->crash_recv_done); - return; - } - - mif_add_timer(&dpld->crash_timer, DUMP_WAIT_TIMEOUT, - _cmc221_idpram_wait_dump, (unsigned long)dpld); -} - -static int _cmc221_idpram_upload(struct dpram_link_device *dpld, - struct dpram_dump_arg *dumparg) -{ - struct link_device *ld = &dpld->ld; - int ret; - u8 __iomem *src; - int buff_size = CMC22x_DUMP_BUFF_SIZE; - - if ((dpld->crash_rcvd & 0x1) == 0) - cmc221_idpram_send_msg(dpld, CMC22x_1ST_BUFF_READY); - else - cmc221_idpram_send_msg(dpld, CMC22x_2ND_BUFF_READY); - - init_completion(&dpld->crash_recv_done); - - mif_add_timer(&dpld->crash_timer, DUMP_WAIT_TIMEOUT, - _cmc221_idpram_wait_dump, (unsigned long)dpld); - - ret = wait_for_completion_interruptible_timeout( - &dpld->crash_recv_done, DUMP_TIMEOUT); - if (!ret) { - mif_info("%s: ERR! CP didn't send dump data!!!\n", ld->name); - goto err_out; - } - - if (cmc221_idpram_recv_msg(dpld) == CMC22x_CP_DUMP_END) { - mif_info("%s: CMC22x_CP_DUMP_END\n", ld->name); - return 0; - } - - if ((dpld->crash_rcvd & 0x1) == 0) - src = dpld->ul_map.buff; - else - src = dpld->ul_map.buff + CMC22x_DUMP_BUFF_SIZE; - - memcpy(dpld->buff, src, buff_size); - - ret = copy_to_user(dumparg->buff, dpld->buff, buff_size); - if (ret < 0) { - mif_info("%s: ERR! copy_to_user fail\n", ld->name); - goto err_out; - } - - dpld->crash_rcvd++; - return buff_size; - -err_out: - return -EIO; -} - -static int cmc221_dump_update(struct dpram_link_device *dpld, void *arg) -{ - struct link_device *ld = &dpld->ld; - struct dpram_dump_arg dump; - int ret; - - ret = copy_from_user(&dump, (void __user *)arg, sizeof(dump)); - if (ret < 0) { - mif_info("%s: ERR! copy_from_user fail\n", ld->name); - return ret; - } - - return _cmc221_idpram_upload(dpld, &dump); -} - -static int cmc221_ioctl(struct dpram_link_device *dpld, struct io_device *iod, - unsigned int cmd, unsigned long arg) -{ - struct link_device *ld = &dpld->ld; - int err = 0; - - switch (cmd) { - case IOCTL_DPRAM_SEND_BOOT: - err = cmc221_download_boot(dpld, (void *)arg); - if (err < 0) - mif_info("%s: ERR! download_boot fail\n", ld->name); - break; - - default: - mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd); - err = -EINVAL; - break; - } - - return err; -} - -static void cmc221_idpram_clr_int2ap(struct dpram_link_device *dpld) -{ - iowrite16(0xFFFF, dpld->sfr.clr_int2ap); -} - -static int cmc221_idpram_wakeup(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - struct modem_data *mdm_data = ld->mdm_data; - int cnt = 0; - - gpio_set_value(mdm_data->gpio_dpram_wakeup, 1); - - while (!gpio_get_value(mdm_data->gpio_dpram_status)) { - if (cnt++ > 10) { - if (in_irq()) - mif_err("ERR! gpio_dpram_status == 0 in IRQ\n"); - else - mif_err("ERR! gpio_dpram_status == 0\n"); - return -EACCES; - } - - mif_info("gpio_dpram_status == 0 (cnt %d)\n", cnt); - if (in_interrupt()) - udelay(1000); - else - usleep_range(1000, 2000); - } - - return 0; -} - -static void cmc221_idpram_sleep(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - gpio_set_value(ld->mdm_data->gpio_dpram_wakeup, 0); -} -#endif - -#if defined(CONFIG_CDMA_MODEM_MDM6600) || defined(CONFIG_GSM_MODEM_ESC6270) -enum qc_dload_tag { - QC_DLOAD_TAG_NONE = 0, - QC_DLOAD_TAG_BIN, - QC_DLOAD_TAG_NV, - QC_DLOAD_TAG_MAX -}; - -static void qc_dload_task(unsigned long data); - -static void qc_init_boot_map(struct dpram_link_device *dpld) -{ - struct qc_dpram_boot_map *qbt_map = &dpld->qc_bt_map; - struct modemlink_dpram_control *dpctl = dpld->dpctl; - - qbt_map->buff = dpld->base; - qbt_map->frame_size = (u16 *)(dpld->base + dpctl->boot_size_offset); - qbt_map->tag = (u16 *)(dpld->base + dpctl->boot_tag_offset); - qbt_map->count = (u16 *)(dpld->base + dpctl->boot_count_offset); - - tasklet_init(&dpld->dl_tsk, qc_dload_task, (unsigned long)dpld); -} - -static int qc_prepare_download(struct dpram_link_device *dpld) -{ - int retval = 0; - int count = 0; - - while (1) { - if (dpld->udl_check.copy_start) { - dpld->udl_check.copy_start = 0; - break; - } - - usleep_range(10000, 11000); - - count++; - if (count > 200) { - mif_err("ERR! count %d\n", count); - return -1; - } - } - - return retval; -} - -static void _qc_do_download(struct dpram_link_device *dpld, - struct dpram_udl_param *param) -{ - struct qc_dpram_boot_map *qbt_map = &dpld->qc_bt_map; - - if (param->size <= dpld->dpctl->max_boot_frame_size) { - memcpy(qbt_map->buff, param->addr, param->size); - iowrite16(param->size, qbt_map->frame_size); - iowrite16(param->tag, qbt_map->tag); - iowrite16(param->count, qbt_map->count); - dpld->send_intr(dpld, 0xDB12); - } else { - mif_info("param->size %d\n", param->size); - } -} - -static int _qc_download(struct dpram_link_device *dpld, void *arg, - enum qc_dload_tag tag) -{ - int retval = 0; - int count = 0; - int cnt_limit; - unsigned char *img; - struct dpram_udl_param param; - - retval = copy_from_user((void *)¶m, (void *)arg, sizeof(param)); - if (retval < 0) { - mif_err("ERR! copy_from_user fail\n"); - return -1; - } - - img = vmalloc(param.size); - if (!img) { - mif_err("ERR! vmalloc fail\n"); - return -1; - } - memset(img, 0, param.size); - memcpy(img, param.addr, param.size); - - dpld->udl_check.total_size = param.size; - dpld->udl_check.rest_size = param.size; - dpld->udl_check.send_size = 0; - dpld->udl_check.copy_complete = 0; - - dpld->udl_param.addr = img; - dpld->udl_param.size = dpld->dpctl->max_boot_frame_size; - if (tag == QC_DLOAD_TAG_NV) - dpld->udl_param.count = 1; - else - dpld->udl_param.count = param.count; - dpld->udl_param.tag = tag; - - if (dpld->udl_check.rest_size < dpld->dpctl->max_boot_frame_size) - dpld->udl_param.size = dpld->udl_check.rest_size; - - /* Download image (binary or NV) */ - _qc_do_download(dpld, &dpld->udl_param); - - /* Wait for completion - */ - if (tag == QC_DLOAD_TAG_NV) - cnt_limit = 200; - else - cnt_limit = 1000; - - while (1) { - if (dpld->udl_check.copy_complete) { - dpld->udl_check.copy_complete = 0; - retval = 0; - break; - } - - usleep_range(10000, 11000); - - count++; - if (count > cnt_limit) { - dpld->udl_check.total_size = 0; - dpld->udl_check.rest_size = 0; - mif_err("ERR! count %d\n", count); - retval = -1; - break; - } - } - - vfree(img); - - return retval; -} - -static int qc_download_binary(struct dpram_link_device *dpld, void *arg) -{ - return _qc_download(dpld, arg, QC_DLOAD_TAG_BIN); -} - -static int qc_download_nv(struct dpram_link_device *dpld, void *arg) -{ - return _qc_download(dpld, arg, QC_DLOAD_TAG_NV); -} - -static void qc_dload_task(unsigned long data) -{ - struct dpram_link_device *dpld = (struct dpram_link_device *)data; - - dpld->udl_check.send_size += dpld->udl_param.size; - dpld->udl_check.rest_size -= dpld->udl_param.size; - - dpld->udl_param.addr += dpld->udl_param.size; - - if (dpld->udl_check.send_size >= dpld->udl_check.total_size) { - dpld->udl_check.copy_complete = 1; - dpld->udl_param.tag = 0; - return; - } - - if (dpld->udl_check.rest_size < dpld->dpctl->max_boot_frame_size) - dpld->udl_param.size = dpld->udl_check.rest_size; - - dpld->udl_param.count += 1; - - _qc_do_download(dpld, &dpld->udl_param); -} - -static void qc_dload_cmd_handler(struct dpram_link_device *dpld, u16 cmd) -{ - switch (cmd) { - case 0x1234: - dpld->udl_check.copy_start = 1; - break; - - case 0xDBAB: - if (dpld->udl_check.total_size) - tasklet_schedule(&dpld->dl_tsk); - break; - - case 0xABCD: - dpld->udl_check.boot_complete = 1; - break; - - default: - mif_err("ERR! unknown command 0x%04X\n", cmd); - } -} - -static int qc_boot_start(struct dpram_link_device *dpld) -{ - u16 mask = 0; - int count = 0; - - /* Send interrupt -> '0x4567' */ - mask = 0x4567; - dpld->send_intr(dpld, mask); - - while (1) { - if (dpld->udl_check.boot_complete) { - dpld->udl_check.boot_complete = 0; - break; - } - - usleep_range(10000, 11000); - - count++; - if (count > 200) { - mif_err("ERR! count %d\n", count); - return -1; - } - } - - return 0; -} - -static int qc_boot_post_process(struct dpram_link_device *dpld) -{ - int count = 0; - - while (1) { - if (dpld->boot_start_complete) { - dpld->boot_start_complete = 0; - break; - } - - usleep_range(10000, 11000); - - count++; - if (count > 200) { - mif_err("ERR! count %d\n", count); - return -1; - } - } - - return 0; -} - -static void qc_start_handler(struct dpram_link_device *dpld) -{ - /* - * INT_MASK_VALID | INT_MASK_CMD | INT_MASK_CP_AIRPLANE_BOOT | - * INT_MASK_CP_AP_ANDROID | INT_MASK_CMD_INIT_END - */ - u16 mask = (0x0080 | 0x0040 | 0x1000 | 0x0100 | 0x0002); - - dpld->boot_start_complete = 1; - - /* Send INIT_END code to CP */ - mif_info("send 0x%04X (INIT_END)\n", mask); - - dpld->send_intr(dpld, mask); -} - -static void qc_crash_log(struct dpram_link_device *dpld) -{ - struct link_device *ld = &dpld->ld; - static unsigned char buf[151]; - u8 __iomem *data = NULL; - - data = dpld->get_rx_buff(dpld, IPC_FMT); - memcpy(buf, data, (sizeof(buf) - 1)); - - mif_info("PHONE ERR MSG\t| %s Crash\n", ld->mdm_data->name); - mif_info("PHONE ERR MSG\t| %s\n", buf); -} - -static int _qc_data_upload(struct dpram_link_device *dpld, - struct dpram_udl_param *param) -{ - struct qc_dpram_boot_map *qbt_map = &dpld->qc_bt_map; - int retval = 0; - u16 intval = 0; - int count = 0; - - while (1) { - if (!gpio_get_value(dpld->gpio_dpram_int)) { - intval = dpld->recv_intr(dpld); - if (intval == 0xDBAB) { - break; - } else { - mif_err("intr 0x%08x\n", intval); - return -1; - } - } - - usleep_range(1000, 2000); - - count++; - if (count > 200) { - mif_err("<%s:%d>\n", __func__, __LINE__); - return -1; - } - } - - param->size = ioread16(qbt_map->frame_size); - memcpy(param->addr, qbt_map->buff, param->size); - param->tag = ioread16(qbt_map->tag); - param->count = ioread16(qbt_map->count); - - dpld->send_intr(dpld, 0xDB12); - - return retval; -} - -static int qc_uload_step1(struct dpram_link_device *dpld) -{ - int retval = 0; - int count = 0; - u16 intval = 0; - u16 mask = 0; - - mif_info("+---------------------------------------------+\n"); - mif_info("| UPLOAD PHONE SDRAM |\n"); - mif_info("+---------------------------------------------+\n"); - - while (1) { - if (!gpio_get_value(dpld->gpio_dpram_int)) { - intval = dpld->recv_intr(dpld); - mif_info("intr 0x%04x\n", intval); - if (intval == 0x1234) { - break; - } else { - mif_info("ERR! invalid intr\n"); - return -1; - } - } - - usleep_range(1000, 2000); - - count++; - if (count > 200) { - intval = dpld->recv_intr(dpld); - mif_info("count %d, intr 0x%04x\n", count, intval); - if (intval == 0x1234) - break; - return -1; - } - } - - mask = 0xDEAD; - dpld->send_intr(dpld, mask); - - return retval; -} - -static int qc_uload_step2(struct dpram_link_device *dpld, void *arg) -{ - int retval = 0; - struct dpram_udl_param param; - - retval = copy_from_user((void *)¶m, (void *)arg, sizeof(param)); - if (retval < 0) { - mif_err("ERR! copy_from_user fail (err %d)\n", retval); - return -1; - } - - retval = _qc_data_upload(dpld, ¶m); - if (retval < 0) { - mif_err("ERR! _qc_data_upload fail (err %d)\n", retval); - return -1; - } - - if (!(param.count % 500)) - mif_info("param->count = %d\n", param.count); - - if (param.tag == 4) { - enable_irq(dpld->irq); - mif_info("param->tag = %d\n", param.tag); - } - - retval = copy_to_user((unsigned long *)arg, ¶m, sizeof(param)); - if (retval < 0) { - mif_err("ERR! copy_to_user fail (err %d)\n", retval); - return -1; - } - - return retval; -} - -static int qc_ioctl(struct dpram_link_device *dpld, struct io_device *iod, - unsigned int cmd, unsigned long arg) -{ - struct link_device *ld = &dpld->ld; - int err = 0; - - switch (cmd) { - case IOCTL_DPRAM_PHONE_POWON: - err = qc_prepare_download(dpld); - if (err < 0) - mif_info("%s: ERR! prepare_download fail\n", ld->name); - break; - - case IOCTL_DPRAM_PHONEIMG_LOAD: - err = qc_download_binary(dpld, (void *)arg); - if (err < 0) - mif_info("%s: ERR! download_binary fail\n", ld->name); - break; - - case IOCTL_DPRAM_NVDATA_LOAD: - err = qc_download_nv(dpld, (void *)arg); - if (err < 0) - mif_info("%s: ERR! download_nv fail\n", ld->name); - break; - - case IOCTL_DPRAM_PHONE_BOOTSTART: - err = qc_boot_start(dpld); - if (err < 0) { - mif_info("%s: ERR! boot_start fail\n", ld->name); - break; - } - - err = qc_boot_post_process(dpld); - if (err < 0) - mif_info("%s: ERR! boot_post_process fail\n", ld->name); - - break; - - case IOCTL_DPRAM_PHONE_UPLOAD_STEP1: - disable_irq_nosync(dpld->irq); - err = qc_uload_step1(dpld); - if (err < 0) { - enable_irq(dpld->irq); - mif_info("%s: ERR! upload_step1 fail\n", ld->name); - } - break; - - case IOCTL_DPRAM_PHONE_UPLOAD_STEP2: - err = qc_uload_step2(dpld, (void *)arg); - if (err < 0) { - enable_irq(dpld->irq); - mif_info("%s: ERR! upload_step2 fail\n", ld->name); - } - break; - - default: - mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd); - err = -EINVAL; - break; - } - - return err; -} - -static irqreturn_t qc_dpram_irq_handler(int irq, void *data) -{ - struct dpram_link_device *dpld = (struct dpram_link_device *)data; - struct link_device *ld = (struct link_device *)&dpld->ld; - u16 int2ap = 0; - - if (unlikely(ld->mode == LINK_MODE_OFFLINE)) - return IRQ_HANDLED; - - int2ap = dpld->recv_intr(dpld); - - if (int2ap == INT_POWERSAFE_FAIL) { - mif_info("%s: int2ap == INT_POWERSAFE_FAIL\n", ld->name); - goto exit; - } - - if (int2ap == 0x1234 || int2ap == 0xDBAB || int2ap == 0xABCD) { - qc_dload_cmd_handler(dpld, int2ap); - goto exit; - } - - if (likely(INT_VALID(int2ap))) - dpld->ipc_rx_handler(dpld, int2ap); - else - mif_info("%s: ERR! invalid intr 0x%04X\n", ld->name, int2ap); - -exit: - return IRQ_HANDLED; -} -#endif - -static struct dpram_ext_op ext_op_set[] = { -#ifdef CONFIG_CDMA_MODEM_CBP72 - [VIA_CBP72] = { - .exist = 1, - .init_boot_map = cbp72_init_boot_map, - .init_dl_map = cbp72_init_dl_map, - .download_binary = cbp72_download_binary, - .dump_start = cbp72_dump_start, - .dump_update = cbp72_dump_update, - .ioctl = cbp72_ioctl, - }, -#endif -#ifdef CONFIG_LTE_MODEM_CMC221 - [SEC_CMC221] = { - .exist = 1, - .init_boot_map = cmc221_init_boot_map, - .init_dl_map = cmc221_init_dl_map, - .init_ul_map = cmc221_init_ul_map, - .init_ipc_map = cmc221_init_ipc_map, - .download_binary = cmc221_download_binary, - .dump_start = cmc221_dump_start, - .dump_update = cmc221_dump_update, - .ioctl = cmc221_ioctl, - .clear_intr = cmc221_idpram_clr_int2ap, - .wakeup = cmc221_idpram_wakeup, - .sleep = cmc221_idpram_sleep, - }, -#endif -#if defined(CONFIG_CDMA_MODEM_MDM6600) - [QC_MDM6600] = { - .exist = 1, - .init_boot_map = qc_init_boot_map, - .cp_start_handler = qc_start_handler, - .crash_log = qc_crash_log, - .ioctl = qc_ioctl, - .irq_handler = qc_dpram_irq_handler, - }, -#endif -#if defined(CONFIG_GSM_MODEM_ESC6270) - [QC_ESC6270] = { - .exist = 1, - .init_boot_map = qc_init_boot_map, - .cp_start_handler = qc_start_handler, - .crash_log = qc_crash_log, - .ioctl = qc_ioctl, - .irq_handler = qc_dpram_irq_handler, - }, -#endif -}; - -struct dpram_ext_op *dpram_get_ext_op(enum modem_t modem) -{ - if (ext_op_set[modem].exist) - return &ext_op_set[modem]; - else - return NULL; -} - diff --git a/drivers/misc/modem_if/modem_link_device_hsic.c b/drivers/misc/modem_if/modem_link_device_hsic.c index dd4f749d80f..cb34b411a67 100644 --- a/drivers/misc/modem_if/modem_link_device_hsic.c +++ b/drivers/misc/modem_if/modem_link_device_hsic.c @@ -32,8 +32,9 @@ #endif #include <linux/suspend.h> #include <linux/version.h> +#include <linux/if_ether.h> -#include <linux/platform_data/modem.h> +#include "modem_tizen.h" #include "modem_prj.h" #include "modem_link_device_hsic.h" #include "modem_utils.h" @@ -48,16 +49,110 @@ static int usb_tx_urb_with_skb(struct usb_device *usbdev, struct sk_buff *skb, #define ehci_vendor_txfilltuning() #endif static void usb_rx_complete(struct urb *urb); +static void skb_rx_complete(struct urb *urb); + +int send_cg_data(struct link_device *ld, + struct io_device *iod, unsigned long arg) +{ + struct sk_buff *skb; + char data[CG_LEN] = CG_AT_CMD; + char id[] = "0"; + char tail[] = CG_AT_TAIL; + int err, ep, con_id; + struct usb_link_device *usb_ld = to_usb_link_device(ld); + struct link_pm_data *pm_data = usb_ld->link_pm_data; + struct device *dev = &usb_ld->usbdev->dev; + struct if_usb_devdata *pipe_data = &usb_ld->devdata[IF_USB_BYPASS_EP]; + + if (!usb_ld->if_usb_connected) { + mif_err("HSIC not connected\n"); + err = -ENODEV; + goto exit; + } + +retry: + if (ld->mc->phone_state != STATE_ONLINE) { + mif_err("MODEM is not online\n"); + err = -ENODEV; + goto exit; + } + + /* check usb runtime pm first */ + if (dev->power.runtime_status != RPM_ACTIVE) { + if (!pm_data->resume_requested) { + mif_debug("QW PM\n"); + INIT_COMPLETION(pm_data->active_done); + queue_delayed_work(pm_data->wq, + &pm_data->link_pm_work, 0); + } + mif_debug("Wait pm\n"); + err = wait_for_completion_timeout(&pm_data->active_done, + msecs_to_jiffies(500)); + /* timeout or -ERESTARTSYS */ + if (err <= 0) + goto retry; + } + + pm_runtime_get_sync(dev); + + /*Set ep. if (arg & 0xc) is 0x04, ep is 1, else if 0x08, ep is 2*/ + ep = ((arg & 0xc)>>2); + pipe_data = &usb_ld->devdata[ep]; + + /*make AT command */ + con_id = (arg & 0x3); + switch (con_id) { + case 0: + id[0] = '0'; + break; + case 1: + id[0] = '1'; + break; + case 2: + id[0] = '2'; + break; + default: + id[0] = '1'; + break; + } + strcat(data, id); + strcat(data, tail); + mif_info("send 'AT+CGDATA' arg=%lu, ep=%d, context=%d\n", + arg, ep, con_id); + skb = alloc_skb(32, GFP_ATOMIC); + if (unlikely(!skb)) { + pm_runtime_put(dev); + return -ENOMEM; + } + memcpy(skb_put(skb, CG_LEN), data, CG_LEN); + pr_skb("IPC-TX::CGDATA", skb); + skbpriv(skb)->iod = iod; + skbpriv(skb)->ld = ld; + + if (!usb_ld->if_usb_connected || !usb_ld->usbdev) + return -ENODEV; + + usb_mark_last_busy(usb_ld->usbdev); + err = usb_tx_urb_with_skb(usb_ld->usbdev, skb, pipe_data); + if (err < 0) { + mif_err("usb_tx_urb fail\n"); + dev_kfree_skb_any(skb); + } + + pm_runtime_put(dev); +exit: + return err; +} static int start_ipc(struct link_device *ld, struct io_device *iod) { struct sk_buff *skb; - char data[1] = {'a'}; + char data[3] = {'A', 'T', '\r'}; int err; struct usb_link_device *usb_ld = to_usb_link_device(ld); struct link_pm_data *pm_data = usb_ld->link_pm_data; struct device *dev = &usb_ld->usbdev->dev; - struct if_usb_devdata *pipe_data = &usb_ld->devdata[IF_USB_FMT_EP]; + struct if_usb_devdata *pipe_data = &usb_ld->devdata[IF_USB_BYPASS_EP]; if (!usb_ld->if_usb_connected) { mif_err("HSIC not connected, skip start ipc\n"); @@ -90,14 +185,15 @@ retry: pm_runtime_get_sync(dev); - mif_err("send 'a'\n"); + mif_err("send 'AT'\n"); skb = alloc_skb(16, GFP_ATOMIC); if (unlikely(!skb)) { pm_runtime_put(dev); return -ENOMEM; } - memcpy(skb_put(skb, 1), data, 1); + memcpy(skb_put(skb, 3), data, 3); + pr_skb("IPC-TX", skb); skbpriv(skb)->iod = iod; skbpriv(skb)->ld = ld; @@ -129,9 +225,11 @@ static int usb_init_communication(struct link_device *ld, mif_info("%d:%s\n", task->pid, get_task_comm(str, task)); +#if 0 /* Send IPC Start ASCII 'a' */ if (iod->id == 0x1) return start_ipc(ld, iod); +#endif return 0; } @@ -139,7 +237,7 @@ static int usb_init_communication(struct link_device *ld, static void usb_terminate_communication(struct link_device *ld, struct io_device *iod) { - if (iod->id != 0x1 || iod->format != IPC_FMT) + if (iod->id != 0x1 || iod->format != IPC_BYPASS) return; if (iod->mc->phone_state == STATE_CRASH_RESET || @@ -178,6 +276,39 @@ static int usb_rx_submit(struct usb_link_device *usb_ld, return ret; } +static int skb_rx_submit(struct usb_link_device *usb_ld, + struct if_usb_devdata *pipe_data, + gfp_t gfp_flags) +{ + int ret; + struct urb *urb; + struct sk_buff *skb; + + if (pipe_data->disconnected) + return -ENOENT; + + skb = alloc_skb(pipe_data->rx_buf_size, gfp_flags); + if (!skb) { + mif_err("alloc skb fail\n"); + return -ENOMEM; + } + + pipe_data->rx_skb = skb; + + urb = pipe_data->urb; + urb->transfer_flags = 0; + usb_fill_bulk_urb(urb, pipe_data->usbdev, + pipe_data->rx_pipe, (void *)skb->data, + pipe_data->rx_buf_size, skb_rx_complete, + (void *)pipe_data); + + ret = usb_submit_urb(urb, gfp_flags); + if (ret) + mif_err("submit urb fail with ret (%d)\n", ret); + + return ret; +} + static void usb_rx_retry_work(struct work_struct *work) { int ret = 0; @@ -193,29 +324,23 @@ static void usb_rx_retry_work(struct work_struct *work) if (usb_ld->usbdev) usb_mark_last_busy(usb_ld->usbdev); - switch (pipe_data->format) { - case IF_USB_FMT_EP: - if (usb_ld->if_usb_is_main) { - pr_urb("IPC-RX, retry", urb); - iod_format = IPC_FMT; - } else { - iod_format = IPC_BOOT; - } - break; - case IF_USB_RAW_EP: - iod_format = IPC_MULTI_RAW; - break; - case IF_USB_RFS_EP: - iod_format = IPC_RFS; - pr_urb("RFS-RX, retry", urb); - break; - case IF_USB_CMD_EP: - iod_format = IPC_CMD; - break; - default: - iod_format = -1; + switch (pipe_data->format) { + case IF_USB_BYPASS_EP: + if (usb_ld->if_usb_is_main) { + pr_urb("BYPASS:IPC-RX", urb); + iod_format = IPC_BYPASS; + } else { + iod_format = IPC_BOOT; + } + break; + case IF_USB_RFS_EP: + iod_format = IPC_RFS; + pr_urb("RFS-RX, retry", urb); break; - } + default: + iod_format = -1; + break; + } iod = link_get_iod_with_format(&usb_ld->ld, iod_format); if (iod) { @@ -269,38 +394,22 @@ static void usb_rx_complete(struct urb *urb) /* call iod recv */ /* how we can distinguish boot ch with fmt ch ?? */ switch (pipe_data->format) { - case IF_USB_FMT_EP: + case IF_USB_BYPASS_EP: if (usb_ld->if_usb_is_main) { pr_urb("IPC-RX", urb); - iod_format = IPC_FMT; + iod_format = IPC_BYPASS; } else { iod_format = IPC_BOOT; } break; - case IF_USB_RAW_EP: - iod_format = IPC_MULTI_RAW; - break; case IF_USB_RFS_EP: iod_format = IPC_RFS; break; - case IF_USB_CMD_EP: - iod_format = IPC_CMD; - break; default: iod_format = -1; break; } - /* flow control CMD by CP, not use io device */ - if (unlikely(iod_format == IPC_CMD)) { - ret = link_rx_flowctl_cmd(&usb_ld->ld, - (char *)urb->transfer_buffer, - urb->actual_length); - if (ret < 0) - mif_err("no multi raw device (%d)\n", ret); - goto rx_submit; - } - iod = link_get_iod_with_format(&usb_ld->ld, iod_format); if (iod) { ret = iod->recv(iod, @@ -333,6 +442,74 @@ rx_submit: } } +static void skb_rx_complete(struct urb *urb) +{ + struct if_usb_devdata *pipe_data = urb->context; + struct usb_link_device *usb_ld = pipe_data->usb_ld; + struct io_device *iod; + struct sk_buff *skb = pipe_data->rx_skb; + int iod_format; + int ret; + + + if (usb_ld->usbdev) + usb_mark_last_busy(usb_ld->usbdev); + + switch (urb->status) { + case -ENOENT: + /* case for 'link pm suspended but rx data had remained' */ + mif_info("urb->status = -ENOENT\n"); + case 0: + if (!urb->actual_length) { + mif_debug("urb has zero length!\n"); + goto rx_submit; + } + + usb_ld->link_pm_data->rx_cnt++; + /* call iod recv */ + switch (pipe_data->format) { + case IF_USB_PDP0_EP: + iod_format = IPC_PDP0; + break; + case IF_USB_PDP1_EP: + iod_format = IPC_PDP1; + break; + default: + iod_format = -1; + break; + } + + iod = link_get_iod_with_format(&usb_ld->ld, iod_format); + + skb_put(skb, urb->actual_length); + + skbpriv(skb)->iod = iod; + skbpriv(skb)->ld = &usb_ld->ld; + + if (iod) { + ret = iod->recv(iod, + &usb_ld->ld, + (char *)skb, 0); + if (ret < 0) { + mif_err("io device recv error (%d)\n", ret); + return; /* skip rx submit */ + } + } + +rx_submit: + if (urb->status == 0) { + if (usb_ld->usbdev) + usb_mark_last_busy(usb_ld->usbdev); + skb_rx_submit(usb_ld, pipe_data, GFP_ATOMIC); + } + break; + default: + mif_err("urb err status = %d\n", urb->status); + break; + } +} + + static int usb_send(struct link_device *ld, struct io_device *iod, struct sk_buff *skb) { @@ -342,7 +519,8 @@ static int usb_send(struct link_device *ld, struct io_device *iod, struct link_pm_data *pm_data = usb_ld->link_pm_data; switch (iod->format) { - case IPC_RAW: + case IPC_PDP0: + case IPC_PDP1: txq = &ld->sk_raw_tx_q; if (unlikely(ld->raw_tx_suspended)) { @@ -363,9 +541,9 @@ static int usb_send(struct link_device *ld, struct io_device *iod, mif_err("resumed done.\n"); } break; - case IPC_BOOT: - case IPC_FMT: + case IPC_BYPASS: case IPC_RFS: + case IPC_BOOT: default: txq = &ld->sk_fmt_tx_q; break; @@ -461,14 +639,20 @@ static int _usb_tx_work(struct sk_buff *skb) switch (iod->format) { case IPC_BOOT: - case IPC_FMT: - /* boot device uses same intf with fmt*/ - pipe_data = &usb_ld->devdata[IF_USB_FMT_EP]; + case IPC_BYPASS: + /* boot device uses same intf with bypass*/ + pipe_data = &usb_ld->devdata[IF_USB_BYPASS_EP]; txq = &ld->sk_fmt_tx_q; break; - case IPC_RAW: - pipe_data = &usb_ld->devdata[IF_USB_RAW_EP]; + case IPC_PDP0: + pipe_data = &usb_ld->devdata[IF_USB_PDP0_EP]; + txq = &ld->sk_raw_tx_q; + pr_skb("IPC_PDP0-TX", skb); + break; + case IPC_PDP1: + pipe_data = &usb_ld->devdata[IF_USB_PDP1_EP]; txq = &ld->sk_raw_tx_q; + pr_skb("IPC_PDP1-TX", skb); break; case IPC_RFS: pipe_data = &usb_ld->devdata[IF_USB_RFS_EP]; @@ -484,12 +668,9 @@ static int _usb_tx_work(struct sk_buff *skb) if (!pipe_data) return -ENOENT; - if (iod->format == IPC_FMT && usb_ld->if_usb_is_main) + if (iod->format == IPC_BYPASS && usb_ld->if_usb_is_main) pr_skb("IPC-TX", skb); - if (iod->format == IPC_RAW) - mif_debug("TX[RAW]\n"); - return usb_tx_urb_with_skb(usb_ld->usbdev, skb, pipe_data); } @@ -876,10 +1057,6 @@ static irqreturn_t link_pm_irq_handler(int irq, void *data) int value; struct link_pm_data *pm_data = data; -#if defined(CONFIG_SLP) - pm_wakeup_event(pm_data->miscdev.this_device, 0); -#endif - if (!pm_data->link_pm_active) return IRQ_HANDLED; @@ -1063,7 +1240,7 @@ static struct modem_ctl *if_usb_get_modemctl(struct link_pm_data *pm_data) { struct io_device *iod; - iod = link_get_iod_with_format(&pm_data->usb_ld->ld, IPC_FMT); + iod = link_get_iod_with_format(&pm_data->usb_ld->ld, IPC_BYPASS); if (!iod) { mif_err("no iodevice for modem control\n"); return NULL; @@ -1088,7 +1265,8 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) #ifdef CONFIG_HAS_WAKELOCK wake_lock_timeout(&pm_data->l2_wake, msecs_to_jiffies(50)); #else - pm_wakeup_event(pm_data->miscdev.this_device, 50); + pm_wakeup_event(pm_data->miscdev.this_device, + msecs_to_jiffies(20)); #endif /* XMM6262 Host wakeup toggle recovery */ if (!pm_data->rx_cnt && !pm_data->tx_cnt) { @@ -1113,10 +1291,28 @@ static int if_usb_resume(struct usb_interface *intf) struct link_pm_data *pm_data = devdata->usb_ld->link_pm_data; if (!devdata->disconnected && devdata->state == STATE_SUSPENDED) { - ret = usb_rx_submit(devdata->usb_ld, devdata, GFP_ATOMIC); - if (ret < 0) { - mif_err("usb_rx_submit error with (%d)\n", ret); - return ret; + switch (devdata->format) { + case IF_USB_BYPASS_EP: + case IF_USB_RFS_EP: + ret = usb_rx_submit(devdata->usb_ld, + devdata, GFP_ATOMIC); + if (ret < 0) { + mif_err("usb_rx_submit error with (%d)\n", ret); + return ret; + } + break; + case IF_USB_PDP0_EP: + case IF_USB_PDP1_EP: + ret = skb_rx_submit(devdata->usb_ld, + devdata, GFP_ATOMIC); + if (ret < 0) { + mif_err("skb_rx_submit error with (%d)\n", ret); + return ret; + } + break; + default: + mif_err("invalid format\n"); + break; } devdata->state = STATE_RESUMED; } @@ -1141,7 +1337,6 @@ static int if_usb_resume(struct usb_interface *intf) return 0; } - static int if_usb_reset_resume(struct usb_interface *intf) { int ret; @@ -1212,12 +1407,9 @@ static void if_usb_disconnect(struct usb_interface *intf) if (devdata->usb_ld->ld.com_state != COM_ONLINE) { cancel_delayed_work(&pm_data->link_reconnect_work); return; - } else { - if (pm_data->ehci_reg_dump) - pm_data->ehci_reg_dump(hdev); + } else schedule_delayed_work(&pm_data->link_reconnect_work, msecs_to_jiffies(500)); - } return; } @@ -1383,7 +1575,23 @@ static int if_usb_probe(struct usb_interface *intf, usb_set_intfdata(intf, (void *)&usb_ld->devdata[pipe]); /* rx start for this endpoint */ - usb_rx_submit(usb_ld, &usb_ld->devdata[pipe], GFP_KERNEL); + switch (pipe) { + case IF_USB_PDP0_EP: + case IF_USB_PDP1_EP: + err = skb_rx_submit(usb_ld, &usb_ld->devdata[pipe], GFP_KERNEL); + if (err < 0) { + mif_err("skb_rx_submit() failed\n"); + return err; + } + break; + default: + err = usb_rx_submit(usb_ld, &usb_ld->devdata[pipe], GFP_KERNEL); + if (err < 0) { + mif_err("usb_rx_submit() failed\n"); + return err; + } + break; + } if (info->intf_id == IPC_CHANNEL && !work_pending(&usb_ld->link_pm_data->link_pm_start.work)) { @@ -1400,10 +1608,10 @@ static int if_usb_probe(struct usb_interface *intf, } /* HSIC main comm channel has been established */ - if (pipe == IF_USB_CMD_EP) + if (pipe == IF_USB_RFS_EP) link_pm_change_modem_state(usb_ld->link_pm_data, STATE_ONLINE); - if (pipe == IF_USB_CMD_EP || info->intf_id == BOOT_DOWN) + if (pipe == IF_USB_RFS_EP || info->intf_id == BOOT_DOWN) usb_ld->if_usb_connected = 1; mif_info("successfully done\n"); @@ -1444,7 +1652,7 @@ MODULE_DEVICE_TABLE(usb, if_usb_ids); static struct usb_driver if_usb_driver = { .name = "cdc_modem", - .probe = if_usb_probe, + .probe = if_usb_probe, .disconnect = if_usb_disconnect, .id_table = if_usb_ids, .suspend = if_usb_suspend, @@ -1478,7 +1686,10 @@ static int if_usb_init(struct link_device *ld) for (i = 0; i < IF_USB_DEVNUM_MAX; i++) { pipe_data = &usb_ld->devdata[i]; pipe_data->format = i; - pipe_data->rx_buf_size = 16 * 1024; + if (i) + pipe_data->rx_buf_size = ETH_DATA_LEN; + else + pipe_data->rx_buf_size = 16 * 1024; pipe_data->rx_buf = kmalloc(pipe_data->rx_buf_size, GFP_DMA | GFP_KERNEL); @@ -1530,7 +1741,6 @@ static int usb_link_pm_init(struct usb_link_device *usb_ld, void *data) pm_data->irq_link_hostwake = gpio_to_irq(pm_data->gpio_link_hostwake); pm_data->link_ldo_enable = pm_pdata->link_ldo_enable; pm_data->link_reconnect = pm_pdata->link_reconnect; - pm_data->ehci_reg_dump = pm_pdata->ehci_reg_dump; pm_data->usb_ld = usb_ld; pm_data->link_pm_active = false; diff --git a/drivers/misc/modem_if/modem_link_device_hsic.h b/drivers/misc/modem_if/modem_link_device_hsic.h index 50a6485d8c4..58850f9c59d 100644 --- a/drivers/misc/modem_if/modem_link_device_hsic.h +++ b/drivers/misc/modem_if/modem_link_device_hsic.h @@ -19,10 +19,10 @@ enum { IF_USB_BOOT_EP = 0, - IF_USB_FMT_EP = 0, - IF_USB_RAW_EP, + IF_USB_BYPASS_EP = 0, + IF_USB_PDP0_EP, + IF_USB_PDP1_EP, IF_USB_RFS_EP, - IF_USB_CMD_EP, IF_USB_DEVNUM_MAX, }; @@ -105,8 +105,6 @@ struct link_pm_data { unsigned ipc_debug_cnt; unsigned long tx_cnt; unsigned long rx_cnt; - - void (*ehci_reg_dump)(struct device *); }; struct if_usb_devdata { @@ -120,6 +118,7 @@ struct if_usb_devdata { int format; struct urb *urb; void *rx_buf; + struct sk_buff *rx_skb; unsigned int rx_buf_size; enum ch_state state; }; diff --git a/drivers/misc/modem_if/modem_link_device_memory.h b/drivers/misc/modem_if/modem_link_device_memory.h deleted file mode 100644 index 9ea01a74867..00000000000 --- a/drivers/misc/modem_if/modem_link_device_memory.h +++ /dev/null @@ -1,501 +0,0 @@ -/* - * 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. - * - */ -#ifndef __MODEM_LINK_DEVICE_MEMORY_H__ -#define __MODEM_LINK_DEVICE_MEMORY_H__ - -#include <linux/spinlock.h> -#include <linux/wakelock.h> -#include <linux/workqueue.h> -#include <linux/timer.h> -#include <linux/platform_data/modem.h> - -#include "modem_prj.h" - -#define DPRAM_MAGIC_CODE 0xAA - -/* interrupt masks.*/ -#define INT_MASK_VALID 0x0080 -#define INT_MASK_CMD 0x0040 -#define INT_VALID(x) ((x) & INT_MASK_VALID) -#define INT_CMD_VALID(x) ((x) & INT_MASK_CMD) -#define INT_NON_CMD(x) (INT_MASK_VALID | (x)) -#define INT_CMD(x) (INT_MASK_VALID | INT_MASK_CMD | (x)) - -#define EXT_UDL_MASK 0xF000 -#define EXT_UDL_CMD(x) ((x) & EXT_UDL_MASK) -#define EXT_INT_VALID_MASK 0x8000 -#define EXT_CMD_VALID_MASK 0x4000 -#define UDL_CMD_VALID_MASK 0x2000 -#define EXT_INT_VALID(x) ((x) & EXT_INT_VALID_MASK) -#define EXT_CMD_VALID(x) ((x) & EXT_CMD_VALID_MASK) -#define UDL_CMD_VALID(x) ((x) & UDL_CMD_VALID_MASK) -#define INT_EXT_CMD(x) (EXT_INT_VALID_MASK | EXT_CMD_VALID_MASK | (x)) - -#define EXT_CMD_MASK(x) ((x) & 0x0FFF) -#define EXT_CMD_SET_SPEED_LOW 0x0011 -#define EXT_CMD_SET_SPEED_MID 0x0012 -#define EXT_CMD_SET_SPEED_HIGH 0x0013 - -#define UDL_RESULT_SUCCESS 0x1 -#define UDL_RESULT_FAIL 0x2 - -#define UDL_CMD_MASK(x) (((x) >> 8) & 0xF) -#define UDL_CMD_RECV_READY 0x1 -#define UDL_CMD_DL_START_REQ 0x2 -#define UDL_CMD_DL_START_RESP 0x3 -#define UDL_CMD_IMAGE_SEND_REQ 0x4 -#define UDL_CMD_SEND_DONE_RESP 0x5 -#define UDL_CMD_SEND_DONE_REQ 0x6 -#define UDL_CMD_UPDATE_DONE 0x7 -#define UDL_CMD_STATUS_UPDATE 0x8 -#define UDL_CMD_IMAGE_SEND_RESP 0x9 -#define UDL_CMD_EFS_CLEAR_RESP 0xB -#define UDL_CMD_ALARM_BOOT_OK 0xC -#define UDL_CMD_ALARM_BOOT_FAIL 0xD - -#define CMD_IMG_START_REQ 0x9200 -#define CMD_IMG_SEND_REQ 0x9400 -#define CMD_DL_SEND_DONE_REQ 0x9600 -#define CMD_UL_RECV_RESP 0x9601 -#define CMD_UL_RECV_DONE_RESP 0x9801 - -/* special interrupt cmd indicating modem boot failure. */ -#define INT_POWERSAFE_FAIL 0xDEAD - -#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 - -#define INT_MASK_REQ_ACK_RFS 0x0400 /* Request RES_ACK_RFS */ -#define INT_MASK_RES_ACK_RFS 0x0200 /* Response of REQ_ACK_RFS */ -#define INT_MASK_SEND_RFS 0x0100 /* Indicate sending RFS data */ - -#define INT_MASK_RES_ACK_SET \ - (INT_MASK_RES_ACK_F | INT_MASK_RES_ACK_R | INT_MASK_RES_ACK_RFS) - -#define INT_MASK_SEND_SET \ - (INT_MASK_SEND_F | INT_MASK_SEND_R | INT_MASK_SEND_RFS) - -#define INT_CMD_MASK(x) ((x) & 0xF) -#define INT_CMD_INIT_START 0x1 -#define INT_CMD_INIT_END 0x2 -#define INT_CMD_REQ_ACTIVE 0x3 -#define INT_CMD_RES_ACTIVE 0x4 -#define INT_CMD_REQ_TIME_SYNC 0x5 -#define INT_CMD_CRASH_RESET 0x7 -#define INT_CMD_PHONE_START 0x8 -#define INT_CMD_ERR_DISPLAY 0x9 -#define INT_CMD_CRASH_EXIT 0x9 -#define INT_CMD_CP_DEEP_SLEEP 0xA -#define INT_CMD_NV_REBUILDING 0xB -#define INT_CMD_EMER_DOWN 0xC -#define INT_CMD_PIF_INIT_DONE 0xD -#define INT_CMD_SILENT_NV_REBUILDING 0xE -#define INT_CMD_NORMAL_PWR_OFF 0xF - -#define START_FLAG 0x7F -#define END_FLAG 0x7E - -#define DP_MAGIC_DMDL 0x4445444C -#define DP_MAGIC_UMDL 0x4445444D -#define DP_DPRAM_SIZE 0x4000 -#define DP_DEFAULT_WRITE_LEN 8168 -#define DP_DEFAULT_DUMP_LEN 16128 -#define DP_DUMP_HEADER_SIZE 7 - -#define UDL_TIMEOUT (50 * HZ) -#define UDL_SEND_TIMEOUT (200 * HZ) -#define FORCE_CRASH_ACK_TIMEOUT (5 * HZ) -#define DUMP_TIMEOUT (30 * HZ) -#define DUMP_START_TIMEOUT (100 * HZ) -#define DUMP_WAIT_TIMEOUT (HZ >> 10) /* 1/1024 second */ -#define RES_ACK_WAIT_TIMEOUT (HZ >> 8) /* 1/256 second */ - -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP -#define MAX_RETRY_CNT 1 -#else -#define MAX_RETRY_CNT 3 -#endif - -#define MAX_SKB_TXQ_DEPTH 1024 - -enum host_boot_mode { - HOST_BOOT_MODE_NORMAL, - HOST_BOOT_MODE_DUMP, -}; - -enum dpram_init_status { - DPRAM_INIT_STATE_NONE, - DPRAM_INIT_STATE_READY, -}; - -struct dpram_boot_img { - char *addr; - int size; - enum host_boot_mode mode; - unsigned req; - unsigned resp; -}; - -#define MAX_PAYLOAD_SIZE 0x2000 -struct dpram_boot_frame { - unsigned req; /* AP->CP request */ - unsigned resp; /* response expected by AP */ - ssize_t len; /* data size in the buffer */ - unsigned offset; /* offset to write into DPRAM */ - char data[MAX_PAYLOAD_SIZE]; -}; - -/* buffer type for modem image */ -struct dpram_dump_arg { - char *buff; /* pointer to the buffer */ - int buff_size; /* buffer size */ - unsigned req; /* AP->CP request */ - unsigned resp; /* CP->AP response */ - bool cmd; /* AP->CP command */ -}; - -struct dpram_boot_map { - u32 __iomem *magic; - u8 __iomem *buff; - u32 __iomem *req; - u32 __iomem *resp; - u32 size; -}; - -struct qc_dpram_boot_map { - u8 __iomem *buff; - u16 __iomem *frame_size; - u16 __iomem *tag; - u16 __iomem *count; -}; - -struct dpram_dload_map { - u32 __iomem *magic; - u8 __iomem *buff; -}; - -struct dpram_uload_map { - u32 __iomem *magic; - u8 __iomem *buff; -}; - -struct ul_header { - u8 bop; - u16 total_frame; - u16 curr_frame; - u16 len; -} __packed; - -struct dpram_udl_param { - unsigned char *addr; - unsigned int size; - unsigned int count; - unsigned int tag; -}; - -struct dpram_udl_check { - unsigned int total_size; - unsigned int rest_size; - unsigned int send_size; - unsigned int copy_start; - unsigned int copy_complete; - unsigned int boot_complete; -}; - -#define DP_BOOT_BUFF_OFFSET 4 -#define DP_DLOAD_BUFF_OFFSET 4 -#define DP_ULOAD_BUFF_OFFSET 4 -#define DP_BOOT_REQ_OFFSET 0 -#define DP_BOOT_RESP_OFFSET 8 - -static inline bool circ_valid(u32 qsize, u32 in, u32 out) -{ - if (in >= qsize) - return false; - - if (out >= qsize) - return false; - - return true; -} - -static inline int circ_get_space(int qsize, int in, int out) -{ - return (in < out) ? (out - in - 1) : (qsize + out - in - 1); -} - -static inline int circ_get_usage(int qsize, int in, int out) -{ - return (in >= out) ? (in - out) : (qsize - out + in); -} - -/** - * circ_read - * @dst: pointer to the destination buffer - * @src: pointer to the start of the circular queue - * @qsize: size of the circular queue - * @out: offset to read - * @len: length of data to be read - * - * Should be invoked after checking data length - */ -static inline void circ_read(u8 *dst, u8 *src, u32 qsize, u32 out, u32 len) -{ - unsigned len1; - - if ((out + len) <= qsize) { - /* ----- (out) (in) ----- */ - /* ----- 7f 00 00 7e ----- */ - memcpy(dst, (src + out), len); - } else { - /* (in) ----------- (out) */ - /* 00 7e ----------- 7f 00 */ - - /* 1) data start (out) ~ buffer end */ - len1 = qsize - out; - memcpy(dst, (src + out), len1); - - /* 2) buffer start ~ data end (in?) */ - memcpy((dst + len1), src, (len - len1)); - } -} - -/** - * circ_write - * @dst: pointer to the start of the circular queue - * @src: pointer to the source - * @qsize: size of the circular queue - * @in: offset to write - * @len: length of data to be written - * - * Should be invoked after checking free space - */ -static inline void circ_write(u8 *dst, u8 *src, u32 qsize, u32 in, u32 len) -{ - u32 space; - - if ((in + len) < qsize) { - /* (in) ----------- (out) */ - /* 00 7e ----------- 7f 00 */ - memcpy((dst + in), src, len); - } else { - /* ----- (out) (in) ----- */ - /* ----- 7f 00 00 7e ----- */ - - /* 1) space start (in) ~ buffer end */ - space = qsize - in; - memcpy((dst + in), src, ((len > space) ? space : len)); - - /* 2) buffer start ~ data end */ - if (len > space) - memcpy(dst, (src + space), (len - space)); - } -} - -#if 1 -#define DPRAM_MAX_RXBQ_SIZE 256 - -struct mif_rxb { - u8 *buff; - unsigned size; - - u8 *data; - unsigned len; -}; - -struct mif_rxb_queue { - int size; - int in; - int out; - struct mif_rxb *rxb; -}; - -/* -** RXB (DPRAM RX buffer) functions -*/ -static inline struct mif_rxb *rxbq_create_pool(unsigned size, int count) -{ - struct mif_rxb *rxb; - u8 *buff; - int i; - - rxb = kzalloc(sizeof(struct mif_rxb) * count, GFP_KERNEL); - if (!rxb) { - mif_info("ERR! kzalloc rxb fail\n"); - return NULL; - } - - buff = kzalloc((size * count), GFP_KERNEL|GFP_DMA); - if (!buff) { - mif_info("ERR! kzalloc buff fail\n"); - kfree(rxb); - return NULL; - } - - for (i = 0; i < count; i++) { - rxb[i].buff = buff; - rxb[i].size = size; - buff += size; - } - - return rxb; -} - -static inline unsigned rxbq_get_page_size(unsigned len) -{ - return ((len + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT; -} - -static inline bool rxbq_empty(struct mif_rxb_queue *rxbq) -{ - return (rxbq->in == rxbq->out) ? true : false; -} - -static inline int rxbq_free_size(struct mif_rxb_queue *rxbq) -{ - int in = rxbq->in; - int out = rxbq->out; - int qsize = rxbq->size; - return (in < out) ? (out - in - 1) : (qsize + out - in - 1); -} - -static inline struct mif_rxb *rxbq_get_free_rxb(struct mif_rxb_queue *rxbq) -{ - struct mif_rxb *rxb = NULL; - - if (likely(rxbq_free_size(rxbq) > 0)) { - rxb = &rxbq->rxb[rxbq->in]; - rxbq->in++; - if (rxbq->in >= rxbq->size) - rxbq->in -= rxbq->size; - rxb->data = rxb->buff; - } - - return rxb; -} - -static inline int rxbq_size(struct mif_rxb_queue *rxbq) -{ - int in = rxbq->in; - int out = rxbq->out; - int qsize = rxbq->size; - return (in >= out) ? (in - out) : (qsize - out + in); -} - -static inline struct mif_rxb *rxbq_get_data_rxb(struct mif_rxb_queue *rxbq) -{ - struct mif_rxb *rxb = NULL; - - if (likely(!rxbq_empty(rxbq))) { - rxb = &rxbq->rxb[rxbq->out]; - rxbq->out++; - if (rxbq->out >= rxbq->size) - rxbq->out -= rxbq->size; - } - - return rxb; -} - -static inline u8 *rxb_put(struct mif_rxb *rxb, unsigned len) -{ - rxb->len = len; - return rxb->data; -} - -static inline void rxb_clear(struct mif_rxb *rxb) -{ - rxb->data = NULL; - rxb->len = 0; -} -#endif - -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP -#define MAX_TRACE_SIZE 1024 - -struct trace_data { - struct timespec ts; - enum dev_format dev; - u8 *data; - int size; -}; - -struct trace_queue { - spinlock_t lock; - int in; - int out; - struct trace_data trd[MAX_TRACE_SIZE]; -}; - -static inline struct trace_data *trq_get_free_slot(struct trace_queue *trq) -{ - int in = trq->in; - int out = trq->out; - int qsize = MAX_TRACE_SIZE; - struct trace_data *trd = NULL; - unsigned long int flags; - - spin_lock_irqsave(&trq->lock, flags); - - if (circ_get_space(qsize, in, out) < 1) { - spin_unlock_irqrestore(&trq->lock, flags); - return NULL; - } - - trd = &trq->trd[in]; - - in++; - if (in == qsize) - trq->in = 0; - else - trq->in = in; - - spin_unlock_irqrestore(&trq->lock, flags); - - return trd; -} - -static inline struct trace_data *trq_get_data_slot(struct trace_queue *trq) -{ - int in = trq->in; - int out = trq->out; - int qsize = MAX_TRACE_SIZE; - struct trace_data *trd = NULL; - unsigned long int flags; - - spin_lock_irqsave(&trq->lock, flags); - - if (circ_get_usage(qsize, in, out) < 1) { - spin_unlock_irqrestore(&trq->lock, flags); - return NULL; - } - - trd = &trq->trd[out]; - - out++; - if (out == qsize) - trq->out = 0; - else - trq->out = out; - - spin_unlock_irqrestore(&trq->lock, flags); - - return trd; -} -#endif - -#endif diff --git a/drivers/misc/modem_if/modem_link_device_mipi.c b/drivers/misc/modem_if/modem_link_device_mipi.c deleted file mode 100644 index f2804e94ee1..00000000000 --- a/drivers/misc/modem_if/modem_link_device_mipi.c +++ /dev/null @@ -1,1418 +0,0 @@ -/* /linux/drivers/new_modem_if/link_dev_mipi.c - * - * Copyright (C) 2010 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/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/sched.h> -#include <linux/irq.h> -#include <linux/poll.h> -#include <linux/gpio.h> -#include <linux/if_arp.h> -#include <linux/wakelock.h> -#include <linux/semaphore.h> -#include <linux/hsi_driver_if.h> - -#include <linux/platform_data/modem.h> -#include "modem_prj.h" -#include "modem_link_device_mipi.h" -#include "modem_utils.h" - -static int mipi_hsi_init_communication(struct link_device *ld, - struct io_device *iod) -{ - struct mipi_link_device *mipi_ld = to_mipi_link_device(ld); - - switch (iod->format) { - case IPC_FMT: - return hsi_init_handshake(mipi_ld, HSI_INIT_MODE_NORMAL); - - case IPC_BOOT: - return hsi_init_handshake(mipi_ld, - HSI_INIT_MODE_FLASHLESS_BOOT); - - case IPC_RAMDUMP: - return hsi_init_handshake(mipi_ld, - HSI_INIT_MODE_CP_RAMDUMP); - - case IPC_RFS: - case IPC_RAW: - default: - return 0; - } -} - -static void mipi_hsi_terminate_communication( - struct link_device *ld, struct io_device *iod) -{ - struct mipi_link_device *mipi_ld = to_mipi_link_device(ld); - - switch (iod->format) { - case IPC_BOOT: - if (&mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].opened) - if_hsi_close_channel(&mipi_ld->hsi_channles[ - HSI_FLASHLESS_CHANNEL]); - break; - - case IPC_RAMDUMP: - if (&mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].opened) - if_hsi_close_channel(&mipi_ld->hsi_channles[ - HSI_CP_RAMDUMP_CHANNEL]); - break; - - case IPC_FMT: - case IPC_RFS: - case IPC_RAW: - default: - break; - } -} - -static int mipi_hsi_send(struct link_device *ld, struct io_device *iod, - struct sk_buff *skb) -{ - int ret; - struct mipi_link_device *mipi_ld = to_mipi_link_device(ld); - - struct sk_buff_head *txq; - - switch (iod->format) { - case IPC_RAW: - txq = &ld->sk_raw_tx_q; - break; - - case IPC_RAMDUMP: - ret = if_hsi_write(&mipi_ld->hsi_channles[ - HSI_CP_RAMDUMP_CHANNEL], - (u32 *)skb->data, skb->len); - if (ret < 0) { - mif_err("[MIPI-HSI] write fail : %d\n", ret); - dev_kfree_skb_any(skb); - return ret; - } else - mif_debug("[MIPI-HSI] write Done\n"); - dev_kfree_skb_any(skb); - return ret; - - case IPC_BOOT: - ret = if_hsi_write(&mipi_ld->hsi_channles[ - HSI_FLASHLESS_CHANNEL], - (u32 *)skb->data, skb->len); - if (ret < 0) { - mif_err("[MIPI-HSI] write fail : %d\n", ret); - dev_kfree_skb_any(skb); - return ret; - } else - mif_debug("[MIPI-HSI] write Done\n"); - dev_kfree_skb_any(skb); - return ret; - - case IPC_FMT: - case IPC_RFS: - default: - txq = &ld->sk_fmt_tx_q; - break; - } - - /* save io device */ - skbpriv(skb)->iod = iod; - /* en queue skb data */ - skb_queue_tail(txq, skb); - - queue_work(ld->tx_wq, &ld->tx_work); - return skb->len; -} - -static void mipi_hsi_tx_work(struct work_struct *work) -{ - int ret; - struct link_device *ld = container_of(work, struct link_device, - tx_work); - struct mipi_link_device *mipi_ld = to_mipi_link_device(ld); - struct io_device *iod; - struct sk_buff *fmt_skb; - struct sk_buff *raw_skb; - int send_channel = 0; - - while (ld->sk_fmt_tx_q.qlen || ld->sk_raw_tx_q.qlen) { - mif_debug("[MIPI-HSI] fmt qlen : %d, raw qlen:%d\n", - ld->sk_fmt_tx_q.qlen, ld->sk_raw_tx_q.qlen); - - fmt_skb = skb_dequeue(&ld->sk_fmt_tx_q); - if (fmt_skb) { - iod = skbpriv(fmt_skb)->iod; - - mif_debug("[MIPI-HSI] dequeue. fmt qlen : %d\n", - ld->sk_fmt_tx_q.qlen); - - if (ld->com_state != COM_ONLINE) { - mif_err("[MIPI-HSI] CP not ready\n"); - skb_queue_head(&ld->sk_fmt_tx_q, fmt_skb); - return; - } - - switch (iod->format) { - case IPC_FMT: - send_channel = HSI_FMT_CHANNEL; - break; - - case IPC_RFS: - send_channel = HSI_RFS_CHANNEL; - break; - - case IPC_BOOT: - send_channel = HSI_FLASHLESS_CHANNEL; - break; - - case IPC_RAMDUMP: - send_channel = HSI_CP_RAMDUMP_CHANNEL; - break; - - default: - break; - } - ret = if_hsi_protocol_send(mipi_ld, send_channel, - (u32 *)fmt_skb->data, fmt_skb->len); - if (ret < 0) { - /* TODO: Re Enqueue */ - mif_err("[MIPI-HSI] write fail : %d\n", ret); - } else - mif_debug("[MIPI-HSI] write Done\n"); - - dev_kfree_skb_any(fmt_skb); - } - - raw_skb = skb_dequeue(&ld->sk_raw_tx_q); - if (raw_skb) { - if (ld->com_state != COM_ONLINE) { - mif_err("[MIPI-HSI] RAW CP not ready\n"); - skb_queue_head(&ld->sk_raw_tx_q, raw_skb); - return; - } - - mif_debug("[MIPI-HSI] dequeue. raw qlen:%d\n", - ld->sk_raw_tx_q.qlen); - - ret = if_hsi_protocol_send(mipi_ld, HSI_RAW_CHANNEL, - (u32 *)raw_skb->data, raw_skb->len); - if (ret < 0) { - /* TODO: Re Enqueue */ - mif_err("[MIPI-HSI] write fail : %d\n", ret); - } else - mif_debug("[MIPI-HSI] write Done\n"); - - dev_kfree_skb_any(raw_skb); - } - } -} - -static int __devinit if_hsi_probe(struct hsi_device *dev); -static struct hsi_device_driver if_hsi_driver = { - .ctrl_mask = ANY_HSI_CONTROLLER, - .probe = if_hsi_probe, - .driver = { - .name = "if_hsi_driver" - }, -}; - -static int if_hsi_set_wakeline(struct if_hsi_channel *channel, - unsigned int state) -{ - int ret; - - spin_lock_bh(&channel->acwake_lock); - if (channel->acwake == state) { - spin_unlock_bh(&channel->acwake_lock); - return 0; - } - - ret = hsi_ioctl(channel->dev, state ? - HSI_IOCTL_ACWAKE_UP : HSI_IOCTL_ACWAKE_DOWN, NULL); - if (ret) { - mif_err("[MIPI-HSI] ACWAKE(%d) setting fail : %d\n", state, - ret); - /* duplicate operation */ - if (ret == -EPERM) - channel->acwake = state; - spin_unlock_bh(&channel->acwake_lock); - return ret; - } - - channel->acwake = state; - spin_unlock_bh(&channel->acwake_lock); - - mif_debug("[MIPI-HSI] ACWAKE_%d(%d)\n", channel->channel_id, state); - return 0; -} - -static void if_hsi_acwake_down_func(unsigned long data) -{ - int i; - struct if_hsi_channel *channel; - struct mipi_link_device *mipi_ld = (struct mipi_link_device *)data; - - mif_debug("[MIPI-HSI]\n"); - - for (i = 0; i < HSI_NUM_OF_USE_CHANNELS; i++) { - channel = &mipi_ld->hsi_channles[i]; - - if ((channel->send_step == STEP_IDLE) && - (channel->recv_step == STEP_IDLE)) { - if_hsi_set_wakeline(channel, 0); - } else { - mod_timer(&mipi_ld->hsi_acwake_down_timer, jiffies + - HSI_ACWAKE_DOWN_TIMEOUT); - mif_debug("[MIPI-HSI] mod_timer done(%d)\n", - HSI_ACWAKE_DOWN_TIMEOUT); - return; - } - } -} - -static int if_hsi_open_channel(struct if_hsi_channel *channel) -{ - int ret; - - if (channel->opened) { - mif_debug("[MIPI-HSI] channel %d is already opened\n", - channel->channel_id); - return 0; - } - - ret = hsi_open(channel->dev); - if (ret) { - mif_err("[MIPI-HSI] hsi_open fail : %d\n", ret); - return ret; - } - channel->opened = 1; - - channel->send_step = STEP_IDLE; - channel->recv_step = STEP_IDLE; - - mif_debug("[MIPI-HSI] hsi_open Done : %d\n", channel->channel_id); - return 0; -} - -static int if_hsi_close_channel(struct if_hsi_channel *channel) -{ - unsigned long int flags; - - if (!channel->opened) { - mif_debug("[MIPI-HSI] channel %d is already closed\n", - channel->channel_id); - return 0; - } - - if_hsi_set_wakeline(channel, 0); - hsi_write_cancel(channel->dev); - hsi_read_cancel(channel->dev); - - spin_lock_irqsave(&channel->tx_state_lock, flags); - channel->tx_state &= ~HSI_CHANNEL_TX_STATE_WRITING; - spin_unlock_irqrestore(&channel->tx_state_lock, flags); - spin_lock_irqsave(&channel->rx_state_lock, flags); - channel->rx_state &= ~HSI_CHANNEL_RX_STATE_READING; - spin_unlock_irqrestore(&channel->rx_state_lock, flags); - - hsi_close(channel->dev); - channel->opened = 0; - - channel->send_step = STEP_CLOSED; - channel->recv_step = STEP_CLOSED; - - mif_debug("[MIPI-HSI] hsi_close Done : %d\n", channel->channel_id); - return 0; -} - -static void mipi_hsi_start_work(struct work_struct *work) -{ - int ret; - u32 start_cmd = 0xC2; - struct mipi_link_device *mipi_ld = - container_of(work, struct mipi_link_device, - start_work.work); - - ret = if_hsi_protocol_send(mipi_ld, HSI_CMD_CHANNEL, &start_cmd, 1); - if (ret < 0) { - /* TODO: Re Enqueue */ - mif_err("[MIPI-HSI] First write fail : %d\n", ret); - } else { - mif_debug("[MIPI-HSI] First write Done : %d\n", ret); - mipi_ld->ld.com_state = COM_ONLINE; - } -} - -static int hsi_init_handshake(struct mipi_link_device *mipi_ld, int mode) -{ - int ret; - int i; - struct hst_ctx tx_config; - struct hsr_ctx rx_config; - - switch (mode) { - case HSI_INIT_MODE_NORMAL: - if (timer_pending(&mipi_ld->hsi_acwake_down_timer)) - del_timer(&mipi_ld->hsi_acwake_down_timer); - - for (i = 0; i < HSI_NUM_OF_USE_CHANNELS; i++) { - if (mipi_ld->hsi_channles[i].opened) { - hsi_write_cancel(mipi_ld->hsi_channles[i].dev); - hsi_read_cancel(mipi_ld->hsi_channles[i].dev); - } else { - ret = if_hsi_open_channel( - &mipi_ld->hsi_channles[i]); - if (ret) - return ret; - } - - hsi_ioctl(mipi_ld->hsi_channles[i].dev, - HSI_IOCTL_GET_TX, &tx_config); - tx_config.mode = 2; - tx_config.divisor = 0; /* Speed : 96MHz */ - tx_config.channels = HSI_MAX_CHANNELS; - hsi_ioctl(mipi_ld->hsi_channles[i].dev, - HSI_IOCTL_SET_TX, &tx_config); - - hsi_ioctl(mipi_ld->hsi_channles[i].dev, - HSI_IOCTL_GET_RX, &rx_config); - rx_config.mode = 2; - rx_config.divisor = 0; /* Speed : 96MHz */ - rx_config.channels = HSI_MAX_CHANNELS; - hsi_ioctl(mipi_ld->hsi_channles[i].dev, - HSI_IOCTL_SET_RX, &rx_config); - mif_debug("[MIPI-HSI] Set TX/RX MIPI-HSI\n"); - - hsi_ioctl(mipi_ld->hsi_channles[i].dev, - HSI_IOCTL_SET_ACREADY_NORMAL, NULL); - mif_debug("[MIPI-HSI] ACREADY_NORMAL\n"); - } - - if (mipi_ld->ld.com_state != COM_ONLINE) - mipi_ld->ld.com_state = COM_HANDSHAKE; - - ret = hsi_read(mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL].dev, - mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL].rx_data, - 1); - if (ret) - mif_err("[MIPI-HSI] hsi_read fail : %d\n", ret); - - if (mipi_ld->ld.com_state != COM_ONLINE) - schedule_delayed_work(&mipi_ld->start_work, 3 * HZ); - - mif_debug("[MIPI-HSI] hsi_init_handshake Done : MODE_NORMAL\n"); - return 0; - - case HSI_INIT_MODE_FLASHLESS_BOOT: - mipi_ld->ld.com_state = COM_BOOT; - - if (mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].opened) { - hsi_write_cancel(mipi_ld->hsi_channles[ - HSI_FLASHLESS_CHANNEL].dev); - hsi_read_cancel(mipi_ld->hsi_channles[ - HSI_FLASHLESS_CHANNEL].dev); - } else { - ret = if_hsi_open_channel( - &mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL]); - if (ret) - return ret; - } - - hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev, - HSI_IOCTL_GET_TX, &tx_config); - tx_config.mode = 2; - tx_config.divisor = 0; /* Speed : 96MHz */ - tx_config.channels = 1; - hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev, - HSI_IOCTL_SET_TX, &tx_config); - - hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev, - HSI_IOCTL_GET_RX, &rx_config); - rx_config.mode = 2; - rx_config.divisor = 0; /* Speed : 96MHz */ - rx_config.channels = 1; - hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev, - HSI_IOCTL_SET_RX, &rx_config); - mif_debug("[MIPI-HSI] Set TX/RX MIPI-HSI\n"); - - if (!wake_lock_active(&mipi_ld->wlock)) { - wake_lock(&mipi_ld->wlock); - mif_debug("[MIPI-HSI] wake_lock\n"); - } - - if_hsi_set_wakeline( - &mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL], 1); - - ret = hsi_read(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev, - mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].rx_data, - HSI_FLASHBOOT_ACK_LEN / 4); - if (ret) - mif_err("[MIPI-HSI] hsi_read fail : %d\n", ret); - - hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev, - HSI_IOCTL_SET_ACREADY_NORMAL, NULL); - - mif_debug("[MIPI-HSI] hsi_init_handshake Done : FLASHLESS_BOOT\n"); - return 0; - - case HSI_INIT_MODE_CP_RAMDUMP: - mipi_ld->ld.com_state = COM_CRASH; - - if (mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].opened) { - hsi_write_cancel(mipi_ld->hsi_channles[ - HSI_CP_RAMDUMP_CHANNEL].dev); - hsi_read_cancel(mipi_ld->hsi_channles[ - HSI_CP_RAMDUMP_CHANNEL].dev); - } else { - ret = if_hsi_open_channel( - &mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL]); - if (ret) - return ret; - } - - hsi_ioctl(mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev, - HSI_IOCTL_GET_TX, &tx_config); - tx_config.mode = 2; - tx_config.divisor = 0; /* Speed : 96MHz */ - tx_config.channels = 1; - hsi_ioctl(mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev, - HSI_IOCTL_SET_TX, &tx_config); - - hsi_ioctl(mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev, - HSI_IOCTL_GET_RX, &rx_config); - rx_config.mode = 2; - rx_config.divisor = 0; /* Speed : 96MHz */ - rx_config.channels = 1; - hsi_ioctl(mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev, - HSI_IOCTL_SET_RX, &rx_config); - mif_debug("[MIPI-HSI] Set TX/RX MIPI-HSI\n"); - - if (!wake_lock_active(&mipi_ld->wlock)) { - wake_lock(&mipi_ld->wlock); - mif_debug("[MIPI-HSI] wake_lock\n"); - } - - if_hsi_set_wakeline( - &mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL], 1); - - ret = hsi_read( - mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev, - mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].rx_data, - DUMP_ERR_INFO_SIZE); - if (ret) - mif_err("[MIPI-HSI] hsi_read fail : %d\n", ret); - - hsi_ioctl(mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev, - HSI_IOCTL_SET_ACREADY_NORMAL, NULL); - - mif_debug("[MIPI-HSI] hsi_init_handshake Done : RAMDUMP\n"); - return 0; - - default: - return -EINVAL; - } -} - -static u32 if_hsi_create_cmd(u32 cmd_type, int ch, void *arg) -{ - u32 cmd = 0; - unsigned int size = 0; - - switch (cmd_type) { - case HSI_LL_MSG_BREAK: - return 0; - - case HSI_LL_MSG_CONN_CLOSED: - cmd = ((HSI_LL_MSG_CONN_CLOSED & 0x0000000F) << 28) - |((ch & 0x000000FF) << 24); - return cmd; - - case HSI_LL_MSG_ACK: - size = *(unsigned int *)arg; - - cmd = ((HSI_LL_MSG_ACK & 0x0000000F) << 28) - |((ch & 0x000000FF) << 24) | ((size & 0x00FFFFFF)); - return cmd; - - case HSI_LL_MSG_NAK: - cmd = ((HSI_LL_MSG_NAK & 0x0000000F) << 28) - |((ch & 0x000000FF) << 24); - return cmd; - - case HSI_LL_MSG_OPEN_CONN_OCTET: - size = *(unsigned int *)arg; - - cmd = ((HSI_LL_MSG_OPEN_CONN_OCTET & 0x0000000F) - << 28) | ((ch & 0x000000FF) << 24) - | ((size & 0x00FFFFFF)); - return cmd; - - case HSI_LL_MSG_OPEN_CONN: - case HSI_LL_MSG_CONF_RATE: - case HSI_LL_MSG_CANCEL_CONN: - case HSI_LL_MSG_CONN_READY: - case HSI_LL_MSG_ECHO: - case HSI_LL_MSG_INFO_REQ: - case HSI_LL_MSG_INFO: - case HSI_LL_MSG_CONFIGURE: - case HSI_LL_MSG_ALLOCATE_CH: - case HSI_LL_MSG_RELEASE_CH: - case HSI_LL_MSG_INVALID: - default: - mif_err("[MIPI-HSI] ERROR... CMD Not supported : %08x\n", - cmd_type); - return -EINVAL; - } -} - -static void if_hsi_cmd_work(struct work_struct *work) -{ - int ret; - unsigned long int flags; - struct mipi_link_device *mipi_ld = - container_of(work, struct mipi_link_device, cmd_work); - struct if_hsi_channel *channel = - &mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL]; - struct if_hsi_command *hsi_cmd; - - mif_debug("[MIPI-HSI] cmd_work\n"); - - do { - spin_lock_irqsave(&mipi_ld->list_cmd_lock, flags); - if (!list_empty(&mipi_ld->list_of_hsi_cmd)) { - hsi_cmd = list_entry(mipi_ld->list_of_hsi_cmd.next, - struct if_hsi_command, list); - list_del(&hsi_cmd->list); - spin_unlock_irqrestore(&mipi_ld->list_cmd_lock, flags); - - channel->send_step = STEP_TX; - if_hsi_set_wakeline(channel, 1); - mod_timer(&mipi_ld->hsi_acwake_down_timer, jiffies + - HSI_ACWAKE_DOWN_TIMEOUT); - } else { - spin_unlock_irqrestore(&mipi_ld->list_cmd_lock, flags); - channel->send_step = STEP_IDLE; - break; - } - mif_debug("[MIPI-HSI] take command : %08x\n", hsi_cmd->command); - - ret = if_hsi_write(channel, &hsi_cmd->command, 4); - if (ret < 0) { - mif_err("[MIPI-HSI] write command fail : %d\n", ret); - if_hsi_set_wakeline(channel, 0); - channel->send_step = STEP_IDLE; - return; - } - mif_debug("[MIPI-HSI] SEND CMD : %08x\n", hsi_cmd->command); - - kfree(hsi_cmd); - } while (true); -} - -static int if_hsi_send_command(struct mipi_link_device *mipi_ld, - u32 cmd_type, int ch, u32 param) -{ - unsigned long int flags; - struct if_hsi_command *hsi_cmd; - - hsi_cmd = kmalloc(sizeof(struct if_hsi_command), GFP_ATOMIC); - if (!hsi_cmd) { - mif_err("[MIPI-HSI] hsi_cmd kmalloc fail\n"); - return -ENOMEM; - } - INIT_LIST_HEAD(&hsi_cmd->list); - - hsi_cmd->command = if_hsi_create_cmd(cmd_type, ch, ¶m); - mif_debug("[MIPI-HSI] made command : %08x\n", hsi_cmd->command); - - spin_lock_irqsave(&mipi_ld->list_cmd_lock, flags); - list_add_tail(&hsi_cmd->list, &mipi_ld->list_of_hsi_cmd); - spin_unlock_irqrestore(&mipi_ld->list_cmd_lock, flags); - - mif_debug("[MIPI-HSI] queue_work : cmd_work\n"); - queue_work(mipi_ld->mipi_wq, &mipi_ld->cmd_work); - - return 0; -} - -static int if_hsi_decode_cmd(u32 *cmd_data, u32 *cmd, u32 *ch, - u32 *param) -{ - u32 data = *cmd_data; - u8 lrc_cal, lrc_act; - u8 val1, val2, val3; - - *cmd = ((data & 0xF0000000) >> 28); - switch (*cmd) { - case HSI_LL_MSG_BREAK: - mif_err("[MIPI-HSI] Command MSG_BREAK Received\n"); - return -1; - - case HSI_LL_MSG_OPEN_CONN: - *ch = ((data & 0x0F000000) >> 24); - *param = ((data & 0x00FFFF00) >> 8); - val1 = ((data & 0xFF000000) >> 24); - val2 = ((data & 0x00FF0000) >> 16); - val3 = ((data & 0x0000FF00) >> 8); - lrc_act = (data & 0x000000FF); - lrc_cal = val1 ^ val2 ^ val3; - - if (lrc_cal != lrc_act) { - mif_err("[MIPI-HSI] CAL is broken\n"); - return -1; - } - return 0; - - case HSI_LL_MSG_CONN_READY: - case HSI_LL_MSG_CONN_CLOSED: - case HSI_LL_MSG_CANCEL_CONN: - case HSI_LL_MSG_NAK: - *ch = ((data & 0x0F000000) >> 24); - return 0; - - case HSI_LL_MSG_ACK: - *ch = ((data & 0x0F000000) >> 24); - *param = (data & 0x00FFFFFF); - return 0; - - case HSI_LL_MSG_CONF_RATE: - *ch = ((data & 0x0F000000) >> 24); - *param = ((data & 0x0F000000) >> 24); - return 0; - - case HSI_LL_MSG_OPEN_CONN_OCTET: - *ch = ((data & 0x0F000000) >> 24); - *param = (data & 0x00FFFFFF); - return 0; - - case HSI_LL_MSG_ECHO: - case HSI_LL_MSG_INFO_REQ: - case HSI_LL_MSG_INFO: - case HSI_LL_MSG_CONFIGURE: - case HSI_LL_MSG_ALLOCATE_CH: - case HSI_LL_MSG_RELEASE_CH: - case HSI_LL_MSG_INVALID: - default: - mif_err("[MIPI-HSI] Invalid command received : %08x\n", *cmd); - *cmd = HSI_LL_MSG_INVALID; - *ch = HSI_LL_INVALID_CHANNEL; - return -1; - } - return 0; -} - -static int if_hsi_rx_cmd_handle(struct mipi_link_device *mipi_ld, u32 cmd, - u32 ch, u32 param) -{ - int ret; - struct if_hsi_channel *channel = &mipi_ld->hsi_channles[ch]; - - mif_debug("[MIPI-HSI] if_hsi_rx_cmd_handle cmd=0x%x, ch=%d, param=%d\n", - cmd, ch, param); - - switch (cmd) { - case HSI_LL_MSG_OPEN_CONN_OCTET: - switch (channel->recv_step) { - case STEP_IDLE: - channel->recv_step = STEP_TO_ACK; - - if (!wake_lock_active(&mipi_ld->wlock)) { - wake_lock(&mipi_ld->wlock); - mif_debug("[MIPI-HSI] wake_lock\n"); - } - - if_hsi_set_wakeline(channel, 1); - mod_timer(&mipi_ld->hsi_acwake_down_timer, jiffies + - HSI_ACWAKE_DOWN_TIMEOUT); - mif_debug("[MIPI-HSI] mod_timer done(%d)\n", - HSI_ACWAKE_DOWN_TIMEOUT); - - ret = if_hsi_send_command(mipi_ld, HSI_LL_MSG_ACK, ch, - param); - if (ret) { - mif_err("[MIPI-HSI] if_hsi_send_command fail : %d\n", - ret); - return ret; - } - - channel->packet_size = param; - channel->recv_step = STEP_RX; - if (param % 4) - param += (4 - (param % 4)); - channel->rx_count = param; - ret = hsi_read(channel->dev, channel->rx_data, - channel->rx_count / 4); - if (ret) { - mif_err("[MIPI-HSI] hsi_read fail : %d\n", ret); - return ret; - } - return 0; - - case STEP_NOT_READY: - ret = if_hsi_send_command(mipi_ld, HSI_LL_MSG_NAK, ch, - param); - if (ret) { - mif_err("[MIPI-HSI] if_hsi_send_command fail : %d\n", - ret); - return ret; - } - return 0; - - default: - mif_err("[MIPI-HSI] wrong state : %08x, recv_step : %d\n", - cmd, channel->recv_step); - return -1; - } - - case HSI_LL_MSG_ACK: - case HSI_LL_MSG_NAK: - switch (channel->send_step) { - case STEP_WAIT_FOR_ACK: - case STEP_SEND_OPEN_CONN: - if (cmd == HSI_LL_MSG_ACK) { - channel->send_step = STEP_TX; - channel->got_nack = 0; - mif_debug("[MIPI-HSI] got ack\n"); - } else { - channel->send_step = STEP_WAIT_FOR_ACK; - channel->got_nack = 1; - mif_debug("[MIPI-HSI] got nack\n"); - } - - up(&channel->ack_done_sem); - return 0; - - default: - mif_err("[MIPI-HSI] wrong state : %08x\n", cmd); - return -1; - } - - case HSI_LL_MSG_CONN_CLOSED: - switch (channel->send_step) { - case STEP_TX: - case STEP_WAIT_FOR_CONN_CLOSED: - mif_debug("[MIPI-HSI] got close\n"); - - channel->send_step = STEP_IDLE; - up(&channel->close_conn_done_sem); - return 0; - - default: - mif_err("[MIPI-HSI] wrong state : %08x\n", cmd); - return -1; - } - - case HSI_LL_MSG_OPEN_CONN: - case HSI_LL_MSG_ECHO: - case HSI_LL_MSG_CANCEL_CONN: - case HSI_LL_MSG_CONF_RATE: - default: - mif_err("[MIPI-HSI] ERROR... CMD Not supported : %08x\n", cmd); - return -EINVAL; - } -} - -static int if_hsi_protocol_send(struct mipi_link_device *mipi_ld, int ch, - u32 *data, unsigned int len) -{ - int ret; - int retry_count = 0; - int ack_timeout_cnt = 0; - struct io_device *iod; - struct if_hsi_channel *channel = &mipi_ld->hsi_channles[ch]; - - if (channel->send_step != STEP_IDLE) { - mif_err("[MIPI-HSI] send step is not IDLE : %d\n", - channel->send_step); - return -EBUSY; - } - channel->send_step = STEP_SEND_OPEN_CONN; - - if (!wake_lock_active(&mipi_ld->wlock)) { - wake_lock(&mipi_ld->wlock); - mif_debug("[MIPI-HSI] wake_lock\n"); - } - - if_hsi_set_wakeline(channel, 1); - mod_timer(&mipi_ld->hsi_acwake_down_timer, jiffies + - HSI_ACWAKE_DOWN_TIMEOUT); - mif_debug("[MIPI-HSI] mod_timer done(%d)\n", - HSI_ACWAKE_DOWN_TIMEOUT); - -retry_send: - - ret = if_hsi_send_command(mipi_ld, HSI_LL_MSG_OPEN_CONN_OCTET, ch, - len); - if (ret) { - mif_err("[MIPI-HSI] if_hsi_send_command fail : %d\n", ret); - if_hsi_set_wakeline(channel, 0); - channel->send_step = STEP_IDLE; - return -1; - } - - channel->send_step = STEP_WAIT_FOR_ACK; - - if (down_timeout(&channel->ack_done_sem, HSI_ACK_DONE_TIMEOUT) < 0) { - mif_err("[MIPI-HSI] ch=%d, ack_done timeout\n", - channel->channel_id); - - if_hsi_set_wakeline(channel, 0); - - if (mipi_ld->ld.com_state == COM_ONLINE) { - ack_timeout_cnt++; - if (ack_timeout_cnt < 10) { - if_hsi_set_wakeline(channel, 1); - mif_err("[MIPI-HSI] ch=%d, retry send open. cnt : %d\n", - channel->channel_id, ack_timeout_cnt); - goto retry_send; - } - - /* try to recover cp */ - iod = link_get_iod_with_format(&mipi_ld->ld, IPC_FMT); - if (iod) - iod->modem_state_changed(iod, - STATE_CRASH_RESET); - } - - channel->send_step = STEP_IDLE; - return -ETIMEDOUT; - } - mif_debug("[MIPI-HSI] ch=%d, got ack_done=%d\n", channel->channel_id, - channel->got_nack); - - if (channel->got_nack && (retry_count < 10)) { - mif_debug("[MIPI-HSI] ch=%d, got nack=%d retry=%d\n", - channel->channel_id, channel->got_nack, - retry_count); - retry_count++; - msleep_interruptible(1); - goto retry_send; - } - retry_count = 0; - - channel->send_step = STEP_TX; - - ret = if_hsi_write(channel, data, len); - if (ret < 0) { - mif_err("[MIPI-HSI] if_hsi_write fail : %d\n", ret); - if_hsi_set_wakeline(channel, 0); - channel->send_step = STEP_IDLE; - return ret; - } - mif_debug("[MIPI-HSI] SEND DATA : %08x(%d)\n", *data, len); - - mif_debug("%08x %08x %08x %08x %08x %08x %08x %08x\n", - *channel->tx_data, *(channel->tx_data + 1), - *(channel->tx_data + 2), *(channel->tx_data + 3), - *(channel->tx_data + 4), *(channel->tx_data + 5), - *(channel->tx_data + 6), *(channel->tx_data + 7)); - - channel->send_step = STEP_WAIT_FOR_CONN_CLOSED; - if (down_timeout(&channel->close_conn_done_sem, - HSI_CLOSE_CONN_DONE_TIMEOUT) < 0) { - mif_err("[MIPI-HSI] ch=%d, close conn timeout\n", - channel->channel_id); - if_hsi_set_wakeline(channel, 0); - channel->send_step = STEP_IDLE; - return -ETIMEDOUT; - } - mif_debug("[MIPI-HSI] ch=%d, got close_conn_done\n", - channel->channel_id); - - channel->send_step = STEP_IDLE; - - mif_debug("[MIPI-HSI] write protocol Done : %d\n", channel->tx_count); - return channel->tx_count; -} - -static int if_hsi_write(struct if_hsi_channel *channel, u32 *data, - unsigned int size) -{ - int ret; - unsigned long int flags; - - spin_lock_irqsave(&channel->tx_state_lock, flags); - if (channel->tx_state & HSI_CHANNEL_TX_STATE_WRITING) { - spin_unlock_irqrestore(&channel->tx_state_lock, flags); - return -EBUSY; - } - channel->tx_state |= HSI_CHANNEL_TX_STATE_WRITING; - spin_unlock_irqrestore(&channel->tx_state_lock, flags); - - channel->tx_data = data; - if (size % 4) - size += (4 - (size % 4)); - channel->tx_count = size; - - mif_debug("[MIPI-HSI] submit write data : 0x%x(%d)\n", - *(u32 *)channel->tx_data, channel->tx_count); - ret = hsi_write(channel->dev, channel->tx_data, channel->tx_count / 4); - if (ret) { - mif_err("[MIPI-HSI] ch=%d, hsi_write fail : %d\n", - channel->channel_id, ret); - - spin_lock_irqsave(&channel->tx_state_lock, flags); - channel->tx_state &= ~HSI_CHANNEL_TX_STATE_WRITING; - spin_unlock_irqrestore(&channel->tx_state_lock, flags); - - return ret; - } - - if (down_timeout(&channel->write_done_sem, - HSI_WRITE_DONE_TIMEOUT) < 0) { - mif_err("[MIPI-HSI] ch=%d, hsi_write_done timeout : %d\n", - channel->channel_id, size); - - mif_err("[MIPI-HSI] data : %08x %08x %08x %08x %08x ...\n", - *channel->tx_data, *(channel->tx_data + 1), - *(channel->tx_data + 2), *(channel->tx_data + 3), - *(channel->tx_data + 4)); - - hsi_write_cancel(channel->dev); - - spin_lock_irqsave(&channel->tx_state_lock, flags); - channel->tx_state &= ~HSI_CHANNEL_TX_STATE_WRITING; - spin_unlock_irqrestore(&channel->tx_state_lock, flags); - - return -ETIMEDOUT; - } - - if (channel->tx_count != size) - mif_err("[MIPI-HSI] ch:%d,write_done fail,write_size:%d,origin_size:%d\n", - channel->channel_id, channel->tx_count, size); - - mif_debug("[MIPI-HSI] len:%d, id:%d, data : %08x %08x %08x %08x %08x ...\n", - channel->tx_count, channel->channel_id, *channel->tx_data, - *(channel->tx_data + 1), *(channel->tx_data + 2), - *(channel->tx_data + 3), *(channel->tx_data + 4)); - - return channel->tx_count; -} - -static void if_hsi_write_done(struct hsi_device *dev, unsigned int size) -{ - unsigned long int flags; - struct mipi_link_device *mipi_ld = - (struct mipi_link_device *)if_hsi_driver.priv_data; - struct if_hsi_channel *channel = &mipi_ld->hsi_channles[dev->n_ch]; - - mif_debug("[MIPI-HSI] got write data : 0x%x(%d)\n", - *(u32 *)channel->tx_data, size); - - spin_lock_irqsave(&channel->tx_state_lock, flags); - channel->tx_state &= ~HSI_CHANNEL_TX_STATE_WRITING; - spin_unlock_irqrestore(&channel->tx_state_lock, flags); - - mif_debug("%08x %08x %08x %08x %08x %08x %08x %08x\n", - *channel->tx_data, *(channel->tx_data + 1), - *(channel->tx_data + 2), *(channel->tx_data + 3), - *(channel->tx_data + 4), *(channel->tx_data + 5), - *(channel->tx_data + 6), *(channel->tx_data + 7)); - - channel->tx_count = 4 * size; - up(&channel->write_done_sem); -} - -static void if_hsi_read_done(struct hsi_device *dev, unsigned int size) -{ - int ret; - unsigned long int flags; - u32 cmd = 0, ch = 0, param = 0; - struct mipi_link_device *mipi_ld = - (struct mipi_link_device *)if_hsi_driver.priv_data; - struct if_hsi_channel *channel = &mipi_ld->hsi_channles[dev->n_ch]; - struct io_device *iod; - enum dev_format format_type = 0; - - mif_debug("[MIPI-HSI] got read data : 0x%x(%d)\n", - *(u32 *)channel->rx_data, size); - - spin_lock_irqsave(&channel->rx_state_lock, flags); - channel->rx_state &= ~HSI_CHANNEL_RX_STATE_READING; - spin_unlock_irqrestore(&channel->rx_state_lock, flags); - - channel->rx_count = 4 * size; - - switch (channel->channel_id) { - case HSI_CONTROL_CHANNEL: - switch (mipi_ld->ld.com_state) { - case COM_HANDSHAKE: - case COM_ONLINE: - mif_debug("[MIPI-HSI] RECV CMD : %08x\n", - *channel->rx_data); - - if (channel->rx_count != 4) { - mif_err("[MIPI-HSI] wrong command len : %d\n", - channel->rx_count); - return; - } - - ret = if_hsi_decode_cmd(channel->rx_data, &cmd, &ch, - ¶m); - if (ret) - mif_err("[MIPI-HSI] decode_cmd fail=%d, " - "cmd=%x\n", ret, cmd); - else { - mif_debug("[MIPI-HSI] decode_cmd : %08x\n", - cmd); - ret = if_hsi_rx_cmd_handle(mipi_ld, cmd, ch, - param); - if (ret) - mif_err("[MIPI-HSI] handle cmd " - "cmd=%x\n", cmd); - } - - ret = hsi_read(channel->dev, channel->rx_data, 1); - if (ret) - mif_err("[MIPI-HSI] hsi_read fail : %d\n", ret); - - return; - - case COM_BOOT: - mif_debug("[MIPI-HSI] receive data : 0x%x(%d)\n", - *channel->rx_data, channel->rx_count); - - iod = link_get_iod_with_format(&mipi_ld->ld, IPC_BOOT); - if (iod) { - channel->packet_size = *channel->rx_data; - mif_debug("[MIPI-HSI] flashless packet size : " - "%d\n", channel->packet_size); - - ret = iod->recv(iod, - &mipi_ld->ld, - (char *)channel->rx_data + 4, - HSI_FLASHBOOT_ACK_LEN - 4); - if (ret < 0) - mif_err("[MIPI-HSI] recv call " - "fail : %d\n", ret); - } - - ret = hsi_read(channel->dev, channel->rx_data, - HSI_FLASHBOOT_ACK_LEN / 4); - if (ret) - mif_err("[MIPI-HSI] hsi_read fail : %d\n", ret); - return; - - case COM_CRASH: - mif_debug("[MIPI-HSI] receive data : 0x%x(%d)\n", - *channel->rx_data, channel->rx_count); - - iod = link_get_iod_with_format(&mipi_ld->ld, - IPC_RAMDUMP); - if (iod) { - channel->packet_size = *channel->rx_data; - mif_debug("[MIPI-HSI] ramdump packet size : " - "%d\n", channel->packet_size); - - ret = iod->recv(iod, - &mipi_ld->ld, - (char *)channel->rx_data + 4, - channel->packet_size); - if (ret < 0) - mif_err("[MIPI-HSI] recv call " - "fail : %d\n", ret); - } - - ret = hsi_read(channel->dev, channel->rx_data, - DUMP_PACKET_SIZE); - if (ret) - mif_err("[MIPI-HSI] hsi_read fail : %d\n", ret); - return; - - case COM_NONE: - default: - mif_err("[MIPI-HSI] receive data in wrong state : 0x%x(%d)\n", - *channel->rx_data, channel->rx_count); - return; - } - break; - - case HSI_FMT_CHANNEL: - mif_debug("[MIPI-HSI] iodevice format : IPC_FMT\n"); - format_type = IPC_FMT; - break; - case HSI_RAW_CHANNEL: - mif_debug("[MIPI-HSI] iodevice format : IPC_MULTI_RAW\n"); - format_type = IPC_MULTI_RAW; - break; - case HSI_RFS_CHANNEL: - mif_debug("[MIPI-HSI] iodevice format : IPC_RFS\n"); - format_type = IPC_RFS; - break; - - case HSI_CMD_CHANNEL: - mif_debug("[MIPI-HSI] receive command data : 0x%x\n", - *channel->rx_data); - - ch = channel->channel_id; - param = 0; - ret = if_hsi_send_command(mipi_ld, HSI_LL_MSG_CONN_CLOSED, - ch, param); - if (ret) - mif_err("[MIPI-HSI] send_cmd fail=%d\n", ret); - - channel->recv_step = STEP_IDLE; - return; - - default: - return; - } - - iod = link_get_iod_with_format(&mipi_ld->ld, format_type); - if (iod) { - mif_debug("[MIPI-HSI] iodevice format : %d\n", iod->format); - - channel->recv_step = STEP_NOT_READY; - - mif_debug("[MIPI-HSI] RECV DATA : %08x(%d)-%d\n", - *channel->rx_data, channel->packet_size, - iod->format); - - mif_debug("%08x %08x %08x %08x %08x %08x %08x %08x\n", - *channel->rx_data, *(channel->rx_data + 1), - *(channel->rx_data + 2), *(channel->rx_data + 3), - *(channel->rx_data + 4), *(channel->rx_data + 5), - *(channel->rx_data + 6), *(channel->rx_data + 7)); - - ret = iod->recv(iod, &mipi_ld->ld, - (char *)channel->rx_data, channel->packet_size); - if (ret < 0) - mif_err("[MIPI-HSI] recv call fail : %d\n", ret); - - ch = channel->channel_id; - param = 0; - ret = if_hsi_send_command(mipi_ld, - HSI_LL_MSG_CONN_CLOSED, ch, param); - if (ret) - mif_err("[MIPI-HSI] send_cmd fail=%d\n", ret); - - channel->recv_step = STEP_IDLE; - } -} - -static void if_hsi_port_event(struct hsi_device *dev, unsigned int event, - void *arg) -{ - int acwake_level = 1; - struct mipi_link_device *mipi_ld = - (struct mipi_link_device *)if_hsi_driver.priv_data; - - switch (event) { - case HSI_EVENT_BREAK_DETECTED: - mif_err("[MIPI-HSI] HSI_EVENT_BREAK_DETECTED\n"); - return; - - case HSI_EVENT_HSR_DATAAVAILABLE: - mif_err("[MIPI-HSI] HSI_EVENT_HSR_DATAAVAILABLE\n"); - return; - - case HSI_EVENT_CAWAKE_UP: - if (dev->n_ch == HSI_CONTROL_CHANNEL) { - if (!wake_lock_active(&mipi_ld->wlock)) { - wake_lock(&mipi_ld->wlock); - mif_debug("[MIPI-HSI] wake_lock\n"); - } - mif_debug("[MIPI-HSI] CAWAKE_%d(1)\n", dev->n_ch); - } - return; - - case HSI_EVENT_CAWAKE_DOWN: - if (dev->n_ch == HSI_CONTROL_CHANNEL) - mif_debug("[MIPI-HSI] CAWAKE_%d(0)\n", dev->n_ch); - - if ((dev->n_ch == HSI_CONTROL_CHANNEL) && - mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL].opened) { - hsi_ioctl( - mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL].dev, - HSI_IOCTL_GET_ACWAKE, &acwake_level); - - mif_debug("[MIPI-HSI] GET_ACWAKE. Ch : %d, level : %d\n", - dev->n_ch, acwake_level); - - if (!acwake_level) { - wake_unlock(&mipi_ld->wlock); - mif_debug("[MIPI-HSI] wake_unlock\n"); - } - } - return; - - case HSI_EVENT_ERROR: - mif_err("[MIPI-HSI] HSI_EVENT_ERROR\n"); - return; - - default: - mif_err("[MIPI-HSI] Unknown Event : %d\n", event); - return; - } -} - -static int __devinit if_hsi_probe(struct hsi_device *dev) -{ - int port = 0; - unsigned long *address; - struct mipi_link_device *mipi_ld = - (struct mipi_link_device *)if_hsi_driver.priv_data; - - for (port = 0; port < HSI_MAX_PORTS; port++) { - if (if_hsi_driver.ch_mask[port]) - break; - } - address = (unsigned long *)&if_hsi_driver.ch_mask[port]; - - if (test_bit(dev->n_ch, address) && (dev->n_p == port)) { - /* Register callback func */ - hsi_set_write_cb(dev, if_hsi_write_done); - hsi_set_read_cb(dev, if_hsi_read_done); - hsi_set_port_event_cb(dev, if_hsi_port_event); - - /* Init device data */ - mipi_ld->hsi_channles[dev->n_ch].dev = dev; - mipi_ld->hsi_channles[dev->n_ch].tx_count = 0; - mipi_ld->hsi_channles[dev->n_ch].rx_count = 0; - mipi_ld->hsi_channles[dev->n_ch].tx_state = 0; - mipi_ld->hsi_channles[dev->n_ch].rx_state = 0; - mipi_ld->hsi_channles[dev->n_ch].packet_size = 0; - mipi_ld->hsi_channles[dev->n_ch].acwake = 0; - mipi_ld->hsi_channles[dev->n_ch].send_step = STEP_UNDEF; - mipi_ld->hsi_channles[dev->n_ch].recv_step = STEP_UNDEF; - spin_lock_init(&mipi_ld->hsi_channles[dev->n_ch].tx_state_lock); - spin_lock_init(&mipi_ld->hsi_channles[dev->n_ch].rx_state_lock); - spin_lock_init(&mipi_ld->hsi_channles[dev->n_ch].acwake_lock); - sema_init(&mipi_ld->hsi_channles[dev->n_ch].write_done_sem, - 0); - sema_init(&mipi_ld->hsi_channles[dev->n_ch].ack_done_sem, - 0); - sema_init(&mipi_ld->hsi_channles[dev->n_ch].close_conn_done_sem, - 0); - } - - mif_debug("[MIPI-HSI] if_hsi_probe() done. ch : %d\n", dev->n_ch); - return 0; -} - -static int if_hsi_init(struct link_device *ld) -{ - int ret; - int i = 0; - struct mipi_link_device *mipi_ld = to_mipi_link_device(ld); - - for (i = 0; i < HSI_MAX_PORTS; i++) - if_hsi_driver.ch_mask[i] = 0; - - for (i = 0; i < HSI_MAX_CHANNELS; i++) { - mipi_ld->hsi_channles[i].dev = NULL; - mipi_ld->hsi_channles[i].opened = 0; - mipi_ld->hsi_channles[i].channel_id = i; - } - if_hsi_driver.ch_mask[0] = CHANNEL_MASK; - - /* TODO - need to get priv data (request to TI) */ - if_hsi_driver.priv_data = (void *)mipi_ld; - ret = hsi_register_driver(&if_hsi_driver); - if (ret) { - mif_err("[MIPI-HSI] hsi_register_driver() fail : %d\n", ret); - return ret; - } - - mipi_ld->mipi_wq = create_singlethread_workqueue("mipi_cmd_wq"); - if (!mipi_ld->mipi_wq) { - mif_err("[MIPI-HSI] fail to create work Q.\n"); - return -ENOMEM; - } - INIT_WORK(&mipi_ld->cmd_work, if_hsi_cmd_work); - INIT_DELAYED_WORK(&mipi_ld->start_work, mipi_hsi_start_work); - - setup_timer(&mipi_ld->hsi_acwake_down_timer, if_hsi_acwake_down_func, - (unsigned long)mipi_ld); - - /* TODO - allocate rx buff */ - mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL].rx_data = - kmalloc(64 * 1024, GFP_DMA | GFP_ATOMIC); - if (!mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL].rx_data) { - mif_err("[MIPI-HSI] alloc HSI_CONTROL_CHANNEL rx_data fail\n"); - return -ENOMEM; - } - mipi_ld->hsi_channles[HSI_FMT_CHANNEL].rx_data = - kmalloc(256 * 1024, GFP_DMA | GFP_ATOMIC); - if (!mipi_ld->hsi_channles[HSI_FMT_CHANNEL].rx_data) { - mif_err("[MIPI-HSI] alloc HSI_FMT_CHANNEL rx_data fail\n"); - return -ENOMEM; - } - mipi_ld->hsi_channles[HSI_RAW_CHANNEL].rx_data = - kmalloc(256 * 1024, GFP_DMA | GFP_ATOMIC); - if (!mipi_ld->hsi_channles[HSI_RAW_CHANNEL].rx_data) { - mif_err("[MIPI-HSI] alloc HSI_RAW_CHANNEL rx_data fail\n"); - return -ENOMEM; - } - mipi_ld->hsi_channles[HSI_RFS_CHANNEL].rx_data = - kmalloc(256 * 1024, GFP_DMA | GFP_ATOMIC); - if (!mipi_ld->hsi_channles[HSI_RFS_CHANNEL].rx_data) { - mif_err("[MIPI-HSI] alloc HSI_RFS_CHANNEL rx_data fail\n"); - return -ENOMEM; - } - mipi_ld->hsi_channles[HSI_CMD_CHANNEL].rx_data = - kmalloc(256 * 1024, GFP_DMA | GFP_ATOMIC); - if (!mipi_ld->hsi_channles[HSI_CMD_CHANNEL].rx_data) { - mif_err("[MIPI-HSI] alloc HSI_CMD_CHANNEL rx_data fail\n"); - return -ENOMEM; - } - - return 0; -} - -struct link_device *mipi_create_link_device(struct platform_device *pdev) -{ - int ret; - struct mipi_link_device *mipi_ld; - struct link_device *ld; - - /* for dpram int */ - /* struct modem_data *pdata = pdev->dev.platform_data; */ - - mipi_ld = kzalloc(sizeof(struct mipi_link_device), GFP_KERNEL); - if (!mipi_ld) - return NULL; - - INIT_LIST_HEAD(&mipi_ld->list_of_hsi_cmd); - spin_lock_init(&mipi_ld->list_cmd_lock); - skb_queue_head_init(&mipi_ld->ld.sk_fmt_tx_q); - skb_queue_head_init(&mipi_ld->ld.sk_raw_tx_q); - - wake_lock_init(&mipi_ld->wlock, WAKE_LOCK_SUSPEND, "mipi_link"); - - ld = &mipi_ld->ld; - - ld->name = "mipi_hsi"; - ld->init_comm = mipi_hsi_init_communication; - ld->terminate_comm = mipi_hsi_terminate_communication; - ld->send = mipi_hsi_send; - ld->com_state = COM_NONE; - - /* for dpram int */ - /* ld->irq = gpio_to_irq(pdata->gpio); s*/ - - ld->tx_wq = create_singlethread_workqueue("mipi_tx_wq"); - if (!ld->tx_wq) { - mif_err("[MIPI-HSI] fail to create work Q.\n"); - return NULL; - } - INIT_WORK(&ld->tx_work, mipi_hsi_tx_work); - - ret = if_hsi_init(ld); - if (ret) - return NULL; - - return ld; -} diff --git a/drivers/misc/modem_if/modem_link_device_mipi.h b/drivers/misc/modem_if/modem_link_device_mipi.h deleted file mode 100644 index 8ca4968b870..00000000000 --- a/drivers/misc/modem_if/modem_link_device_mipi.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2010 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. - * - */ - -#ifndef __MODEM_LINK_DEVICE_MIPI_H__ -#define __MODEM_LINK_DEVICE_MIPI_H__ - - -#define HSI_MAX_CHANNELS 16 -#define CHANNEL_MASK 0xFF - -#define HSI_CHANNEL_TX_STATE_UNAVAIL (1 << 0) -#define HSI_CHANNEL_TX_STATE_WRITING (1 << 1) -#define HSI_CHANNEL_RX_STATE_UNAVAIL (1 << 0) -#define HSI_CHANNEL_RX_STATE_READING (1 << 1) - -#define HSI_WRITE_DONE_TIMEOUT (HZ) -#define HSI_READ_DONE_TIMEOUT (HZ) -#define HSI_ACK_DONE_TIMEOUT (HZ) -#define HSI_CLOSE_CONN_DONE_TIMEOUT (HZ) -#define HSI_ACWAKE_DOWN_TIMEOUT (HZ / 2) - -#define HSI_CONTROL_CHANNEL 0 -#define HSI_FLASHLESS_CHANNEL 0 -#define HSI_CP_RAMDUMP_CHANNEL 0 -#define HSI_FMT_CHANNEL 1 -#define HSI_RAW_CHANNEL 2 -#define HSI_RFS_CHANNEL 3 -#define HSI_CMD_CHANNEL 4 -#define HSI_NUM_OF_USE_CHANNELS 5 - -#define HSI_LL_INVALID_CHANNEL 0xFF - -#define HSI_FLASHBOOT_ACK_LEN 16 -#define DUMP_PACKET_SIZE 12289 /* 48K + 4 length, word unit */ -#define DUMP_ERR_INFO_SIZE 39 /* 150 bytes + 4 length , word unit */ - -enum { - HSI_LL_MSG_BREAK, /* 0x0 */ - HSI_LL_MSG_ECHO, - HSI_LL_MSG_INFO_REQ, - HSI_LL_MSG_INFO, - HSI_LL_MSG_CONFIGURE, - HSI_LL_MSG_ALLOCATE_CH, - HSI_LL_MSG_RELEASE_CH, - HSI_LL_MSG_OPEN_CONN, - HSI_LL_MSG_CONN_READY, - HSI_LL_MSG_CONN_CLOSED, /* 0x9 */ - HSI_LL_MSG_CANCEL_CONN, - HSI_LL_MSG_ACK, /* 0xB */ - HSI_LL_MSG_NAK, /* 0xC */ - HSI_LL_MSG_CONF_RATE, - HSI_LL_MSG_OPEN_CONN_OCTET, /* 0xE */ - HSI_LL_MSG_INVALID = 0xFF, -}; - -enum { - STEP_UNDEF, - STEP_CLOSED, - STEP_NOT_READY, - STEP_IDLE, - STEP_ERROR, - STEP_SEND_OPEN_CONN, - STEP_SEND_ACK, - STEP_WAIT_FOR_ACK, - STEP_TO_ACK, - STEP_SEND_NACK, - STEP_GET_NACK, - STEP_SEND_CONN_READY, - STEP_WAIT_FOR_CONN_READY, - STEP_SEND_CONF_RATE, - STEP_WAIT_FOR_CONF_ACK, - STEP_TX, - STEP_RX, - STEP_SEND_CONN_CLOSED, - STEP_WAIT_FOR_CONN_CLOSED, - STEP_SEND_BREAK, -}; - - -struct if_hsi_channel { - struct hsi_device *dev; - unsigned int channel_id; - - u32 *tx_data; - unsigned int tx_count; - u32 *rx_data; - unsigned int rx_count; - unsigned int packet_size; - - unsigned int tx_state; - unsigned int rx_state; - spinlock_t tx_state_lock; - spinlock_t rx_state_lock; - - unsigned int send_step; - unsigned int recv_step; - - unsigned int got_nack; - unsigned int acwake; - spinlock_t acwake_lock; - - struct semaphore write_done_sem; - struct semaphore ack_done_sem; - struct semaphore close_conn_done_sem; - - unsigned int opened; -}; - -struct if_hsi_command { - u32 command; - struct list_head list; -}; - -struct mipi_link_device { - struct link_device ld; - - /* mipi specific link data */ - struct if_hsi_channel hsi_channles[HSI_MAX_CHANNELS]; - struct list_head list_of_hsi_cmd; - spinlock_t list_cmd_lock; - - struct workqueue_struct *mipi_wq; - struct work_struct cmd_work; - struct delayed_work start_work; - - struct wake_lock wlock; - struct timer_list hsi_acwake_down_timer; -}; -/* converts from struct link_device* to struct xxx_link_device* */ -#define to_mipi_link_device(linkdev) \ - container_of(linkdev, struct mipi_link_device, ld) - - -enum { - HSI_INIT_MODE_NORMAL, - HSI_INIT_MODE_FLASHLESS_BOOT, - HSI_INIT_MODE_CP_RAMDUMP, -}; -static int hsi_init_handshake(struct mipi_link_device *mipi_ld, int mode); -static int if_hsi_write(struct if_hsi_channel *channel, u32 *data, - unsigned int size); -static int if_hsi_protocol_send(struct mipi_link_device *mipi_ld, int ch, - u32 *data, unsigned int len); -static int if_hsi_close_channel(struct if_hsi_channel *channel); - -#endif diff --git a/drivers/misc/modem_if/modem_link_device_pld.c b/drivers/misc/modem_if/modem_link_device_pld.c deleted file mode 100644 index 23d4627b78a..00000000000 --- a/drivers/misc/modem_if/modem_link_device_pld.c +++ /dev/null @@ -1,1618 +0,0 @@ -/* - * 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/kallsyms.h> -#include <linux/platform_data/modem.h> - -#include "modem_prj.h" -#include "modem_link_device_pld.h" -#include "modem_utils.h" - - -/* -** Function prototypes for basic DPRAM operations -*/ -static inline void clear_intr(struct pld_link_device *pld); -static inline u16 recv_intr(struct pld_link_device *pld); -static inline void send_intr(struct pld_link_device *pld, u16 mask); - -static inline u16 get_magic(struct pld_link_device *pld); -static inline void set_magic(struct pld_link_device *pld, u16 val); -static inline u16 get_access(struct pld_link_device *pld); -static inline void set_access(struct pld_link_device *pld, u16 val); - -static inline u32 get_tx_head(struct pld_link_device *pld, int id); -static inline u32 get_tx_tail(struct pld_link_device *pld, int id); -static inline void set_tx_head(struct pld_link_device *pld, int id, u32 in); -static inline void set_tx_tail(struct pld_link_device *pld, int id, u32 out); -static inline u8 *get_tx_buff(struct pld_link_device *pld, int id); -static inline u32 get_tx_buff_size(struct pld_link_device *pld, int id); - -static inline u32 get_rx_head(struct pld_link_device *pld, int id); -static inline u32 get_rx_tail(struct pld_link_device *pld, int id); -static inline void set_rx_head(struct pld_link_device *pld, int id, u32 in); -static inline void set_rx_tail(struct pld_link_device *pld, int id, u32 out); -static inline u8 *get_rx_buff(struct pld_link_device *pld, int id); -static inline u32 get_rx_buff_size(struct pld_link_device *pld, int id); - -static inline u16 get_mask_req_ack(struct pld_link_device *pld, int id); -static inline u16 get_mask_res_ack(struct pld_link_device *pld, int id); -static inline u16 get_mask_send(struct pld_link_device *pld, int id); - -static void handle_cp_crash(struct pld_link_device *pld); -static int trigger_force_cp_crash(struct pld_link_device *pld); - -/* -** Functions for debugging -*/ -static void set_dpram_map(struct pld_link_device *pld, - struct mif_irq_map *map) -{ - map->magic = get_magic(pld); - map->access = get_access(pld); - - map->fmt_tx_in = get_tx_head(pld, IPC_FMT); - map->fmt_tx_out = get_tx_tail(pld, IPC_FMT); - map->fmt_rx_in = get_rx_head(pld, IPC_FMT); - map->fmt_rx_out = get_rx_tail(pld, IPC_FMT); - map->raw_tx_in = get_tx_head(pld, IPC_RAW); - map->raw_tx_out = get_tx_tail(pld, IPC_RAW); - map->raw_rx_in = get_rx_head(pld, IPC_RAW); - map->raw_rx_out = get_rx_tail(pld, IPC_RAW); - - map->cp2ap = recv_intr(pld); -} - -/* -** DPRAM operations -*/ -static int pld_register_isr(unsigned irq, irqreturn_t (*isr)(int, void*), - unsigned long flag, const char *name, - struct pld_link_device *pld) -{ - int ret = 0; - - ret = request_irq(irq, isr, flag, name, pld); - if (ret) { - mif_info("%s: ERR! request_irq fail (err %d)\n", name, ret); - return ret; - } - - ret = enable_irq_wake(irq); - if (ret) - mif_info("%s: ERR! enable_irq_wake fail (err %d)\n", name, ret); - - mif_info("%s (#%d) handler registered\n", name, irq); - - return 0; -} - -static inline void clear_intr(struct pld_link_device *pld) -{ - if (pld->ext_op && pld->ext_op->clear_intr) - pld->ext_op->clear_intr(pld); -} - -static inline u16 recv_intr(struct pld_link_device *pld) -{ - u16 val1 = 0, val2 = 0, cnt = 3; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&pld->mbx2ap[0]), - pld->address_buffer); - val1 = ioread16(pld->base); - - iowrite16(PLD_ADDR_MASK(&pld->mbx2ap[0]), - pld->address_buffer); - val2 = ioread16(pld->base); - - if (likely(val1 == val2)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; - } - - mif_err("ERR: intr1(%d) != intr1(%d)\n", val1, val2); - - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - - return val1; -} - -static inline void send_intr(struct pld_link_device *pld, u16 mask) -{ - int cnt = 3; - u32 val = 0; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - iowrite16(PLD_ADDR_MASK(&pld->mbx2cp[0]), - pld->address_buffer); - iowrite16((u16)mask, pld->base); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&pld->mbx2cp[0]), - pld->address_buffer); - val = ioread16(pld->base); - - if (likely(val == mask)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return; - } - - mif_err("ERR: intr1(%d) != intr2(%d)\n", val, mask); - udelay(100); - - /* Write head value again */ - iowrite16(PLD_ADDR_MASK(&pld->mbx2cp[0]), - pld->address_buffer); - iowrite16((u16)mask, pld->base); - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - - return; -} - -static inline u16 get_magic(struct pld_link_device *pld) -{ - u16 val1 = 0, val2 = 0, cnt = 3; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&pld->magic_ap2cp[0]), - pld->address_buffer); - val1 = ioread16(pld->base); - - iowrite16(PLD_ADDR_MASK(&pld->magic_ap2cp[0]), - pld->address_buffer); - val2 = ioread16(pld->base); - - if (likely(val1 == val2)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; - } - - mif_err("ERR: txq.head(%d) != in(%d)\n", val1, val2); - udelay(100); - - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; - -} - -static inline void set_magic(struct pld_link_device *pld, u16 in) -{ - int cnt = 3; - u32 val = 0; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - iowrite16(PLD_ADDR_MASK(&pld->magic_ap2cp[0]), - pld->address_buffer); - iowrite16((u16)in, pld->base); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&pld->magic_ap2cp[0]), - pld->address_buffer); - val = ioread16(pld->base); - - if (likely(val == in)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return; - } - - mif_err("ERR: magic1(%d) != magic2(%d)\n", val, in); - udelay(100); - - /* Write head value again */ - iowrite16(PLD_ADDR_MASK(&pld->magic_ap2cp[0]), - pld->address_buffer); - iowrite16((u16)in, pld->base); - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - return; -} - -static inline u16 get_access(struct pld_link_device *pld) -{ - u16 val1 = 0, val2 = 0, cnt = 3; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&pld->access_ap2cp[0]), - pld->address_buffer); - val1 = ioread16(pld->base); - - iowrite16(PLD_ADDR_MASK(&pld->access_ap2cp[0]), - pld->address_buffer); - val2 = ioread16(pld->base); - - if (likely(val1 == val2)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; - } - - mif_err("ERR: access1(%d) != access2(%d)\n", val1, val2); - udelay(100); - - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; - -} - -static inline void set_access(struct pld_link_device *pld, u16 in) -{ - int cnt = 3; - u32 val = 0; - unsigned long int flags; - - iowrite16(PLD_ADDR_MASK(&pld->access_ap2cp[0]), - pld->address_buffer); - iowrite16((u16)in, pld->base); - - spin_lock_irqsave(&pld->pld_lock, flags); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&pld->access_ap2cp[0]), - pld->address_buffer); - val = ioread16(pld->base); - - if (likely(val == in)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return; - } - - mif_err("ERR: access(%d) != access(%d)\n", val, in); - udelay(100); - - /* Write head value again */ - iowrite16(PLD_ADDR_MASK(&pld->access_ap2cp[0]), - pld->address_buffer); - iowrite16((u16)in, pld->base); - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - return; -} - -static inline u32 get_tx_head(struct pld_link_device *pld, int id) -{ - u16 val1 = 0, val2 = 0, cnt = 3; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.head)[0]), - pld->address_buffer); - val1 = ioread16(pld->base); - - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.head)[0]), - pld->address_buffer); - val2 = ioread16(pld->base); - - if (likely(val1 == val2)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; - } - - mif_err("ERR: %s txq.head(%d) != in(%d)\n", - get_dev_name(id), val1, val2); - udelay(100); - - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; -} - -static inline u32 get_tx_tail(struct pld_link_device *pld, int id) -{ - u16 val1 = 0, val2 = 0, cnt = 3; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.tail)[0]), - pld->address_buffer); - val1 = ioread16(pld->base); - - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.tail)[0]), - pld->address_buffer); - val2 = ioread16(pld->base); - - if (likely(val1 == val2)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; - } - - mif_err("ERR: %s txq.tail(%d) != in(%d)\n", - get_dev_name(id), val1, val2); - udelay(100); - - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; -} - -static inline void set_tx_head(struct pld_link_device *pld, int id, u32 in) -{ - int cnt = 3; - u32 val = 0; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.head)[0]), - pld->address_buffer); - iowrite16((u16)in, pld->base); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.head)[0]), - pld->address_buffer); - val = ioread16(pld->base); - - if (likely(val == in)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return; - } - - mif_err("ERR: %s txq.head(%d) != in(%d)\n", - get_dev_name(id), val, in); - udelay(100); - - /* Write head value again */ - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->txq.head)[0]), - pld->address_buffer); - iowrite16((u16)in, pld->base); - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - return; -} - -static inline void set_tx_tail(struct pld_link_device *pld, int id, u32 out) -{ - return; -} - -static inline u8 *get_tx_buff(struct pld_link_device *pld, int id) -{ - return pld->dev[id]->txq.buff; -} - -static inline u32 get_tx_buff_size(struct pld_link_device *pld, int id) -{ - return pld->dev[id]->txq.size; -} - -static inline u32 get_rx_head(struct pld_link_device *pld, int id) -{ - u16 val1 = 0, val2 = 0, cnt = 3; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.head)[0]), - pld->address_buffer); - val1 = ioread16(pld->base); - - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.head)[0]), - pld->address_buffer); - val2 = ioread16(pld->base); - - if (likely(val1 == val2)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; - } - - mif_err("ERR: %s rxq.head(%d) != in(%d)\n", - get_dev_name(id), val1, val2); - udelay(100); - - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; -} - -static inline u32 get_rx_tail(struct pld_link_device *pld, int id) -{ - u16 val1 = 0, val2 = 0, cnt = 3; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - do { - /* Check head value written */ - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.tail)[0]), - pld->address_buffer); - val1 = ioread16(pld->base); - - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.tail)[0]), - pld->address_buffer); - val2 = ioread16(pld->base); - - if (likely(val1 == val2)) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; - } - - mif_err("ERR: %s rxq.tail(%d) != in(%d)\n", - get_dev_name(id), val1, val2); - udelay(100); - - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - return val1; -} - -static inline void set_rx_head(struct pld_link_device *pld, int id, u32 in) -{ - return; -} - -static inline void set_rx_tail(struct pld_link_device *pld, int id, u32 out) -{ - int cnt = 3; - u32 val = 0; - unsigned long int flags; - - spin_lock_irqsave(&pld->pld_lock, flags); - - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.tail)[0]), - pld->address_buffer); - iowrite16((u16)out, pld->base); - - do { - /* Check tail value written */ - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.tail)[0]), - pld->address_buffer); - val = ioread16(pld->base); - - if (val == out) { - spin_unlock_irqrestore(&pld->pld_lock, flags); - return; - } - - mif_err("ERR: %s rxq.tail(%d) != out(%d)\n", - get_dev_name(id), val, out); - udelay(100); - - /* Write tail value again */ - iowrite16(PLD_ADDR_MASK(&(pld->dev[id]->rxq.tail)[0]), - pld->address_buffer); - iowrite16((u16)out, pld->base); - } while (cnt--); - - spin_unlock_irqrestore(&pld->pld_lock, flags); - return; -} - -static inline u8 *get_rx_buff(struct pld_link_device *pld, int id) -{ - return pld->dev[id]->rxq.buff; -} - -static inline u32 get_rx_buff_size(struct pld_link_device *pld, int id) -{ - return pld->dev[id]->rxq.size; -} - -static inline u16 get_mask_req_ack(struct pld_link_device *pld, int id) -{ - return pld->dev[id]->mask_req_ack; -} - -static inline u16 get_mask_res_ack(struct pld_link_device *pld, int id) -{ - return pld->dev[id]->mask_res_ack; -} - -static inline u16 get_mask_send(struct pld_link_device *pld, int id) -{ - return pld->dev[id]->mask_send; -} - -/* Get free space in the TXQ as well as in & out pointers */ -static inline int get_txq_space(struct pld_link_device *pld, int dev, u32 qsize, - u32 *in, u32 *out) -{ - struct link_device *ld = &pld->ld; - int cnt = 3; - u32 head; - u32 tail; - int space; - - do { - head = get_tx_head(pld, dev); - tail = get_tx_tail(pld, dev); - - space = (head < tail) ? (tail - head - 1) : - (qsize + tail - head - 1); - mif_debug("%s: %s_TXQ qsize[%u] in[%u] out[%u] space[%u]\n", - ld->name, get_dev_name(dev), qsize, head, tail, space); - - if (circ_valid(qsize, head, tail)) { - *in = head; - *out = tail; - return space; - } - - mif_info("%s: CAUTION! <%pf> " - "%s_TXQ invalid (size:%d in:%d out:%d)\n", - ld->name, __builtin_return_address(0), - get_dev_name(dev), qsize, head, tail); - - udelay(100); - } while (cnt--); - - *in = 0; - *out = 0; - return -EINVAL; -} - -static void reset_tx_circ(struct pld_link_device *pld, int dev) -{ - set_tx_head(pld, dev, 0); - set_tx_tail(pld, dev, 0); - if (dev == IPC_FMT) - trigger_force_cp_crash(pld); -} - -/* Get data size in the RXQ as well as in & out pointers */ -static inline int get_rxq_rcvd(struct pld_link_device *pld, int dev, u32 qsize, - u32 *in, u32 *out) -{ - struct link_device *ld = &pld->ld; - int cnt = 3; - u32 head; - u32 tail; - u32 rcvd; - - do { - head = get_rx_head(pld, dev); - tail = get_rx_tail(pld, dev); - if (head == tail) { - *in = head; - *out = tail; - return 0; - } - - rcvd = (head > tail) ? (head - tail) : (qsize - tail + head); - mif_info("%s: %s_RXQ qsize[%u] in[%u] out[%u] rcvd[%u]\n", - ld->name, get_dev_name(dev), qsize, head, tail, rcvd); - - if (circ_valid(qsize, head, tail)) { - *in = head; - *out = tail; - return rcvd; - } - - mif_info("%s: CAUTION! <%pf> " - "%s_RXQ invalid (size:%d in:%d out:%d)\n", - ld->name, __builtin_return_address(0), - get_dev_name(dev), qsize, head, tail); - - udelay(100); - } while (cnt--); - - *in = 0; - *out = 0; - return -EINVAL; -} - -static void reset_rx_circ(struct pld_link_device *pld, int dev) -{ - set_rx_head(pld, dev, 0); - set_rx_tail(pld, dev, 0); - if (dev == IPC_FMT) - trigger_force_cp_crash(pld); -} - -static int check_access(struct pld_link_device *pld) -{ - struct link_device *ld = &pld->ld; - int i; - u16 magic = get_magic(pld); - u16 access = get_access(pld); - - if (likely(magic == DPRAM_MAGIC_CODE && access == 1)) - return 0; - - for (i = 1; i <= 100; i++) { - mif_info("%s: ERR! magic:%X access:%X -> retry:%d\n", - ld->name, magic, access, i); - udelay(100); - - magic = get_magic(pld); - access = get_access(pld); - if (likely(magic == DPRAM_MAGIC_CODE && access == 1)) - return 0; - } - - mif_info("%s: !CRISIS! magic:%X access:%X\n", ld->name, magic, access); - return -EACCES; -} - -static bool ipc_active(struct pld_link_device *pld) -{ - struct link_device *ld = &pld->ld; - - /* Check DPRAM mode */ - if (ld->mode != LINK_MODE_IPC) { - mif_info("%s: <%pf> ld->mode != LINK_MODE_IPC\n", - ld->name, __builtin_return_address(0)); - return false; - } - - if (check_access(pld) < 0) { - mif_info("%s: ERR! <%pf> check_access fail\n", - ld->name, __builtin_return_address(0)); - return false; - } - - return true; -} - -static void pld_ipc_write(struct pld_link_device *pld, int dev, - u32 qsize, u32 in, u32 out, struct sk_buff *skb) -{ - struct link_device *ld = &pld->ld; - u8 __iomem *buff = get_tx_buff(pld, dev); - u8 *src = skb->data; - u32 len = skb->len; - u32 inp; - struct mif_irq_map map; - - if (in < out) { - /* +++++++++ in ---------- out ++++++++++ */ - iowrite16(PLD_ADDR_MASK(&(buff+in)[0]), pld->address_buffer); - memcpy(pld->base, src, len); - } else { - /* ------ out +++++++++++ in ------------ */ - u32 space = qsize - in; - - /* 1) in -> buffer end */ - iowrite16(PLD_ADDR_MASK(&(buff+in)[0]), pld->address_buffer); - memcpy(pld->base, src, ((len > space) ? space : len)); - - if (len > space) { - iowrite16(PLD_ADDR_MASK(&buff[0]), - pld->address_buffer); - memcpy(pld->base, (src+space), (len-space)); - } - } - - /* update new in pointer */ - inp = in + len; - if (inp >= qsize) - inp -= qsize; - set_tx_head(pld, dev, inp); - - if (dev == IPC_FMT) { - set_dpram_map(pld, &map); - mif_irq_log(ld->mc->msd, map, "ipc_write", sizeof("ipc_write")); - mif_ipc_log(MIF_IPC_AP2CP, ld->mc->msd, skb->data, skb->len); - } -} - -static int pld_try_ipc_tx(struct pld_link_device *pld, int dev) -{ - struct link_device *ld = &pld->ld; - struct sk_buff_head *txq = ld->skb_txq[dev]; - struct sk_buff *skb; - unsigned long int flags; - u32 qsize = get_tx_buff_size(pld, dev); - u32 in; - u32 out; - int space; - int copied = 0; - - spin_lock_irqsave(&pld->tx_rx_lock, flags); - - while (1) { - space = get_txq_space(pld, dev, qsize, &in, &out); - if (unlikely(space < 0)) { - spin_unlock_irqrestore(&pld->tx_rx_lock, flags); - reset_tx_circ(pld, dev); - return space; - } - - skb = skb_dequeue(txq); - if (unlikely(!skb)) - break; - - if (unlikely(space < skb->len)) { - atomic_set(&pld->res_required[dev], 1); - skb_queue_head(txq, skb); - spin_unlock_irqrestore(&pld->tx_rx_lock, flags); - mif_info("%s: %s " - "qsize[%u] in[%u] out[%u] free[%u] < len[%u]\n", - ld->name, get_dev_name(dev), - qsize, in, out, space, skb->len); - return -ENOSPC; - } - - /* TX if there is enough room in the queue */ - pld_ipc_write(pld, dev, qsize, in, out, skb); - copied += skb->len; - dev_kfree_skb_any(skb); - } - - spin_unlock_irqrestore(&pld->tx_rx_lock, flags); - - return copied; -} - -static void pld_ipc_rx_task(unsigned long data) -{ - struct pld_link_device *pld = (struct pld_link_device *)data; - struct link_device *ld = &pld->ld; - struct io_device *iod; - struct mif_rxb *rxb; - unsigned qlen; - int i; - - for (i = 0; i < ld->max_ipc_dev; i++) { - iod = pld->iod[i]; - qlen = rxbq_size(&pld->rxbq[i]); - while (qlen > 0) { - rxb = rxbq_get_data_rxb(&pld->rxbq[i]); - iod->recv(iod, ld, rxb->data, rxb->len); - rxb_clear(rxb); - qlen--; - } - } -} - -static void pld_ipc_read(struct pld_link_device *pld, int dev, u8 *dst, - u8 __iomem *src, u32 out, u32 len, u32 qsize) -{ - u8 *ori_det = dst; - - if ((out + len) <= qsize) { - /* ----- (out) (in) ----- */ - /* ----- 7f 00 00 7e ----- */ - iowrite16(PLD_ADDR_MASK(&(src+out)[0]), pld->address_buffer); - memcpy(dst, pld->base, len); - } else { - /* (in) ----------- (out) */ - /* 00 7e ----------- 7f 00 */ - unsigned len1 = qsize - out; - - /* 1) out -> buffer end */ - iowrite16(PLD_ADDR_MASK(&(src+out)[0]), pld->address_buffer); - memcpy(dst, pld->base, len1); - - /* 2) buffer start -> in */ - dst += len1; - iowrite16(PLD_ADDR_MASK(&src[0]), pld->address_buffer); - memcpy(dst, pld->base, (len - len1)); - } - - if (pld->ld.mode == LINK_MODE_IPC && ori_det[0] != 0x7F) { - mif_info("ipc read error!! in[%d], out[%d]\n", - get_rx_head(pld, dev), - get_rx_tail(pld, dev)); - } - -} - -/* - ret < 0 : error - ret == 0 : no data - ret > 0 : valid data -*/ -static int pld_ipc_recv_data_with_rxb(struct pld_link_device *pld, int dev) -{ - struct link_device *ld = &pld->ld; - struct mif_rxb *rxb; - u8 __iomem *src = get_rx_buff(pld, dev); - u32 qsize = get_rx_buff_size(pld, dev); - u32 in; - u32 out; - u32 rcvd; - struct mif_irq_map map; - unsigned long int flags; - - spin_lock_irqsave(&pld->tx_rx_lock, flags); - - rcvd = get_rxq_rcvd(pld, dev, qsize, &in, &out); - if (rcvd <= 0) { - spin_unlock_irqrestore(&pld->tx_rx_lock, flags); - return rcvd; - } - - if (dev == IPC_FMT) { - set_dpram_map(pld, &map); - mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv")); - } - - /* Allocate an rxb */ - rxb = rxbq_get_free_rxb(&pld->rxbq[dev]); - if (!rxb) { - mif_info("%s: ERR! %s rxbq_get_free_rxb fail\n", - ld->name, get_dev_name(dev)); - spin_unlock_irqrestore(&pld->tx_rx_lock, flags); - return -ENOMEM; - } - - /* Read data from each DPRAM buffer */ - pld_ipc_read(pld, dev, rxb_put(rxb, rcvd), src, out, rcvd, qsize); - - /* Calculate and set new out */ - out += rcvd; - if (out >= qsize) - out -= qsize; - set_rx_tail(pld, dev, out); - - spin_unlock_irqrestore(&pld->tx_rx_lock, flags); - return rcvd; -} - -static void non_command_handler(struct pld_link_device *pld, u16 non_cmd) -{ - struct link_device *ld = &pld->ld; - int i = 0; - int ret = 0; - u16 mask = 0; - - if (!ipc_active(pld)) - return; - - /* Read data from DPRAM */ - for (i = 0; i < ld->max_ipc_dev; i++) { - ret = pld_ipc_recv_data_with_rxb(pld, i); - if (ret < 0) - reset_rx_circ(pld, i); - - /* Check and process REQ_ACK (at this time, in == out) */ - if (non_cmd & get_mask_req_ack(pld, i)) { - mif_debug("%s: send %s_RES_ACK\n", - ld->name, get_dev_name(i)); - mask |= get_mask_res_ack(pld, i); - } - } - - /* Schedule soft IRQ for RX */ - tasklet_hi_schedule(&pld->rx_tsk); - - /* Try TX via DPRAM */ - for (i = 0; i < ld->max_ipc_dev; i++) { - if (atomic_read(&pld->res_required[i]) > 0) { - ret = pld_try_ipc_tx(pld, i); - if (ret > 0) { - atomic_set(&pld->res_required[i], 0); - mask |= get_mask_send(pld, i); - } else if (ret == -ENOSPC) { - mask |= get_mask_req_ack(pld, i); - } - } - } - - if (mask) { - send_intr(pld, INT_NON_CMD(mask)); - mif_debug("%s: send intr 0x%04X\n", ld->name, mask); - } -} - -static void handle_cp_crash(struct pld_link_device *pld) -{ - struct link_device *ld = &pld->ld; - struct io_device *iod; - int i; - - for (i = 0; i < ld->max_ipc_dev; i++) { - mif_info("%s: purging %s_skb_txq\b", ld->name, get_dev_name(i)); - skb_queue_purge(ld->skb_txq[i]); - } - - iod = link_get_iod_with_format(ld, IPC_FMT); - iod->modem_state_changed(iod, STATE_CRASH_EXIT); - - iod = link_get_iod_with_format(ld, IPC_BOOT); - iod->modem_state_changed(iod, STATE_CRASH_EXIT); - - iod = link_get_iod_with_channel(ld, RMNET0_CH_ID); - if (iod) - iodevs_for_each(iod->msd, iodev_netif_stop, 0); -} - -static void handle_no_crash_ack(unsigned long arg) -{ - struct pld_link_device *pld = (struct pld_link_device *)arg; - struct link_device *ld = &pld->ld; - - mif_err("%s: ERR! No CRASH_EXIT ACK from CP\n", ld->mc->name); - - if (!wake_lock_active(&pld->wlock)) - wake_lock(&pld->wlock); - - handle_cp_crash(pld); -} - -static int trigger_force_cp_crash(struct pld_link_device *pld) -{ - struct link_device *ld = &pld->ld; - - if (ld->mode == LINK_MODE_ULOAD) { - mif_err("%s: CP crash is already in progress\n", ld->mc->name); - return 0; - } - - ld->mode = LINK_MODE_ULOAD; - mif_err("%s: called by %pf\n", ld->name, __builtin_return_address(0)); - - send_intr(pld, INT_CMD(INT_CMD_CRASH_EXIT)); - - mif_add_timer(&pld->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT, - handle_no_crash_ack, (unsigned long)pld); - - return 0; -} - -static int pld_init_ipc(struct pld_link_device *pld) -{ - struct link_device *ld = &pld->ld; - int i; - - if (ld->mode == LINK_MODE_IPC && - get_magic(pld) == DPRAM_MAGIC_CODE && - get_access(pld) == 1) - mif_info("%s: IPC already initialized\n", ld->name); - - /* Clear pointers in every circular queue */ - for (i = 0; i < ld->max_ipc_dev; i++) { - set_tx_head(pld, i, 0); - set_tx_tail(pld, i, 0); - set_rx_head(pld, i, 0); - set_rx_tail(pld, i, 0); - } - - /* Initialize variables for efficient TX/RX processing */ - for (i = 0; i < ld->max_ipc_dev; i++) - pld->iod[i] = link_get_iod_with_format(ld, i); - pld->iod[IPC_RAW] = link_get_iod_with_format(ld, IPC_MULTI_RAW); - - for (i = 0; i < ld->max_ipc_dev; i++) - atomic_set(&pld->res_required[i], 0); - - spin_lock_init(&pld->tx_rx_lock); - - /* Enable IPC */ - atomic_set(&pld->accessing, 0); - - set_magic(pld, DPRAM_MAGIC_CODE); - set_access(pld, 1); - if (get_magic(pld) != DPRAM_MAGIC_CODE || get_access(pld) != 1) - return -EACCES; - - ld->mode = LINK_MODE_IPC; - - if (wake_lock_active(&pld->wlock)) - wake_unlock(&pld->wlock); - - return 0; -} - -static void cmd_req_active_handler(struct pld_link_device *pld) -{ - send_intr(pld, INT_CMD(INT_CMD_RES_ACTIVE)); -} - -static void cmd_crash_reset_handler(struct pld_link_device *pld) -{ - struct link_device *ld = &pld->ld; - struct io_device *iod = NULL; - - ld->mode = LINK_MODE_ULOAD; - - if (!wake_lock_active(&pld->wlock)) - wake_lock(&pld->wlock); - - mif_err("%s: Recv 0xC7 (CRASH_RESET)\n", ld->name); - - iod = link_get_iod_with_format(ld, IPC_FMT); - iod->modem_state_changed(iod, STATE_CRASH_RESET); - - iod = link_get_iod_with_format(ld, IPC_BOOT); - iod->modem_state_changed(iod, STATE_CRASH_RESET); -} - -static void cmd_crash_exit_handler(struct pld_link_device *pld) -{ - struct link_device *ld = &pld->ld; - - ld->mode = LINK_MODE_ULOAD; - - if (!wake_lock_active(&pld->wlock)) - wake_lock(&pld->wlock); - - mif_err("%s: Recv 0xC9 (CRASH_EXIT)\n", ld->name); - - del_timer(&pld->crash_ack_timer); - - if (pld->ext_op && pld->ext_op->crash_log) - pld->ext_op->crash_log(pld); - - handle_cp_crash(pld); -} - -static void cmd_phone_start_handler(struct pld_link_device *pld) -{ - struct link_device *ld = &pld->ld; - struct io_device *iod = NULL; - - mif_info("%s: Recv 0xC8 (CP_START)\n", ld->name); - - pld_init_ipc(pld); - - iod = link_get_iod_with_format(ld, IPC_FMT); - if (!iod) { - mif_info("%s: ERR! no iod\n", ld->name); - return; - } - - if (pld->ext_op && pld->ext_op->cp_start_handler) - pld->ext_op->cp_start_handler(pld); - - if (ld->mc->phone_state != STATE_ONLINE) { - mif_info("%s: phone_state: %d -> ONLINE\n", - ld->name, ld->mc->phone_state); - iod->modem_state_changed(iod, STATE_ONLINE); - } - - mif_info("%s: Send 0xC2 (INIT_END)\n", ld->name); - send_intr(pld, INT_CMD(INT_CMD_INIT_END)); -} - -static void command_handler(struct pld_link_device *pld, u16 cmd) -{ - struct link_device *ld = &pld->ld; - - switch (INT_CMD_MASK(cmd)) { - case INT_CMD_REQ_ACTIVE: - cmd_req_active_handler(pld); - break; - - case INT_CMD_CRASH_RESET: - pld->init_status = DPRAM_INIT_STATE_NONE; - cmd_crash_reset_handler(pld); - break; - - case INT_CMD_CRASH_EXIT: - pld->init_status = DPRAM_INIT_STATE_NONE; - cmd_crash_exit_handler(pld); - break; - - case INT_CMD_PHONE_START: - pld->init_status = DPRAM_INIT_STATE_READY; - cmd_phone_start_handler(pld); - complete_all(&pld->dpram_init_cmd); - break; - - case INT_CMD_NV_REBUILDING: - mif_info("%s: NV_REBUILDING\n", ld->name); - break; - - case INT_CMD_PIF_INIT_DONE: - complete_all(&pld->modem_pif_init_done); - break; - - case INT_CMD_SILENT_NV_REBUILDING: - mif_info("%s: SILENT_NV_REBUILDING\n", ld->name); - break; - - case INT_CMD_NORMAL_PWR_OFF: - /*ToDo:*/ - /*kernel_sec_set_cp_ack()*/; - break; - - case INT_CMD_REQ_TIME_SYNC: - case INT_CMD_CP_DEEP_SLEEP: - case INT_CMD_EMER_DOWN: - break; - - default: - mif_info("%s: unknown command 0x%04X\n", ld->name, cmd); - } -} - -static irqreturn_t pld_irq_handler(int irq, void *data) -{ - struct pld_link_device *pld = (struct pld_link_device *)data; - struct link_device *ld = (struct link_device *)&pld->ld; - u16 int2ap = 0; - - if (unlikely(ld->mode == LINK_MODE_OFFLINE)) - return IRQ_HANDLED; - - int2ap = recv_intr(pld); - - if (unlikely(int2ap == INT_POWERSAFE_FAIL)) { - mif_info("%s: int2ap == INT_POWERSAFE_FAIL\n", ld->name); - goto exit; - } else if (int2ap == 0x1234 || int2ap == 0xDBAB || int2ap == 0xABCD) { - if (pld->ext_op && pld->ext_op->dload_cmd_handler) { - pld->ext_op->dload_cmd_handler(pld, int2ap); - goto exit; - } - } - - if (likely(INT_VALID(int2ap))) { - if (unlikely(INT_CMD_VALID(int2ap))) - command_handler(pld, int2ap); - else - non_command_handler(pld, int2ap); - } else { - mif_info("%s: ERR! invalid intr 0x%04X\n", - ld->name, int2ap); - } - -exit: - clear_intr(pld); - return IRQ_HANDLED; -} - -static void pld_send_ipc(struct link_device *ld, int dev, - struct io_device *iod, struct sk_buff *skb) -{ - struct pld_link_device *pld = to_pld_link_device(ld); - struct sk_buff_head *txq = ld->skb_txq[dev]; - int ret; - u16 mask; - - skb_queue_tail(txq, skb); - if (txq->qlen > 1024) { - mif_debug("%s: %s txq->qlen %d > 1024\n", - ld->name, get_dev_name(dev), txq->qlen); - } - - if (!ipc_active(pld)) - goto exit; - - if (atomic_read(&pld->res_required[dev]) > 0) { - mif_debug("%s: %s_TXQ is full\n", ld->name, get_dev_name(dev)); - goto exit; - } - - ret = pld_try_ipc_tx(pld, dev); - if (ret > 0) { - mask = get_mask_send(pld, dev); - send_intr(pld, INT_NON_CMD(mask)); - } else if (ret == -ENOSPC) { - mask = get_mask_req_ack(pld, dev); - send_intr(pld, INT_NON_CMD(mask)); - mif_info("%s: Send REQ_ACK 0x%04X\n", ld->name, mask); - } else { - mif_info("%s: pld_try_ipc_tx fail (err %d)\n", ld->name, ret); - } - -exit: - return; -} - -static int pld_send(struct link_device *ld, struct io_device *iod, - struct sk_buff *skb) -{ - enum dev_format dev = iod->format; - int len = skb->len; - - switch (dev) { - case IPC_FMT: - case IPC_RAW: - case IPC_RFS: - if (likely(ld->mode == LINK_MODE_IPC)) { - pld_send_ipc(ld, dev, iod, skb); - } else { - mif_info("%s: ld->mode != LINK_MODE_IPC\n", ld->name); - dev_kfree_skb_any(skb); - } - return len; - - default: - mif_info("%s: ERR! no TXQ for %s\n", ld->name, iod->name); - dev_kfree_skb_any(skb); - return -ENODEV; - } -} - -static int pld_force_dump(struct link_device *ld, struct io_device *iod) -{ - struct pld_link_device *pld = to_pld_link_device(ld); - trigger_force_cp_crash(pld); - return 0; -} - -static int pld_dump_start(struct link_device *ld, struct io_device *iod) -{ - struct pld_link_device *pld = to_pld_link_device(ld); - - if (pld->ext_op && pld->ext_op->dump_start) - return pld->ext_op->dump_start(pld); - else - return -ENODEV; -} - -static int pld_dump_update(struct link_device *ld, struct io_device *iod, - unsigned long arg) -{ - struct pld_link_device *pld = to_pld_link_device(ld); - - if (pld->ext_op && pld->ext_op->dump_update) - return pld->ext_op->dump_update(pld, (void *)arg); - else - return -ENODEV; -} - -static int pld_ioctl(struct link_device *ld, struct io_device *iod, - unsigned int cmd, unsigned long arg) -{ - struct pld_link_device *pld = to_pld_link_device(ld); - int err = 0; - -/* - mif_info("%s: cmd 0x%08X\n", ld->name, cmd); -*/ - - switch (cmd) { - case IOCTL_DPRAM_INIT_STATUS: - mif_debug("%s: get dpram init status\n", ld->name); - return pld->init_status; - - default: - if (pld->ext_ioctl) { - err = pld->ext_ioctl(pld, iod, cmd, arg); - } else { - mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd); - err = -EINVAL; - } - - break; - } - - return err; -} - -static int pld_table_init(struct pld_link_device *pld) -{ - struct link_device *ld = &pld->ld; - u8 __iomem *dp_base; - int i; - - if (!pld->base) { - mif_info("%s: ERR! pld->base == NULL\n", ld->name); - return -EINVAL; - } - dp_base = pld->base; - - /* Map for IPC */ - if (pld->dpctl->ipc_map) { - memcpy(&pld->ipc_map, pld->dpctl->ipc_map, - sizeof(struct dpram_ipc_map)); - } - - pld->magic_ap2cp = pld->ipc_map.magic_ap2cp; - pld->access_ap2cp = pld->ipc_map.access_ap2cp; - - pld->magic_cp2ap = pld->ipc_map.magic_cp2ap; - pld->access_cp2ap = pld->ipc_map.access_cp2ap; - - pld->address_buffer = pld->ipc_map.address_buffer; - - for (i = 0; i < ld->max_ipc_dev; i++) - pld->dev[i] = &pld->ipc_map.dev[i]; - pld->mbx2ap = pld->ipc_map.mbx_cp2ap; - pld->mbx2cp = pld->ipc_map.mbx_ap2cp; - - /* Map for booting */ - if (pld->ext_op && pld->ext_op->init_boot_map) { - pld->ext_op->init_boot_map(pld); - } else { - pld->bt_map.magic = (u32 *)(dp_base); - pld->bt_map.buff = (u8 *)(dp_base + DP_BOOT_BUFF_OFFSET); - pld->bt_map.size = pld->size - 8; - } - - /* Map for download (FOTA, UDL, etc.) */ - if (pld->ext_op && pld->ext_op->init_dl_map) { - pld->ext_op->init_dl_map(pld); - } else { - pld->dl_map.magic = (u32 *)(dp_base); - pld->dl_map.buff = (u8 *)(dp_base + DP_DLOAD_BUFF_OFFSET); - } - - /* Map for upload mode */ - if (pld->ext_op && pld->ext_op->init_ul_map) { - pld->ext_op->init_ul_map(pld); - } else { - pld->ul_map.magic = (u32 *)(dp_base); - pld->ul_map.buff = (u8 *)(dp_base + DP_ULOAD_BUFF_OFFSET); - } - - return 0; -} - -static void pld_setup_common_op(struct pld_link_device *pld) -{ - pld->clear_intr = clear_intr; - pld->recv_intr = recv_intr; - pld->send_intr = send_intr; - pld->get_magic = get_magic; - pld->set_magic = set_magic; - pld->get_access = get_access; - pld->set_access = set_access; - pld->get_tx_head = get_tx_head; - pld->get_tx_tail = get_tx_tail; - pld->set_tx_head = set_tx_head; - pld->set_tx_tail = set_tx_tail; - pld->get_tx_buff = get_tx_buff; - pld->get_tx_buff_size = get_tx_buff_size; - pld->get_rx_head = get_rx_head; - pld->get_rx_tail = get_rx_tail; - pld->set_rx_head = set_rx_head; - pld->set_rx_tail = set_rx_tail; - pld->get_rx_buff = get_rx_buff; - pld->get_rx_buff_size = get_rx_buff_size; - pld->get_mask_req_ack = get_mask_req_ack; - pld->get_mask_res_ack = get_mask_res_ack; - pld->get_mask_send = get_mask_send; -} - -static int pld_link_init(struct link_device *ld, struct io_device *iod) -{ - return 0; -} - -static void pld_link_terminate(struct link_device *ld, struct io_device *iod) -{ - return; -} - -struct link_device *pld_create_link_device(struct platform_device *pdev) -{ - struct modem_data *mdm_data = NULL; - struct pld_link_device *pld = NULL; - struct link_device *ld = NULL; - struct resource *res = NULL; - resource_size_t res_size; - struct modemlink_dpram_control *dpctl = NULL; - unsigned long task_data; - int ret = 0; - int i = 0; - int bsize; - int qsize; - - /* Get the platform data */ - mdm_data = (struct modem_data *)pdev->dev.platform_data; - if (!mdm_data) { - mif_info("ERR! mdm_data == NULL\n"); - goto err; - } - mif_info("modem = %s\n", mdm_data->name); - mif_info("link device = %s\n", mdm_data->link_name); - - if (!mdm_data->dpram_ctl) { - mif_info("ERR! mdm_data->dpram_ctl == NULL\n"); - goto err; - } - dpctl = mdm_data->dpram_ctl; - - /* Alloc DPRAM link device structure */ - pld = kzalloc(sizeof(struct pld_link_device), GFP_KERNEL); - if (!pld) { - mif_info("ERR! kzalloc pld fail\n"); - goto err; - } - ld = &pld->ld; - - /* Retrieve modem data and DPRAM control data from the modem data */ - ld->mdm_data = mdm_data; - ld->name = mdm_data->link_name; - ld->ipc_version = mdm_data->ipc_version; - - /* Retrieve the most basic data for IPC from the modem data */ - pld->dpctl = dpctl; - pld->type = dpctl->dp_type; - - if (mdm_data->ipc_version < SIPC_VER_50) { - if (!dpctl->max_ipc_dev) { - mif_info("ERR! no max_ipc_dev\n"); - goto err; - } - - ld->aligned = dpctl->aligned; - ld->max_ipc_dev = dpctl->max_ipc_dev; - } else { - ld->aligned = 1; - ld->max_ipc_dev = MAX_SIPC5_DEV; - } - - /* Set attributes as a link device */ - ld->init_comm = pld_link_init; - ld->terminate_comm = pld_link_terminate; - ld->send = pld_send; - ld->force_dump = pld_force_dump; - ld->dump_start = pld_dump_start; - ld->dump_update = pld_dump_update; - ld->ioctl = pld_ioctl; - - 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; - - /* Set up function pointers */ - pld_setup_common_op(pld); - pld->ext_op = pld_get_ext_op(mdm_data->modem_type); - if (pld->ext_op && pld->ext_op->ioctl) - pld->ext_ioctl = pld->ext_op->ioctl; - - /* Retrieve DPRAM resource */ - if (!dpctl->dp_base) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - mif_info("%s: ERR! platform_get_resource fail\n", - ld->name); - goto err; - } - res_size = resource_size(res); - - dpctl->dp_base = ioremap_nocache(res->start, res_size); - dpctl->dp_size = res_size; - } - pld->base = dpctl->dp_base; - pld->size = dpctl->dp_size; - - mif_info("%s: type %d, aligned %d, base 0x%08X, size %d\n", - ld->name, pld->type, ld->aligned, (int)pld->base, pld->size); - - /* Initialize DPRAM map (physical map -> logical map) */ - ret = pld_table_init(pld); - if (ret < 0) { - mif_info("%s: ERR! pld_table_init fail (err %d)\n", - ld->name, ret); - goto err; - } - - spin_lock_init(&pld->pld_lock); - - /* Disable IPC */ - set_magic(pld, 0); - set_access(pld, 0); - - pld->init_status = DPRAM_INIT_STATE_NONE; - - /* Initialize locks, completions, and bottom halves */ - snprintf(pld->wlock_name, MIF_MAX_NAME_LEN, "%s_wlock", ld->name); - wake_lock_init(&pld->wlock, WAKE_LOCK_SUSPEND, pld->wlock_name); - - init_completion(&pld->dpram_init_cmd); - init_completion(&pld->modem_pif_init_done); - init_completion(&pld->udl_start_complete); - init_completion(&pld->udl_cmd_complete); - init_completion(&pld->crash_start_complete); - init_completion(&pld->crash_recv_done); - - task_data = (unsigned long)pld; - tasklet_init(&pld->rx_tsk, pld_ipc_rx_task, task_data); - - /* Prepare RXB queue */ - qsize = DPRAM_MAX_RXBQ_SIZE; - for (i = 0; i < ld->max_ipc_dev; i++) { - bsize = rxbq_get_page_size(get_rx_buff_size(pld, i)); - pld->rxbq[i].size = qsize; - pld->rxbq[i].in = 0; - pld->rxbq[i].out = 0; - pld->rxbq[i].rxb = rxbq_create_pool(bsize, qsize); - if (!pld->rxbq[i].rxb) { - mif_info("%s: ERR! %s rxbq_create_pool fail\n", - ld->name, get_dev_name(i)); - goto err; - } - mif_info("%s: %s rxbq_pool created (bsize:%d, qsize:%d)\n", - ld->name, get_dev_name(i), bsize, qsize); - } - - /* Prepare a multi-purpose miscellaneous buffer */ - pld->buff = kzalloc(pld->size, GFP_KERNEL); - if (!pld->buff) { - mif_info("%s: ERR! kzalloc pld->buff fail\n", ld->name); - goto err; - } - - /* Retrieve DPRAM IRQ GPIO# */ - pld->gpio_dpram_int = mdm_data->gpio_dpram_int; - - /* Retrieve DPRAM IRQ# */ - if (!dpctl->dpram_irq) { - dpctl->dpram_irq = platform_get_irq_byname(pdev, "dpram_irq"); - if (dpctl->dpram_irq < 0) { - mif_info("%s: ERR! platform_get_irq_byname fail\n", - ld->name); - goto err; - } - } - pld->irq = dpctl->dpram_irq; - - /* Retrieve DPRAM IRQ flags */ - if (!dpctl->dpram_irq_flags) - dpctl->dpram_irq_flags = (IRQF_NO_SUSPEND | IRQF_TRIGGER_LOW); - pld->irq_flags = dpctl->dpram_irq_flags; - - /* Register DPRAM interrupt handler */ - snprintf(pld->irq_name, MIF_MAX_NAME_LEN, "%s_irq", ld->name); - ret = pld_register_isr(pld->irq, pld_irq_handler, pld->irq_flags, - pld->irq_name, pld); - if (ret) - goto err; - - return ld; - -err: - if (pld) { - kfree(pld->buff); - kfree(pld); - } - - return NULL; -} - diff --git a/drivers/misc/modem_if/modem_link_device_pld.h b/drivers/misc/modem_if/modem_link_device_pld.h deleted file mode 100644 index 89c44b2a86b..00000000000 --- a/drivers/misc/modem_if/modem_link_device_pld.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - * 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. - * - */ -#ifndef __MODEM_LINK_DEVICE_PLD_H__ -#define __MODEM_LINK_DEVICE_PLD_H__ - -#include "modem_link_device_memory.h" - -#define PLD_ADDR_MASK(x) (0x00003FFF & (unsigned long)(x)) - -/* - mbx_ap2cp + 0x0 - magic_code + - access_enable + - padding + - mbx_cp2ap + 0x1000 - magic_code + - access_enable + - padding + - fmt_tx_head + fmt_tx_tail + fmt_tx_buff + 0x2000 - raw_tx_head + raw_tx_tail + raw_tx_buff + - fmt_rx_head + fmt_rx_tail + fmt_rx_buff + 0x3000 - raw_rx_head + raw_rx_tail + raw_rx_buff + - = 2 + - 4094 + - 2 + - 4094 + - 2 + - 2 + - 2 + 2 + 1020 + - 2 + 2 + 3064 + - 2 + 2 + 1020 + - 2 + 2 + 3064 - */ - -#define PLD_FMT_TX_BUFF_SZ 1024 -#define PLD_RAW_TX_BUFF_SZ 3072 -#define PLD_FMT_RX_BUFF_SZ 1024 -#define PLD_RAW_RX_BUFF_SZ 3072 - -#define MAX_MSM_EDPRAM_IPC_DEV 2 /* FMT, RAW */ - -struct pld_ipc_map { - u16 mbx_ap2cp; - u16 magic_ap2cp; - u16 access_ap2cp; - u16 fmt_tx_head; - u16 raw_tx_head; - u16 fmt_rx_tail; - u16 raw_rx_tail; - u16 temp1; - u8 padding1[4080]; - - u16 mbx_cp2ap; - u16 magic_cp2ap; - u16 access_cp2ap; - u16 fmt_tx_tail; - u16 raw_tx_tail; - u16 fmt_rx_head; - u16 raw_rx_head; - u16 temp2; - u8 padding2[4080]; - - u8 fmt_tx_buff[PLD_FMT_TX_BUFF_SZ]; - u8 raw_tx_buff[PLD_RAW_TX_BUFF_SZ]; - u8 fmt_rx_buff[PLD_RAW_TX_BUFF_SZ]; - u8 raw_rx_buff[PLD_RAW_RX_BUFF_SZ]; - - u8 padding3[16384]; - - u16 address_buffer; -}; - -struct pld_ext_op; - -struct pld_link_device { - struct link_device ld; - - /* DPRAM address and size */ - enum dpram_type type; /* DPRAM type */ - u8 __iomem *base; /* DPRAM base virtual address */ - u32 size; /* DPRAM size */ - - /* DPRAM IRQ GPIO# */ - unsigned gpio_dpram_int; - - /* DPRAM IRQ from CP */ - int irq; - unsigned long irq_flags; - char irq_name[MIF_MAX_NAME_LEN]; - - /* Link to DPRAM control functions dependent on each platform */ - struct modemlink_dpram_control *dpctl; - - /* Physical configuration -> logical configuration */ - union { - struct dpram_boot_map bt_map; - struct qc_dpram_boot_map qc_bt_map; - }; - - struct dpram_dload_map dl_map; - struct dpram_uload_map ul_map; - - /* IPC device map */ - struct dpram_ipc_map ipc_map; - - /* Pointers (aliases) to IPC device map */ - u16 __iomem *magic_ap2cp; - u16 __iomem *access_ap2cp; - u16 __iomem *magic_cp2ap; - u16 __iomem *access_cp2ap; - u16 __iomem *address_buffer; - - struct dpram_ipc_device *dev[MAX_IPC_DEV]; - u16 __iomem *mbx2ap; - u16 __iomem *mbx2cp; - - /* Wakelock for DPRAM device */ - struct wake_lock wlock; - char wlock_name[MIF_MAX_NAME_LEN]; - - /* For booting */ - unsigned boot_start_complete; - struct completion dpram_init_cmd; - struct completion modem_pif_init_done; - - /* For UDL */ - struct tasklet_struct ul_tsk; - struct tasklet_struct dl_tsk; - struct completion udl_start_complete; - struct completion udl_cmd_complete; - struct dpram_udl_check udl_check; - struct dpram_udl_param udl_param; - - /* For CP crash dump */ - struct timer_list crash_ack_timer; - struct completion crash_start_complete; - struct completion crash_recv_done; - struct timer_list crash_timer; - int crash_rcvd; /* Count of CP crash dump packets received */ - - /* For locking TX process */ - spinlock_t tx_rx_lock; - spinlock_t pld_lock; - - /* For efficient RX process */ - struct tasklet_struct rx_tsk; - struct mif_rxb_queue rxbq[MAX_IPC_DEV]; - struct io_device *iod[MAX_IPC_DEV]; - - /* For retransmission after buffer full state */ - atomic_t res_required[MAX_IPC_DEV]; - - /* For wake-up/sleep control */ - atomic_t accessing; - - /* Multi-purpose miscellaneous buffer */ - u8 *buff; - - /* PLD IPC initialization status */ - int init_status; - - /* Alias to device-specific IOCTL function */ - int (*ext_ioctl)(struct pld_link_device *pld, struct io_device *iod, - unsigned int cmd, unsigned long arg); - - /* Common operations for each DPRAM */ - void (*clear_intr)(struct pld_link_device *pld); - u16 (*recv_intr)(struct pld_link_device *pld); - void (*send_intr)(struct pld_link_device *pld, u16 mask); - u16 (*get_magic)(struct pld_link_device *pld); - void (*set_magic)(struct pld_link_device *pld, u16 value); - u16 (*get_access)(struct pld_link_device *pld); - void (*set_access)(struct pld_link_device *pld, u16 value); - u32 (*get_tx_head)(struct pld_link_device *pld, int id); - u32 (*get_tx_tail)(struct pld_link_device *pld, int id); - void (*set_tx_head)(struct pld_link_device *pld, int id, u32 head); - void (*set_tx_tail)(struct pld_link_device *pld, int id, u32 tail); - u8 *(*get_tx_buff)(struct pld_link_device *pld, int id); - u32 (*get_tx_buff_size)(struct pld_link_device *pld, int id); - u32 (*get_rx_head)(struct pld_link_device *pld, int id); - u32 (*get_rx_tail)(struct pld_link_device *pld, int id); - void (*set_rx_head)(struct pld_link_device *pld, int id, u32 head); - void (*set_rx_tail)(struct pld_link_device *pld, int id, u32 tail); - u8 *(*get_rx_buff)(struct pld_link_device *pld, int id); - u32 (*get_rx_buff_size)(struct pld_link_device *pld, int id); - u16 (*get_mask_req_ack)(struct pld_link_device *pld, int id); - u16 (*get_mask_res_ack)(struct pld_link_device *pld, int id); - u16 (*get_mask_send)(struct pld_link_device *pld, int id); - - /* Extended operations for various modems */ - struct pld_ext_op *ext_op; -}; - -/* converts from struct link_device* to struct xxx_link_device* */ -#define to_pld_link_device(linkdev) \ - container_of(linkdev, struct pld_link_device, ld) - -struct pld_ext_op { - int exist; - - void (*init_boot_map)(struct pld_link_device *pld); - void (*init_dl_map)(struct pld_link_device *pld); - void (*init_ul_map)(struct pld_link_device *pld); - - void (*dload_cmd_handler)(struct pld_link_device *pld, u16 cmd); - - void (*cp_start_handler)(struct pld_link_device *pld); - - void (*crash_log)(struct pld_link_device *pld); - int (*dump_start)(struct pld_link_device *pld); - int (*dump_update)(struct pld_link_device *pld, void *arg); - - int (*ioctl)(struct pld_link_device *pld, struct io_device *iod, - unsigned int cmd, unsigned long arg); - - void (*clear_intr)(struct pld_link_device *pld); -}; - -struct pld_ext_op *pld_get_ext_op(enum modem_t modem); -#endif diff --git a/drivers/misc/modem_if/modem_link_device_pld_ext_op.c b/drivers/misc/modem_if/modem_link_device_pld_ext_op.c deleted file mode 100644 index 4f2df8f447a..00000000000 --- a/drivers/misc/modem_if/modem_link_device_pld_ext_op.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - * 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/kallsyms.h> -#include <linux/platform_data/modem.h> - -#include "modem_prj.h" -#include "modem_link_device_pld.h" -#include "modem_utils.h" - -#if defined(CONFIG_CDMA_MODEM_MDM6600) || defined(CONFIG_GSM_MODEM_ESC6270) -enum qc_dload_tag { - QC_DLOAD_TAG_NONE = 0, - QC_DLOAD_TAG_BIN, - QC_DLOAD_TAG_NV, - QC_DLOAD_TAG_MAX -}; - -static void qc_dload_task(unsigned long data); - -static void qc_init_boot_map(struct pld_link_device *pld) -{ - struct qc_dpram_boot_map *qbt_map = &pld->qc_bt_map; - struct modemlink_dpram_control *dpctl = pld->dpctl; - - qbt_map->buff = pld->dev[0]->txq.buff; - qbt_map->frame_size = (u16 *)(pld->base + dpctl->boot_size_offset); - qbt_map->tag = (u16 *)(pld->base + dpctl->boot_tag_offset); - qbt_map->count = (u16 *)(pld->base + dpctl->boot_count_offset); - - tasklet_init(&pld->dl_tsk, qc_dload_task, (unsigned long)pld); -} - -static void qc_dload_map(struct pld_link_device *pld, u8 is_upload) -{ - struct qc_dpram_boot_map *qbt_map = &pld->qc_bt_map; - struct modemlink_dpram_control *dpctl = pld->dpctl; - unsigned int upload_offset = 0; - - if (is_upload == 1) { - upload_offset = 0x1000; - qbt_map->buff = pld->dev[0]->rxq.buff; - } else { - upload_offset = 0; - qbt_map->buff = pld->dev[0]->txq.buff; - } - - qbt_map->frame_size = (u16 *)(pld->base + - dpctl->boot_size_offset + upload_offset); - qbt_map->tag = (u16 *)(pld->base + - dpctl->boot_tag_offset + upload_offset); - qbt_map->count = (u16 *)(pld->base + - dpctl->boot_count_offset + upload_offset); - -} - -static int qc_prepare_download(struct pld_link_device *pld) -{ - int retval = 0; - int count = 0; - - qc_dload_map(pld, 0); - - while (1) { - if (pld->udl_check.copy_start) { - pld->udl_check.copy_start = 0; - break; - } - - usleep_range(10000, 11000); - - count++; - if (count > 1000) { - mif_err("ERR! count %d\n", count); - return -1; - } - } - - return retval; -} - -static void _qc_do_download(struct pld_link_device *pld, - struct dpram_udl_param *param) -{ - struct qc_dpram_boot_map *qbt_map = &pld->qc_bt_map; - - if (param->size <= pld->dpctl->max_boot_frame_size) { - iowrite16(PLD_ADDR_MASK(&qbt_map->buff[0]), - pld->address_buffer); - memcpy(pld->base, param->addr, param->size); - - iowrite16(PLD_ADDR_MASK(&qbt_map->frame_size[0]), - pld->address_buffer); - iowrite16(param->size, pld->base); - - iowrite16(PLD_ADDR_MASK(&qbt_map->tag[0]), - pld->address_buffer); - iowrite16(param->tag, pld->base); - - iowrite16(PLD_ADDR_MASK(&qbt_map->count[0]), - pld->address_buffer); - iowrite16(param->count, pld->base); - - pld->send_intr(pld, 0xDB12); - } else { - mif_info("param->size %d\n", param->size); - } -} - -static int _qc_download(struct pld_link_device *pld, void *arg, - enum qc_dload_tag tag) -{ - int retval = 0; - int count = 0; - int cnt_limit; - unsigned char *img; - struct dpram_udl_param param; - - retval = copy_from_user((void *)¶m, (void *)arg, sizeof(param)); - if (retval < 0) { - mif_err("ERR! copy_from_user fail\n"); - return -1; - } - - img = vmalloc(param.size); - if (!img) { - mif_err("ERR! vmalloc fail\n"); - return -1; - } - memset(img, 0, param.size); - memcpy(img, param.addr, param.size); - - pld->udl_check.total_size = param.size; - pld->udl_check.rest_size = param.size; - pld->udl_check.send_size = 0; - pld->udl_check.copy_complete = 0; - - pld->udl_param.addr = img; - pld->udl_param.size = pld->dpctl->max_boot_frame_size; - if (tag == QC_DLOAD_TAG_NV) - pld->udl_param.count = 1; - else - pld->udl_param.count = param.count; - pld->udl_param.tag = tag; - - if (pld->udl_check.rest_size < pld->dpctl->max_boot_frame_size) - pld->udl_param.size = pld->udl_check.rest_size; - - /* Download image (binary or NV) */ - _qc_do_download(pld, &pld->udl_param); - - /* Wait for completion - */ - if (tag == QC_DLOAD_TAG_NV) - cnt_limit = 200; - else - cnt_limit = 1000; - - while (1) { - if (pld->udl_check.copy_complete) { - pld->udl_check.copy_complete = 0; - retval = 0; - break; - } - - usleep_range(10000, 11000); - - count++; - if (count > cnt_limit) { - mif_err("ERR! count %d\n", count); - retval = -1; - break; - } - } - - vfree(img); - - return retval; -} - -static int qc_download_bin(struct pld_link_device *pld, void *arg) -{ - return _qc_download(pld, arg, QC_DLOAD_TAG_BIN); -} - -static int qc_download_nv(struct pld_link_device *pld, void *arg) -{ - return _qc_download(pld, arg, QC_DLOAD_TAG_NV); -} - -static void qc_dload_task(unsigned long data) -{ - struct pld_link_device *pld = (struct pld_link_device *)data; - - pld->udl_check.send_size += pld->udl_param.size; - pld->udl_check.rest_size -= pld->udl_param.size; - - pld->udl_param.addr += pld->udl_param.size; - - if (pld->udl_check.send_size >= pld->udl_check.total_size) { - pld->udl_check.copy_complete = 1; - pld->udl_param.tag = 0; - return; - } - - if (pld->udl_check.rest_size < pld->dpctl->max_boot_frame_size) - pld->udl_param.size = pld->udl_check.rest_size; - - pld->udl_param.count += 1; - - _qc_do_download(pld, &pld->udl_param); -} - -static void qc_dload_cmd_handler(struct pld_link_device *pld, u16 cmd) -{ - switch (cmd) { - case 0x1234: - pld->udl_check.copy_start = 1; - break; - - case 0xDBAB: - tasklet_schedule(&pld->dl_tsk); - break; - - case 0xABCD: - mif_info("[%s] booting Start\n", pld->ld.name); - pld->udl_check.boot_complete = 1; - break; - - default: - mif_err("ERR! unknown command 0x%04X\n", cmd); - } -} - -static int qc_boot_start(struct pld_link_device *pld) -{ - u16 mask = 0; - int count = 0; - - /* Send interrupt -> '0x4567' */ - mask = 0x4567; - pld->send_intr(pld, mask); - - while (1) { - if (pld->udl_check.boot_complete) { - pld->udl_check.boot_complete = 0; - break; - } - - usleep_range(10000, 11000); - - count++; - if (count > 200) { - mif_err("ERR! count %d\n", count); - return -1; - } - } - - return 0; -} - -static int qc_boot_post_process(struct pld_link_device *pld) -{ - int count = 0; - - while (1) { - if (pld->boot_start_complete) { - pld->boot_start_complete = 0; - break; - } - - usleep_range(10000, 11000); - - count++; - if (count > 200) { - mif_err("ERR! count %d\n", count); - return -1; - } - } - - return 0; -} - -static void qc_start_handler(struct pld_link_device *pld) -{ - /* - * INT_MASK_VALID | INT_MASK_CMD | INT_MASK_CP_AIRPLANE_BOOT | - * INT_MASK_CP_AP_ANDROID | INT_MASK_CMD_INIT_END - */ - u16 mask = (0x0080 | 0x0040 | 0x1000 | 0x0100 | 0x0002); - - pld->boot_start_complete = 1; - - /* Send INIT_END code to CP */ - mif_info("send 0x%04X (INIT_END)\n", mask); - - pld->send_intr(pld, mask); -} - -static void qc_crash_log(struct pld_link_device *pld) -{ - struct link_device *ld = &pld->ld; - static unsigned char buf[151]; - u8 __iomem *data = NULL; - - data = pld->get_rx_buff(pld, IPC_FMT); - memcpy(buf, data, (sizeof(buf) - 1)); - - mif_info("PHONE ERR MSG\t| %s Crash\n", ld->mdm_data->name); - mif_info("PHONE ERR MSG\t| %s\n", buf); -} - -static int _qc_data_upload(struct pld_link_device *pld, - struct dpram_udl_param *param) -{ - struct qc_dpram_boot_map *qbt_map = &pld->qc_bt_map; - int retval = 0; - u16 intval = 0; - int count = 0; - - while (1) { - if (!gpio_get_value(pld->gpio_dpram_int)) { - intval = pld->recv_intr(pld); - if (intval == 0xDBAB) { - break; - } else { - mif_err("intr 0x%08x\n", intval); - return -1; - } - } - - usleep_range(1000, 2000); - - count++; - if (count > 200) { - mif_err("<%s:%d>\n", __func__, __LINE__); - return -1; - } - } - - iowrite16(PLD_ADDR_MASK(&qbt_map->frame_size[0]), - pld->address_buffer); - param->size = ioread16(pld->base); - - iowrite16(PLD_ADDR_MASK(&qbt_map->tag[0]), - pld->address_buffer); - param->tag = ioread16(pld->base); - - iowrite16(PLD_ADDR_MASK(&qbt_map->count[0]), - pld->address_buffer); - param->count = ioread16(pld->base); - - iowrite16(PLD_ADDR_MASK(&qbt_map->buff[0]), - pld->address_buffer); - memcpy(param->addr, pld->base, param->size); - - pld->send_intr(pld, 0xDB12); - - return retval; -} - -static int qc_uload_step1(struct pld_link_device *pld) -{ - int retval = 0; - int count = 0; - u16 intval = 0; - u16 mask = 0; - - qc_dload_map(pld, 1); - - mif_info("+---------------------------------------------+\n"); - mif_info("| UPLOAD PHONE SDRAM |\n"); - mif_info("+---------------------------------------------+\n"); - - while (1) { - if (!gpio_get_value(pld->gpio_dpram_int)) { - intval = pld->recv_intr(pld); - mif_info("intr 0x%04x\n", intval); - if (intval == 0x1234) { - break; - } else { - mif_info("ERR! invalid intr\n"); - return -1; - } - } - - usleep_range(1000, 2000); - - count++; - if (count > 200) { - intval = pld->recv_intr(pld); - mif_info("count %d, intr 0x%04x\n", count, intval); - if (intval == 0x1234) - break; - return -1; - } - } - - mask = 0xDEAD; - pld->send_intr(pld, mask); - - return retval; -} - -static int qc_uload_step2(struct pld_link_device *pld, void *arg) -{ - int retval = 0; - struct dpram_udl_param param; - - retval = copy_from_user((void *)¶m, (void *)arg, sizeof(param)); - if (retval < 0) { - mif_err("ERR! copy_from_user fail (err %d)\n", retval); - return -1; - } - - retval = _qc_data_upload(pld, ¶m); - if (retval < 0) { - mif_err("ERR! _qc_data_upload fail (err %d)\n", retval); - return -1; - } - - if (!(param.count % 500)) - mif_info("param->count = %d\n", param.count); - - if (param.tag == 4) { - enable_irq(pld->irq); - mif_info("param->tag = %d\n", param.tag); - } - - retval = copy_to_user((unsigned long *)arg, ¶m, sizeof(param)); - if (retval < 0) { - mif_err("ERR! copy_to_user fail (err %d)\n", retval); - return -1; - } - - return retval; -} - -static int qc_ioctl(struct pld_link_device *pld, struct io_device *iod, - unsigned int cmd, unsigned long arg) -{ - struct link_device *ld = &pld->ld; - int err = 0; - - switch (cmd) { - case IOCTL_DPRAM_PHONE_POWON: - err = qc_prepare_download(pld); - if (err < 0) - mif_info("%s: ERR! prepare_download fail\n", ld->name); - break; - - case IOCTL_DPRAM_PHONEIMG_LOAD: - err = qc_download_bin(pld, (void *)arg); - if (err < 0) - mif_info("%s: ERR! download_bin fail\n", ld->name); - break; - - case IOCTL_DPRAM_NVDATA_LOAD: - err = qc_download_nv(pld, (void *)arg); - if (err < 0) - mif_info("%s: ERR! download_nv fail\n", ld->name); - break; - - case IOCTL_DPRAM_PHONE_BOOTSTART: - err = qc_boot_start(pld); - if (err < 0) { - mif_info("%s: ERR! boot_start fail\n", ld->name); - break; - } - - err = qc_boot_post_process(pld); - if (err < 0) - mif_info("%s: ERR! boot_post_process fail\n", ld->name); - - break; - - case IOCTL_DPRAM_PHONE_UPLOAD_STEP1: - disable_irq_nosync(pld->irq); - err = qc_uload_step1(pld); - if (err < 0) { - enable_irq(pld->irq); - mif_info("%s: ERR! upload_step1 fail\n", ld->name); - } - break; - - case IOCTL_DPRAM_PHONE_UPLOAD_STEP2: - err = qc_uload_step2(pld, (void *)arg); - if (err < 0) { - enable_irq(pld->irq); - mif_info("%s: ERR! upload_step2 fail\n", ld->name); - } - break; - - default: - mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd); - err = -EINVAL; - break; - } - - return err; -} -#endif - -static struct pld_ext_op ext_op_set[] = { -#if defined(CONFIG_CDMA_MODEM_MDM6600) - [QC_MDM6600] = { - .exist = 1, - .init_boot_map = qc_init_boot_map, - .dload_cmd_handler = qc_dload_cmd_handler, - .cp_start_handler = qc_start_handler, - .crash_log = qc_crash_log, - .ioctl = qc_ioctl, - }, -#endif -#if defined(CONFIG_GSM_MODEM_ESC6270) - [QC_ESC6270] = { - .exist = 1, - .init_boot_map = qc_init_boot_map, - .dload_cmd_handler = qc_dload_cmd_handler, - .cp_start_handler = qc_start_handler, - .crash_log = qc_crash_log, - .ioctl = qc_ioctl, - }, -#endif -}; - -struct pld_ext_op *pld_get_ext_op(enum modem_t modem) -{ - if (ext_op_set[modem].exist) - return &ext_op_set[modem]; - else - return NULL; -} diff --git a/drivers/misc/modem_if/modem_link_device_usb.c b/drivers/misc/modem_if/modem_link_device_usb.c deleted file mode 100644 index 5b7c98bebea..00000000000 --- a/drivers/misc/modem_if/modem_link_device_usb.c +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * Copyright (C) 2010 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. - * - */ - -#define DEBUG - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/sched.h> -#include <linux/irq.h> -#include <linux/poll.h> -#include <linux/gpio.h> -#include <linux/if_arp.h> -#include <linux/platform_device.h> -#include <linux/suspend.h> - -#include <linux/platform_data/modem.h> -#include "modem_prj.h" -#include "modem_link_device_usb.h" -#include "modem_utils.h" -#include "modem_link_pm_usb.h" - -#include <mach/regs-gpio.h> - -#define URB_COUNT 4 - -static int usb_tx_urb_with_skb(struct usb_link_device *usb_ld, - struct sk_buff *skb, struct if_usb_devdata *pipe_data); - -static void -usb_free_urbs(struct usb_link_device *usb_ld, struct if_usb_devdata *pipe) -{ - struct usb_device *usbdev = usb_ld->usbdev; - struct urb *urb; - - while ((urb = usb_get_from_anchor(&pipe->urbs))) { - usb_poison_urb(urb); - usb_free_coherent(usbdev, pipe->rx_buf_size, - urb->transfer_buffer, urb->transfer_dma); - urb->transfer_buffer = NULL; - usb_put_urb(urb); - usb_free_urb(urb); - } -} - -static int start_ipc(struct link_device *ld, struct io_device *iod) -{ - struct sk_buff *skb; - char data[1] = {'a'}; - int err; - struct usb_link_device *usb_ld = to_usb_link_device(ld); - struct if_usb_devdata *pipe_data = &usb_ld->devdata[IF_USB_FMT_EP]; - - if (has_hub(usb_ld) && usb_ld->link_pm_data->hub_handshake_done) { - mif_err("Already send start ipc, skip start ipc\n"); - err = 0; - goto exit; - } - - if (!usb_ld->if_usb_connected) { - mif_err("HSIC/USB not connected, skip start ipc\n"); - err = -ENODEV; - goto exit; - } - - if (has_hub(usb_ld) && - usb_ld->if_usb_initstates == INIT_IPC_START_DONE) { - mif_debug("Already IPC started\n"); - err = 0; - goto exit; - } - - mif_info("send 'a'\n"); - - skb = alloc_skb(16, GFP_ATOMIC); - if (unlikely(!skb)) - return -ENOMEM; - memcpy(skb_put(skb, 1), data, 1); - - skbpriv(skb)->iod = iod; - skbpriv(skb)->ld = &usb_ld->ld; - err = usb_tx_urb_with_skb(usb_ld, skb, pipe_data); - if (err < 0) { - mif_err("usb_tx_urb fail\n"); - goto exit; - } - usb_ld->link_pm_data->hub_handshake_done = true; - usb_ld->if_usb_initstates = INIT_IPC_START_DONE; -exit: - return err; -} - -static int usb_init_communication(struct link_device *ld, - struct io_device *iod) -{ - int err = 0; - switch (iod->format) { - case IPC_BOOT: - ld->com_state = COM_BOOT; - skb_queue_purge(&ld->sk_fmt_tx_q); - break; - - case IPC_RAMDUMP: - ld->com_state = COM_CRASH; - break; - - case IPC_FMT: - err = start_ipc(ld, iod); - break; - - case IPC_RFS: - case IPC_RAW: - - default: - ld->com_state = COM_ONLINE; - break; - } - - mif_debug("com_state = %d\n", ld->com_state); - return err; -} - -static void usb_terminate_communication( - struct link_device *ld, struct io_device *iod) -{ - mif_debug("com_state = %d\n", ld->com_state); -} - -static int usb_rx_submit(struct if_usb_devdata *pipe, struct urb *urb, - gfp_t gfp_flags) -{ - int ret; - - usb_anchor_urb(urb, &pipe->reading); - ret = usb_submit_urb(urb, gfp_flags); - if (ret) { - usb_unanchor_urb(urb); - usb_anchor_urb(urb, &pipe->urbs); - mif_err("submit urb fail with ret (%d)\n", ret); - } - - usb_mark_last_busy(urb->dev); - return ret; -} - -static void usb_rx_complete(struct urb *urb) -{ - struct if_usb_devdata *pipe_data = urb->context; - struct usb_link_device *usb_ld = usb_get_intfdata(pipe_data->data_intf); - struct io_device *iod; - int iod_format = IPC_FMT; - int ret; - - usb_mark_last_busy(urb->dev); - - switch (urb->status) { - case 0: - case -ENOENT: - if (!urb->actual_length) - goto re_submit; - /* call iod recv */ - /* how we can distinguish boot ch with fmt ch ?? */ - switch (pipe_data->format) { - case IF_USB_FMT_EP: - iod_format = IPC_FMT; - pr_buffer("rx", (char *)urb->transfer_buffer, - (size_t)urb->actual_length, 16); - break; - case IF_USB_RAW_EP: - iod_format = IPC_MULTI_RAW; - break; - case IF_USB_RFS_EP: - iod_format = IPC_RFS; - break; - default: - break; - } - - /* during boot stage fmt end point */ - /* shared with boot io device */ - /* when we use fmt device only, at boot and ipc exchange - it can be reduced to 1 device */ - if (iod_format == IPC_FMT && - usb_ld->ld.com_state == COM_BOOT) - iod_format = IPC_BOOT; - if (iod_format == IPC_FMT && - usb_ld->ld.com_state == COM_CRASH) - iod_format = IPC_RAMDUMP; - - iod = link_get_iod_with_format(&usb_ld->ld, iod_format); - if (iod) { - ret = iod->recv(iod, - &usb_ld->ld, - (char *)urb->transfer_buffer, - urb->actual_length); - if (ret < 0) - mif_err("io device recv error :%d\n", ret); - } -re_submit: - if (urb->status || atomic_read(&usb_ld->suspend_count)) - break; - - usb_mark_last_busy(urb->dev); - usb_rx_submit(pipe_data, urb, GFP_ATOMIC); - return; - case -ESHUTDOWN: - case -EPROTO: - break; - case -EOVERFLOW: - mif_err("RX overflow\n"); - break; - default: - mif_err("RX complete Status (%d)\n", urb->status); - break; - } - - usb_anchor_urb(urb, &pipe_data->urbs); -} - -static int usb_send(struct link_device *ld, struct io_device *iod, - struct sk_buff *skb) -{ - struct sk_buff_head *txq; - size_t tx_size; - - if (iod->format == IPC_RAW) - txq = &ld->sk_raw_tx_q; - else - txq = &ld->sk_fmt_tx_q; - - /* store the tx size before run the tx_delayed_work*/ - tx_size = skb->len; - - /* en queue skb data */ - skb_queue_tail(txq, skb); - - queue_delayed_work(ld->tx_wq, &ld->tx_delayed_work, 0); - - return tx_size; -} - -static void usb_tx_complete(struct urb *urb) -{ - int ret = 0; - struct sk_buff *skb = urb->context; - - switch (urb->status) { - case 0: - break; - default: - mif_err("TX error (%d)\n", urb->status); - } - - usb_mark_last_busy(urb->dev); - ret = pm_runtime_put_autosuspend(&urb->dev->dev); - if (ret < 0 && ret != -EAGAIN) - mif_debug("pm_runtime_put_autosuspend failed: %d\n", ret); - usb_free_urb(urb); - dev_kfree_skb_any(skb); -} - -static void if_usb_force_disconnect(struct work_struct *work) -{ - struct usb_link_device *usb_ld = - container_of(work, struct usb_link_device, disconnect_work); - struct usb_device *udev = usb_ld->usbdev; - - /* if already disconnected before run this workqueue */ - if (!udev || !(&udev->dev) || !usb_ld->if_usb_connected) - return; - - /* disconnect udev's parent if usb hub used */ - if (has_hub(usb_ld)) - udev = udev->parent; - - pm_runtime_get_sync(&udev->dev); - if (udev->state != USB_STATE_NOTATTACHED) { - usb_force_disconnect(udev); - mif_info("force disconnect\n"); - } - pm_runtime_put_autosuspend(&udev->dev); -} - -static void -usb_change_modem_state(struct usb_link_device *usb_ld, enum modem_state state) -{ - struct io_device *iod; - - iod = link_get_iod_with_format(&usb_ld->ld, IPC_FMT); - if (iod) - iod->modem_state_changed(iod, state); -} - -static int usb_tx_urb_with_skb(struct usb_link_device *usb_ld, - struct sk_buff *skb, struct if_usb_devdata *pipe_data) -{ - int ret, cnt = 0; - struct urb *urb; - struct usb_device *usbdev = usb_ld->usbdev; - unsigned long flags; - - if (!usbdev || (usbdev->state == USB_STATE_NOTATTACHED) || - usb_ld->host_wake_timeout_flag) - return -ENODEV; - - pm_runtime_get_noresume(&usbdev->dev); - - if (usbdev->dev.power.runtime_status == RPM_SUSPENDED || - usbdev->dev.power.runtime_status == RPM_SUSPENDING) { - usb_ld->resume_status = AP_INITIATED_RESUME; - SET_SLAVE_WAKEUP(usb_ld->pdata, 1); - - while (!wait_event_interruptible_timeout(usb_ld->l2_wait, - usbdev->dev.power.runtime_status == RPM_ACTIVE - || pipe_data->disconnected, - HOST_WAKEUP_TIMEOUT_JIFFIES)) { - - if (cnt == MAX_RETRY) { - mif_err("host wakeup timeout !!\n"); - SET_SLAVE_WAKEUP(usb_ld->pdata, 0); - pm_runtime_put_autosuspend(&usbdev->dev); - schedule_work(&usb_ld->disconnect_work); - usb_ld->host_wake_timeout_flag = 1; - return -1; - } - mif_err("host wakeup timeout ! retry..\n"); - SET_SLAVE_WAKEUP(usb_ld->pdata, 0); - udelay(100); - SET_SLAVE_WAKEUP(usb_ld->pdata, 1); - cnt++; - } - - if (pipe_data->disconnected) { - SET_SLAVE_WAKEUP(usb_ld->pdata, 0); - pm_runtime_put_autosuspend(&usbdev->dev); - return -ENODEV; - } - - mif_debug("wait_q done (runtime_status=%d)\n", - usbdev->dev.power.runtime_status); - } - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - mif_err("alloc urb error\n"); - if (pm_runtime_put_autosuspend(&usbdev->dev) < 0) - mif_debug("pm_runtime_put_autosuspend fail\n"); - return -ENOMEM; - } - - urb->transfer_flags = URB_ZERO_PACKET; - usb_fill_bulk_urb(urb, usbdev, pipe_data->tx_pipe, skb->data, - skb->len, usb_tx_complete, (void *)skb); - - spin_lock_irqsave(&usb_ld->lock, flags); - if (atomic_read(&usb_ld->suspend_count)) { - /* transmission will be done in resume */ - usb_anchor_urb(urb, &usb_ld->deferred); - usb_put_urb(urb); - mif_debug("anchor urb (0x%p)\n", urb); - spin_unlock_irqrestore(&usb_ld->lock, flags); - return 0; - } - spin_unlock_irqrestore(&usb_ld->lock, flags); - - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret < 0) { - mif_err("usb_submit_urb with ret(%d)\n", ret); - if (pm_runtime_put_autosuspend(&usbdev->dev) < 0) - mif_debug("pm_runtime_put_autosuspend fail\n"); - } - return ret; -} - -static void usb_tx_work(struct work_struct *work) -{ - int ret = 0; - struct link_device *ld = - container_of(work, struct link_device, tx_delayed_work.work); - struct usb_link_device *usb_ld = to_usb_link_device(ld); - struct io_device *iod; - struct sk_buff *skb; - struct if_usb_devdata *pipe_data; - struct link_pm_data *pm_data = usb_ld->link_pm_data; - - /*TODO: check the PHONE ACTIVE STATES */ - /* because tx data wait until hub on with wait_for_complettion, it - should queue to single_threaded work queue */ - if (!link_pm_set_active(usb_ld)) - return; - - while (ld->sk_fmt_tx_q.qlen || ld->sk_raw_tx_q.qlen) { - /* send skb from fmt_txq and raw_txq, - * one by one for fair flow control */ - skb = skb_dequeue(&ld->sk_fmt_tx_q); - if (skb) { - iod = skbpriv(skb)->iod; - switch (iod->format) { - case IPC_BOOT: - case IPC_RAMDUMP: - case IPC_FMT: - /* boot device uses same intf with fmt*/ - pipe_data = &usb_ld->devdata[IF_USB_FMT_EP]; - break; - case IPC_RFS: - pipe_data = &usb_ld->devdata[IF_USB_RFS_EP]; - break; - default: - /* wrong packet for fmt tx q , drop it */ - dev_kfree_skb_any(skb); - continue; - } - - ret = usb_tx_urb_with_skb(usb_ld, skb, pipe_data); - if (ret < 0) { - mif_err("usb_tx_urb_with_skb, ret(%d)\n", - ret); - skb_queue_head(&ld->sk_fmt_tx_q, skb); - return; - } - } - - skb = skb_dequeue(&ld->sk_raw_tx_q); - if (skb) { - pipe_data = &usb_ld->devdata[IF_USB_RAW_EP]; - ret = usb_tx_urb_with_skb(usb_ld, skb, pipe_data); - if (ret < 0) { - mif_err("usb_tx_urb_with_skb " - "for raw, ret(%d)\n", - ret); - skb_queue_head(&ld->sk_raw_tx_q, skb); - return; - } - } - } -} - -static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct usb_link_device *usb_ld = usb_get_intfdata(intf); - struct link_pm_data *pm_data = usb_ld->link_pm_data; - int i; - - if (atomic_inc_return(&usb_ld->suspend_count) == IF_USB_DEVNUM_MAX) { - mif_debug("L2\n"); - - for (i = 0; i < IF_USB_DEVNUM_MAX; i++) - usb_kill_anchored_urbs(&usb_ld->devdata[i].reading); - - if (pm_data->freq_unlock) - pm_data->freq_unlock(&usb_ld->usbdev->dev); - - wake_unlock(&usb_ld->susplock); - } - - return 0; -} - -static void runtime_pm_work(struct work_struct *work) -{ - struct usb_link_device *usb_ld = container_of(work, - struct usb_link_device, runtime_pm_work.work); - int ret; - - ret = pm_request_autosuspend(&usb_ld->usbdev->dev); - - if (ret == -EAGAIN || ret == 1) - queue_delayed_work(system_nrt_wq, &usb_ld->runtime_pm_work, - msecs_to_jiffies(50)); -} - -static void post_resume_work(struct work_struct *work) -{ - struct usb_link_device *usb_ld = container_of(work, - struct usb_link_device, post_resume_work.work); - struct link_pm_data *pm_data = usb_ld->link_pm_data; - struct usb_device *udev = usb_ld->usbdev; - - /* if already disconnected before run this workqueue */ - if (!udev || !(&udev->dev) || !usb_ld->if_usb_connected) - return; - - /* lock cpu/bus frequency when L2->L0 */ - if (pm_data->freq_lock) - pm_data->freq_lock(&udev->dev); -} - -static void wait_enumeration_work(struct work_struct *work) -{ - struct usb_link_device *usb_ld = container_of(work, - struct usb_link_device, wait_enumeration.work); - if (usb_ld->if_usb_connected == 0) { - mif_err("USB disconnected and not enumerated for long time\n"); - usb_change_modem_state(usb_ld, STATE_CRASH_EXIT); - } -} - -static int if_usb_resume(struct usb_interface *intf) -{ - int i, ret; - struct sk_buff *skb; - struct usb_link_device *usb_ld = usb_get_intfdata(intf); - struct if_usb_devdata *pipe; - struct urb *urb; - - spin_lock_irq(&usb_ld->lock); - if (!atomic_dec_return(&usb_ld->suspend_count)) { - spin_unlock_irq(&usb_ld->lock); - - mif_debug("\n"); - wake_lock(&usb_ld->susplock); - - /* HACK: Runtime pm does not allow requesting autosuspend from - * resume callback, delayed it after resume */ - queue_delayed_work(system_nrt_wq, &usb_ld->runtime_pm_work, - msecs_to_jiffies(50)); - - for (i = 0; i < IF_USB_DEVNUM_MAX; i++) { - pipe = &usb_ld->devdata[i]; - while ((urb = usb_get_from_anchor(&pipe->urbs))) { - ret = usb_rx_submit(pipe, urb, GFP_KERNEL); - if (ret < 0) { - usb_put_urb(urb); - mif_err( - "usb_rx_submit error with (%d)\n", - ret); - return ret; - } - usb_put_urb(urb); - } - } - - while ((urb = usb_get_from_anchor(&usb_ld->deferred))) { - mif_debug("got urb (0x%p) from anchor & resubmit\n", - urb); - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret < 0) { - mif_err("resubmit failed\n"); - skb = urb->context; - dev_kfree_skb_any(skb); - usb_free_urb(urb); - ret = pm_runtime_put_autosuspend( - &usb_ld->usbdev->dev); - if (ret < 0 && ret != -EAGAIN) - mif_debug("pm_runtime_put_autosuspend " - "failed: %d\n", ret); - } - } - SET_SLAVE_WAKEUP(usb_ld->pdata, 1); - udelay(100); - SET_SLAVE_WAKEUP(usb_ld->pdata, 0); - - /* if_usb_resume() is atomic. post_resume_work is - * a kind of bottom halves - */ - queue_delayed_work(system_nrt_wq, &usb_ld->post_resume_work, 0); - - return 0; - } - - spin_unlock_irq(&usb_ld->lock); - return 0; -} - -static int if_usb_reset_resume(struct usb_interface *intf) -{ - int ret; - - mif_debug("\n"); - ret = if_usb_resume(intf); - return ret; -} - -static struct usb_device_id if_usb_ids[] = { - { USB_DEVICE(0x04e8, 0x6999), /* CMC221 LTE Modem */ - /*.driver_info = 0,*/ - }, - { } /* terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, if_usb_ids); - -static struct usb_driver if_usb_driver; -static void if_usb_disconnect(struct usb_interface *intf) -{ - struct usb_link_device *usb_ld = usb_get_intfdata(intf); - struct usb_device *usbdev = usb_ld->usbdev; - struct link_pm_data *pm_data = usb_ld->link_pm_data; - int dev_id = intf->altsetting->desc.bInterfaceNumber; - struct if_usb_devdata *pipe_data = &usb_ld->devdata[dev_id]; - - - usb_set_intfdata(intf, NULL); - - pipe_data->disconnected = 1; - smp_wmb(); - - wake_up(&usb_ld->l2_wait); - - usb_ld->if_usb_connected = 0; - usb_ld->flow_suspend = 1; - - dev_dbg(&usbdev->dev, "%s\n", __func__); - usb_ld->dev_count--; - usb_driver_release_interface(&if_usb_driver, pipe_data->data_intf); - - usb_kill_anchored_urbs(&pipe_data->reading); - usb_free_urbs(usb_ld, pipe_data); - - if (usb_ld->dev_count == 0) { - cancel_delayed_work_sync(&usb_ld->runtime_pm_work); - cancel_delayed_work_sync(&usb_ld->post_resume_work); - cancel_delayed_work_sync(&usb_ld->ld.tx_delayed_work); - usb_put_dev(usbdev); - usb_ld->usbdev = NULL; - pm_runtime_forbid(pm_data->root_hub); - } -} - -static int __devinit if_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_host_interface *data_desc; - struct usb_link_device *usb_ld = - (struct usb_link_device *)id->driver_info; - struct link_device *ld = &usb_ld->ld; - struct usb_interface *data_intf; - struct usb_device *usbdev = interface_to_usbdev(intf); - struct device *dev, *ehci_dev, *root_hub; - struct if_usb_devdata *pipe; - struct urb *urb; - int i; - int j; - int dev_id; - int err; - - /* To detect usb device order probed */ - dev_id = intf->cur_altsetting->desc.bInterfaceNumber; - - if (dev_id >= IF_USB_DEVNUM_MAX) { - dev_err(&intf->dev, "Device id %d cannot support\n", - dev_id); - return -EINVAL; - } - - if (!usb_ld) { - dev_err(&intf->dev, - "if_usb device doesn't be allocated\n"); - err = ENOMEM; - goto out; - } - - mif_info("probe dev_id=%d usb_device_id(0x%p), usb_ld (0x%p)\n", - dev_id, id, usb_ld); - - usb_ld->usbdev = usbdev; - usb_get_dev(usbdev); - - for (i = 0; i < IF_USB_DEVNUM_MAX; i++) { - data_intf = usb_ifnum_to_if(usbdev, i); - - /* remap endpoint of RAW to no.1 for LTE modem */ - if (i == 0) - pipe = &usb_ld->devdata[1]; - else if (i == 1) - pipe = &usb_ld->devdata[0]; - else - pipe = &usb_ld->devdata[i]; - - pipe->disconnected = 0; - pipe->data_intf = data_intf; - data_desc = data_intf->cur_altsetting; - - /* Endpoints */ - if (usb_pipein(data_desc->endpoint[0].desc.bEndpointAddress)) { - pipe->rx_pipe = usb_rcvbulkpipe(usbdev, - data_desc->endpoint[0].desc.bEndpointAddress); - pipe->tx_pipe = usb_sndbulkpipe(usbdev, - data_desc->endpoint[1].desc.bEndpointAddress); - pipe->rx_buf_size = 1024*4; - } else { - pipe->rx_pipe = usb_rcvbulkpipe(usbdev, - data_desc->endpoint[1].desc.bEndpointAddress); - pipe->tx_pipe = usb_sndbulkpipe(usbdev, - data_desc->endpoint[0].desc.bEndpointAddress); - pipe->rx_buf_size = 1024*4; - } - - if (i == 0) { - dev_info(&usbdev->dev, "USB IF USB device found\n"); - } else { - err = usb_driver_claim_interface(&if_usb_driver, - data_intf, usb_ld); - if (err < 0) { - mif_err("failed to cliam usb interface\n"); - goto out; - } - } - - usb_set_intfdata(data_intf, usb_ld); - usb_ld->dev_count++; - pm_suspend_ignore_children(&data_intf->dev, true); - - for (j = 0; j < URB_COUNT; j++) { - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - mif_err("alloc urb fail\n"); - err = -ENOMEM; - goto out2; - } - - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - urb->transfer_buffer = usb_alloc_coherent(usbdev, - pipe->rx_buf_size, GFP_KERNEL, - &urb->transfer_dma); - if (!urb->transfer_buffer) { - mif_err( - "Failed to allocate transfer buffer\n"); - usb_free_urb(urb); - err = -ENOMEM; - goto out2; - } - - usb_fill_bulk_urb(urb, usbdev, pipe->rx_pipe, - urb->transfer_buffer, pipe->rx_buf_size, - usb_rx_complete, pipe); - usb_anchor_urb(urb, &pipe->urbs); - } - } - - /* temporary call reset_resume */ - atomic_set(&usb_ld->suspend_count, 1); - if_usb_reset_resume(data_intf); - atomic_set(&usb_ld->suspend_count, 0); - - SET_HOST_ACTIVE(usb_ld->pdata, 1); - usb_ld->host_wake_timeout_flag = 0; - - if (gpio_get_value(usb_ld->pdata->gpio_phone_active)) { - struct link_pm_data *pm_data = usb_ld->link_pm_data; - int delay = pm_data->autosuspend_delay_ms ?: - DEFAULT_AUTOSUSPEND_DELAY_MS; - pm_runtime_set_autosuspend_delay(&usbdev->dev, delay); - dev = &usbdev->dev; - if (dev->parent) { - dev_dbg(&usbdev->dev, "if_usb Runtime PM Start!!\n"); - usb_enable_autosuspend(usb_ld->usbdev); - /* s5p-ehci runtime pm allow - usb phy suspend mode */ - root_hub = &usbdev->bus->root_hub->dev; - ehci_dev = root_hub->parent; - mif_debug("ehci device = %s, %s\n", - dev_driver_string(ehci_dev), - dev_name(ehci_dev)); - pm_runtime_allow(ehci_dev); - - if (!pm_data->autosuspend) - pm_runtime_forbid(dev); - - if (has_hub(usb_ld)) - link_pm_preactive(pm_data); - - pm_data->root_hub = root_hub; - } - - usb_ld->flow_suspend = 0; - /* Queue work if skbs were pending before a disconnect/probe */ - if (ld->sk_fmt_tx_q.qlen || ld->sk_raw_tx_q.qlen) - queue_delayed_work(ld->tx_wq, &ld->tx_delayed_work, 0); - - usb_ld->if_usb_connected = 1; - /*USB3503*/ - mif_debug("hub active complete\n"); - - usb_change_modem_state(usb_ld, STATE_ONLINE); - } else { - usb_change_modem_state(usb_ld, STATE_LOADER_DONE); - } - - /* check dynamic switching gpio received - * before usb enumeration is completed - */ - if (ld->mc->need_switch_to_usb) { - ld->mc->need_switch_to_usb = false; - rawdevs_set_tx_link(ld->msd, LINKDEV_USB); - } - - return 0; - -out2: - usb_ld->dev_count--; - for (i = 0; i < IF_USB_DEVNUM_MAX; i++) - usb_free_urbs(usb_ld, &usb_ld->devdata[i]); -out: - usb_set_intfdata(intf, NULL); - return err; -} - -irqreturn_t usb_resume_irq(int irq, void *data) -{ - int ret; - struct usb_link_device *usb_ld = data; - int hwup; - static int wake_status = -1; - struct device *dev; - - hwup = gpio_get_value(usb_ld->pdata->gpio_host_wakeup); - if (hwup == wake_status) { - mif_err("Received spurious wake irq: %d", hwup); - return IRQ_HANDLED; - } - wake_status = hwup; - - irq_set_irq_type(irq, hwup ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH); - /* - * exynos BSP has problem when using level interrupt. - * If we change irq type from interrupt handler, - * we can get level interrupt twice. - * this is temporary solution until SYS.LSI resolve this problem. - */ - __raw_writel(eint_irq_to_bit(irq), S5P_EINT_PEND(EINT_REG_NR(irq))); - wake_lock_timeout(&usb_ld->gpiolock, 100); - - mif_err("< H-WUP %d\n", hwup); - - if (!link_pm_is_connected(usb_ld)) - return IRQ_HANDLED; - - if (hwup) { - dev = &usb_ld->usbdev->dev; - mif_info("runtime status=%d\n", - dev->power.runtime_status); - - /* if usb3503 was on, usb_if was resumed by probe */ - if (has_hub(usb_ld) && - (dev->power.runtime_status == RPM_ACTIVE || - dev->power.runtime_status == RPM_RESUMING)) - return IRQ_HANDLED; - - device_lock(dev); - if (dev->power.is_prepared || dev->power.is_suspended) { - pm_runtime_get_noresume(dev); - ret = 0; - } else { - ret = pm_runtime_get_sync(dev); - } - device_unlock(dev); - if (ret < 0) { - mif_err("pm_runtime_get fail (%d)\n", ret); - return IRQ_HANDLED; - } - } else { - if (usb_ld->resume_status == AP_INITIATED_RESUME) - wake_up(&usb_ld->l2_wait); - usb_ld->resume_status = CP_INITIATED_RESUME; - pm_runtime_mark_last_busy(&usb_ld->usbdev->dev); - pm_runtime_put_autosuspend(&usb_ld->usbdev->dev); - } - - return IRQ_HANDLED; -} - -static int if_usb_init(struct usb_link_device *usb_ld) -{ - int ret; - int i; - struct if_usb_devdata *pipe; - - /* give it to probe, or global variable needed */ - if_usb_ids[0].driver_info = (unsigned long)usb_ld; - - for (i = 0; i < IF_USB_DEVNUM_MAX; i++) { - pipe = &usb_ld->devdata[i]; - pipe->format = i; - pipe->disconnected = 1; - init_usb_anchor(&pipe->urbs); - init_usb_anchor(&pipe->reading); - } - - init_waitqueue_head(&usb_ld->l2_wait); - init_usb_anchor(&usb_ld->deferred); - - ret = usb_register(&if_usb_driver); - if (ret) { - mif_err("usb_register_driver() fail : %d\n", ret); - return ret; - } - - return 0; -} - -struct link_device *usb_create_link_device(void *data) -{ - int ret; - struct modem_data *pdata; - struct platform_device *pdev = (struct platform_device *)data; - struct usb_link_device *usb_ld = NULL; - struct link_device *ld = NULL; - - pdata = pdev->dev.platform_data; - - usb_ld = kzalloc(sizeof(struct usb_link_device), GFP_KERNEL); - if (!usb_ld) - goto err; - - INIT_LIST_HEAD(&usb_ld->ld.list); - skb_queue_head_init(&usb_ld->ld.sk_fmt_tx_q); - skb_queue_head_init(&usb_ld->ld.sk_raw_tx_q); - spin_lock_init(&usb_ld->lock); - - ld = &usb_ld->ld; - usb_ld->pdata = pdata; - - ld->name = "usb"; - ld->init_comm = usb_init_communication; - ld->terminate_comm = usb_terminate_communication; - ld->send = usb_send; - ld->com_state = COM_NONE; - - /*ld->tx_wq = create_singlethread_workqueue("usb_tx_wq");*/ - ld->tx_wq = alloc_workqueue("usb_tx_wq", - WQ_HIGHPRI | WQ_UNBOUND | WQ_RESCUER, 1); - - if (!ld->tx_wq) { - mif_err("fail to create work Q.\n"); - goto err; - } - - usb_ld->pdata->irq_host_wakeup = platform_get_irq(pdev, 1); - wake_lock_init(&usb_ld->gpiolock, WAKE_LOCK_SUSPEND, - "modem_usb_gpio_wake"); - wake_lock_init(&usb_ld->susplock, WAKE_LOCK_SUSPEND, - "modem_usb_suspend_block"); - - INIT_DELAYED_WORK(&ld->tx_delayed_work, usb_tx_work); - INIT_DELAYED_WORK(&usb_ld->runtime_pm_work, runtime_pm_work); - INIT_DELAYED_WORK(&usb_ld->post_resume_work, post_resume_work); - INIT_DELAYED_WORK(&usb_ld->wait_enumeration, wait_enumeration_work); - INIT_WORK(&usb_ld->disconnect_work, if_usb_force_disconnect); - - /* create link pm device */ - ret = link_pm_init(usb_ld, data); - if (ret) - goto err; - - ret = if_usb_init(usb_ld); - if (ret) - goto err; - - return ld; -err: - if (ld && ld->tx_wq) - destroy_workqueue(ld->tx_wq); - - kfree(usb_ld); - - return NULL; -} - -static struct usb_driver if_usb_driver = { - .name = "if_usb_driver", - .probe = if_usb_probe, - .disconnect = if_usb_disconnect, - .id_table = if_usb_ids, - .suspend = if_usb_suspend, - .resume = if_usb_resume, - .reset_resume = if_usb_reset_resume, - .supports_autosuspend = 1, -}; - -static void __exit if_usb_exit(void) -{ - usb_deregister(&if_usb_driver); -} - -bool usb_is_enumerated(struct modem_shared *msd) -{ - struct link_device *ld = find_linkdev(msd, LINKDEV_USB); - if (ld) - return to_usb_link_device(ld)->usbdev != NULL; - else - return false; -} - - -/* lte specific functions */ - -static int lte_wake_resume(struct device *pdev) -{ - struct modem_data *pdata = pdev->platform_data; - int val; - - val = gpio_get_value(pdata->gpio_host_wakeup); - if (!val) { - mif_debug("> S-WUP 1\n"); - gpio_set_value(pdata->gpio_slave_wakeup, 1); - } - - return 0; -} - -static const struct dev_pm_ops lte_wake_pm_ops = { - .resume = lte_wake_resume, -}; - -static struct platform_driver lte_wake_driver = { - .driver = { - .name = "modem_lte_wake", - .pm = <e_wake_pm_ops, - }, -}; - -static int __init lte_wake_init(void) -{ - return platform_driver_register(<e_wake_driver); -} -module_init(lte_wake_init); diff --git a/drivers/misc/modem_if/modem_link_device_usb.h b/drivers/misc/modem_if/modem_link_device_usb.h deleted file mode 100644 index 8233fd11548..00000000000 --- a/drivers/misc/modem_if/modem_link_device_usb.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2010 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. - * - */ - -#ifndef __MODEM_LINK_DEVICE_USB_H__ -#define __MODEM_LINK_DEVICE_USB_H__ - -#include <linux/usb.h> -#include <linux/wakelock.h> - -#define IF_USB_DEVNUM_MAX 3 - -#define IF_USB_FMT_EP 0 -#define IF_USB_RAW_EP 1 -#define IF_USB_RFS_EP 2 - -#define DEFAULT_AUTOSUSPEND_DELAY_MS 500 -#define HOST_WAKEUP_TIMEOUT_JIFFIES msecs_to_jiffies(500) -#define WAIT_ENUMURATION_TIMEOUT_JIFFIES msecs_to_jiffies(15000) -#define MAX_RETRY 30 - -#define IOCTL_LINK_CONTROL_ENABLE _IO('o', 0x30) -#define IOCTL_LINK_CONTROL_ACTIVE _IO('o', 0x31) -#define IOCTL_LINK_GET_HOSTWAKE _IO('o', 0x32) -#define IOCTL_LINK_CONNECTED _IO('o', 0x33) -#define IOCTL_LINK_SET_BIAS_CLEAR _IO('o', 0x34) - -#define IOCTL_LINK_PORT_ON _IO('o', 0x35) -#define IOCTL_LINK_PORT_OFF _IO('o', 0x36) - -enum RESUME_STATUS { - CP_INITIATED_RESUME, - AP_INITIATED_RESUME, -}; - -enum IPC_INIT_STATUS { - INIT_IPC_NOT_READY, - INIT_IPC_START_DONE, /* send 'a' done */ -}; - -enum hub_status { - HUB_STATE_OFF, /* usb3503 0ff*/ - HUB_STATE_RESUMMING, /* usb3503 on, but enummerattion was not yet*/ - HUB_STATE_ACTIVE, /* hub and CMC221 enumerate */ -}; - -struct if_usb_devdata { - struct usb_interface *data_intf; - unsigned int tx_pipe; - unsigned int rx_pipe; - u8 disconnected; - - int format; - struct usb_anchor urbs; - struct usb_anchor reading; - unsigned int rx_buf_size; -}; - -struct usb_link_device { - /*COMMON LINK DEVICE*/ - struct link_device ld; - - struct modem_data *pdata; - - /*USB SPECIFIC LINK DEVICE*/ - struct usb_device *usbdev; - struct if_usb_devdata devdata[IF_USB_DEVNUM_MAX]; - struct delayed_work runtime_pm_work; - struct delayed_work post_resume_work; - struct delayed_work wait_enumeration; - struct work_struct disconnect_work; - - struct wake_lock gpiolock; - struct wake_lock susplock; - - unsigned int dev_count; - unsigned int suspended; - atomic_t suspend_count; - enum RESUME_STATUS resume_status; - int if_usb_connected; - int if_usb_initstates; - int flow_suspend; - int host_wake_timeout_flag; - - unsigned gpio_slave_wakeup; - unsigned gpio_host_wakeup; - unsigned gpio_host_active; - int irq_host_wakeup; - struct delayed_work dwork; - struct work_struct resume_work; - int cpcrash_flag; - wait_queue_head_t l2_wait; - - spinlock_t lock; - struct usb_anchor deferred; - - /* LINK PM DEVICE DATA */ - struct link_pm_data *link_pm_data; -}; -/* converts from struct link_device* to struct xxx_link_device* */ -#define to_usb_link_device(linkdev) \ - container_of(linkdev, struct usb_link_device, ld) - -#define SET_SLAVE_WAKEUP(_pdata, _value) \ -do { \ - gpio_set_value(_pdata->gpio_slave_wakeup, _value); \ - mif_debug("> S-WUP %s\n", _value ? "1" : "0"); \ -} while (0) - -#define SET_HOST_ACTIVE(_pdata, _value) \ -do { \ - gpio_set_value(_pdata->gpio_host_active, _value); \ - mif_debug("> H-ACT %s\n", _value ? "1" : "0"); \ -} while (0) - -#define has_hub(usb_ld) ((usb_ld)->link_pm_data->has_usbhub) - -irqreturn_t usb_resume_irq(int irq, void *data); -bool usb_is_enumerated(struct modem_shared *msd); - -#endif diff --git a/drivers/misc/modem_if/modem_link_pm_usb.c b/drivers/misc/modem_if/modem_link_pm_usb.c deleted file mode 100644 index 1b2614eb58d..00000000000 --- a/drivers/misc/modem_if/modem_link_pm_usb.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (C) 2012 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. - * - */ - -#define DEBUG - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/sched.h> -#include <linux/irq.h> -#include <linux/poll.h> -#include <linux/gpio.h> -#include <linux/if_arp.h> -#include <linux/platform_device.h> -#include <linux/suspend.h> - -#include "modem_link_pm_usb.h" - -static inline void start_hub_work(struct link_pm_data *pm_data, int delay) -{ - if (pm_data->hub_work_running == false) { - pm_data->hub_work_running = true; - wake_lock(&pm_data->hub_lock); - mif_debug("link_pm_hub_work is started\n"); - } - - schedule_delayed_work(&pm_data->link_pm_hub, msecs_to_jiffies(delay)); -} - -static inline void end_hub_work(struct link_pm_data *pm_data) -{ - wake_unlock(&pm_data->hub_lock); - pm_data->hub_work_running = false; - mif_debug("link_pm_hub_work is done\n"); -} - -bool link_pm_is_connected(struct usb_link_device *usb_ld) -{ - if (has_hub(usb_ld)) { - struct link_pm_data *pm_data = usb_ld->link_pm_data; - if (pm_data->hub_init_lock) - return false; - - if (pm_data->hub_status == HUB_STATE_OFF) { - if (pm_data->hub_work_running == false) - start_hub_work(pm_data, 0); - return false; - } - } - - if (!usb_ld->if_usb_connected) { - mif_err("mif: if not connected\n"); - return false; - } - - return true; -} - -void link_pm_preactive(struct link_pm_data *pm_data) -{ - if (pm_data->root_hub) { - mif_info("pre-active\n"); - pm_data->hub_on_retry_cnt = 0; - complete(&pm_data->hub_active); - pm_runtime_put_sync(pm_data->root_hub); - } - - pm_data->hub_status = HUB_STATE_ACTIVE; -} - -static void link_pm_hub_work(struct work_struct *work) -{ - int err; - struct link_pm_data *pm_data = - container_of(work, struct link_pm_data, link_pm_hub.work); - - if (pm_data->hub_status == HUB_STATE_ACTIVE) { - end_hub_work(pm_data); - return; - } - - if (!pm_data->port_enable) { - mif_err("mif: hub power func not assinged\n"); - end_hub_work(pm_data); - return; - } - - /* If kernel if suspend, wait the ehci resume */ - if (pm_data->dpm_suspending) { - mif_info("dpm_suspending\n"); - start_hub_work(pm_data, 500); - return; - } - - switch (pm_data->hub_status) { - case HUB_STATE_OFF: - pm_data->hub_status = HUB_STATE_RESUMMING; - mif_trace("hub off->on\n"); - - /* skip 1st time before first probe */ - if (pm_data->root_hub) - pm_runtime_get_sync(pm_data->root_hub); - err = pm_data->port_enable(2, 1); - if (err < 0) { - mif_err("hub on fail err=%d\n", err); - err = pm_data->port_enable(2, 0); - if (err < 0) - mif_err("hub off fail err=%d\n", err); - pm_data->hub_status = HUB_STATE_OFF; - if (pm_data->root_hub) - pm_runtime_put_sync(pm_data->root_hub); - end_hub_work(pm_data); - } else { - /* resume root hub */ - start_hub_work(pm_data, 100); - } - break; - case HUB_STATE_RESUMMING: - if (pm_data->hub_on_retry_cnt++ > 50) { - pm_data->hub_on_retry_cnt = 0; - pm_data->hub_status = HUB_STATE_OFF; - if (pm_data->root_hub) - pm_runtime_put_sync(pm_data->root_hub); - end_hub_work(pm_data); - } else { - mif_info("hub resumming: %d\n", - pm_data->hub_on_retry_cnt); - start_hub_work(pm_data, 200); - } - break; - } -exit: - return; -} - -static int link_pm_hub_standby(void *args) -{ - struct link_pm_data *pm_data = args; - struct usb_link_device *usb_ld = pm_data->usb_ld; - int err = 0; - - if (!pm_data->port_enable) { - mif_err("port power func not assinged\n"); - return -ENODEV; - } - - err = pm_data->port_enable(2, 0); - if (err < 0) - mif_err("hub off fail err=%d\n", err); - - pm_data->hub_status = HUB_STATE_OFF; - - /* this function is atomic. - * make force disconnect in workqueue.. - */ - if (pm_data->usb_ld->if_usb_connected) - schedule_work(&usb_ld->disconnect_work); - - return err; -} - -bool link_pm_set_active(struct usb_link_device *usb_ld) -{ - int ret; - struct link_pm_data *pm_data = usb_ld->link_pm_data; - - if (has_hub(usb_ld)) { - if (pm_data->hub_status != HUB_STATE_ACTIVE) { - INIT_COMPLETION(pm_data->hub_active); - SET_SLAVE_WAKEUP(usb_ld->pdata, 1); - ret = wait_for_completion_timeout(&pm_data->hub_active, - msecs_to_jiffies(2000)); - if (!ret) { /*timeout*/ - mif_err("hub on timeout - retry\n"); - SET_SLAVE_WAKEUP(usb_ld->pdata, 0); - queue_delayed_work(usb_ld->ld.tx_wq, - &usb_ld->ld.tx_delayed_work, 0); - return false; - } - } - } else { - /* TODO do something */ - } - return true; -} - -static long link_pm_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - int value, err = 0; - struct link_pm_data *pm_data = file->private_data; - struct usb_link_device *usb_ld = pm_data->usb_ld; - - mif_info("cmd: 0x%08x\n", cmd); - - switch (cmd) { - case IOCTL_LINK_CONTROL_ACTIVE: - if (copy_from_user(&value, (const void __user *)arg, - sizeof(int))) - return -EFAULT; - gpio_set_value(pm_data->gpio_link_active, value); - break; - case IOCTL_LINK_GET_HOSTWAKE: - return !gpio_get_value(pm_data->gpio_link_hostwake); - case IOCTL_LINK_CONNECTED: - return usb_ld->if_usb_connected; - case IOCTL_LINK_PORT_ON: - /* ignore cp host wakeup irq, set the hub_init_lock when AP try - CP off and release hub_init_lock when CP boot done */ - pm_data->hub_init_lock = 0; - if (pm_data->root_hub) - pm_runtime_get_sync(pm_data->root_hub); - if (pm_data->port_enable) { - err = pm_data->port_enable(2, 1); - if (err < 0) { - mif_err("hub on fail err=%d\n", err); - goto exit; - } - pm_data->hub_status = HUB_STATE_RESUMMING; - } - break; - case IOCTL_LINK_PORT_OFF: - err = link_pm_hub_standby(pm_data); - if (err < 0) { - mif_err("usb3503 active fail\n"); - goto exit; - } - pm_data->hub_init_lock = 1; - pm_data->hub_handshake_done = 0; - break; - default: - break; - } -exit: - return err; -} - -static ssize_t show_autosuspend(struct device *dev, - struct device_attribute *attr, char *buf) -{ - char *p = buf; - struct miscdevice *miscdev = dev_get_drvdata(dev); - struct link_pm_data *pm_data = container_of(miscdev, - struct link_pm_data, miscdev); - struct usb_link_device *usb_ld = pm_data->usb_ld; - - p += sprintf(buf, "%s\n", pm_data->autosuspend ? "on" : "off"); - - return p - buf; -} - -static ssize_t store_autosuspend(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct miscdevice *miscdev = dev_get_drvdata(dev); - struct link_pm_data *pm_data = container_of(miscdev, - struct link_pm_data, miscdev); - struct usb_link_device *usb_ld = pm_data->usb_ld; - struct task_struct *task = get_current(); - char taskname[TASK_COMM_LEN]; - - mif_info("autosuspend: %s: %s(%d)'\n", - buf, get_task_comm(taskname, task), task->pid); - - if (!strncmp(buf, "on", 2)) { - pm_data->autosuspend = true; - if (usb_ld->usbdev) - pm_runtime_allow(&usb_ld->usbdev->dev); - } else if (!strncmp(buf, "off", 3)) { - pm_data->autosuspend = false; - if (usb_ld->usbdev) - pm_runtime_forbid(&usb_ld->usbdev->dev); - } - - return count; -} - -static struct device_attribute attr_autosuspend = - __ATTR(autosuspend, S_IRUGO | S_IWUSR, - show_autosuspend, store_autosuspend); - -static int link_pm_open(struct inode *inode, struct file *file) -{ - struct link_pm_data *pm_data = - (struct link_pm_data *)file->private_data; - file->private_data = (void *)pm_data; - return 0; -} - -static int link_pm_release(struct inode *inode, struct file *file) -{ - file->private_data = NULL; - return 0; -} - -static const struct file_operations link_pm_fops = { - .owner = THIS_MODULE, - .open = link_pm_open, - .release = link_pm_release, - .unlocked_ioctl = link_pm_ioctl, -}; - -static int link_pm_notifier_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct link_pm_data *pm_data = - container_of(this, struct link_pm_data, pm_notifier); - struct usb_link_device *usb_ld = pm_data->usb_ld; - - switch (event) { - case PM_SUSPEND_PREPARE: - pm_data->dpm_suspending = true; - if (has_hub(usb_ld)) - link_pm_hub_standby(pm_data); - return NOTIFY_OK; - case PM_POST_SUSPEND: - pm_data->dpm_suspending = false; - return NOTIFY_OK; - } - return NOTIFY_DONE; -} - -int link_pm_init(struct usb_link_device *usb_ld, void *data) -{ - int err; - int irq; - struct platform_device *pdev = (struct platform_device *)data; - struct modem_data *pdata = - (struct modem_data *)pdev->dev.platform_data; - struct modemlink_pm_data *pm_pdata = pdata->link_pm_data; - struct link_pm_data *pm_data = - kzalloc(sizeof(struct link_pm_data), GFP_KERNEL); - if (!pm_data) { - mif_err("link_pm_data is NULL\n"); - return -ENOMEM; - } - /* get link pm data from modemcontrol's platform data */ - pm_data->gpio_link_active = pm_pdata->gpio_link_active; - pm_data->gpio_link_hostwake = pm_pdata->gpio_link_hostwake; - pm_data->gpio_link_slavewake = pm_pdata->gpio_link_slavewake; - pm_data->link_reconnect = pm_pdata->link_reconnect; - pm_data->port_enable = pm_pdata->port_enable; - pm_data->freq_lock = pm_pdata->freq_lock; - pm_data->freq_unlock = pm_pdata->freq_unlock; - pm_data->autosuspend_delay_ms = pm_pdata->autosuspend_delay_ms; - pm_data->autosuspend = true; - - pm_data->usb_ld = usb_ld; - usb_ld->link_pm_data = pm_data; - - pm_data->miscdev.minor = MISC_DYNAMIC_MINOR; - pm_data->miscdev.name = "link_pm"; - pm_data->miscdev.fops = &link_pm_fops; - - err = misc_register(&pm_data->miscdev); - if (err < 0) { - mif_err("fail to register pm device(%d)\n", err); - goto err_misc_register; - } - - err = device_create_file(pm_data->miscdev.this_device, - &attr_autosuspend); - if (err) { - mif_err("fail to create file: autosuspend: %d\n", err); - goto err_create_file; - } - - pm_data->hub_init_lock = 1; - irq = gpio_to_irq(usb_ld->pdata->gpio_host_wakeup); - err = request_threaded_irq(irq, NULL, usb_resume_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "modem_usb_wake", usb_ld); - if (err) { - mif_err("Failed to allocate an interrupt(%d)\n", irq); - goto err_request_irq; - } - enable_irq_wake(irq); - - pm_data->has_usbhub = pm_pdata->has_usbhub; - - if (has_hub(usb_ld)) { - init_completion(&pm_data->hub_active); - pm_data->hub_status = HUB_STATE_OFF; - pm_data->hub_handshake_done = 0; - pm_data->root_hub = NULL; - - pm_pdata->hub_standby = link_pm_hub_standby; - pm_pdata->hub_pm_data = pm_data; - - wake_lock_init(&pm_data->hub_lock, WAKE_LOCK_SUSPEND, - "modem_hub_enum_lock"); - INIT_DELAYED_WORK(&pm_data->link_pm_hub, link_pm_hub_work); - pm_data->hub_work_running = false; - } - - pm_data->pm_notifier.notifier_call = link_pm_notifier_event; - register_pm_notifier(&pm_data->pm_notifier); - - return 0; - -err_request_irq: -err_create_file: - misc_deregister(&pm_data->miscdev); -err_misc_register: - kfree(pm_data); - return err; -} diff --git a/drivers/misc/modem_if/modem_link_pm_usb.h b/drivers/misc/modem_if/modem_link_pm_usb.h deleted file mode 100644 index d26af761114..00000000000 --- a/drivers/misc/modem_if/modem_link_pm_usb.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2012 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. - * - */ - -#ifndef __MODEM_LINK_PM_USB_H__ -#define __MODEM_LINK_PM_USB_H__ - -#include <linux/platform_data/modem.h> -#include "modem_prj.h" -#include "modem_link_device_usb.h" - -struct link_pm_data { - struct miscdevice miscdev; - struct usb_link_device *usb_ld; - unsigned gpio_link_active; - unsigned gpio_link_hostwake; - unsigned gpio_link_slavewake; - int (*link_reconnect)(void); - int link_reconnect_cnt; - - struct workqueue_struct *wq; - struct completion active_done; - -/*USB3503*/ - struct completion hub_active; - int hub_status; - bool has_usbhub; - /* ignore hub on by host wakeup irq before cp power on*/ - int hub_init_lock; - /* C1 stay disconnect status after send 'a', skip 'a' next enumeration*/ - int hub_handshake_done; - struct wake_lock hub_lock; - struct delayed_work link_pm_hub; - bool hub_work_running; - int hub_on_retry_cnt; - struct device *root_hub; - - struct notifier_block pm_notifier; - bool dpm_suspending; - - int (*port_enable)(int, int); - - int (*freq_lock)(struct device *dev); - int (*freq_unlock)(struct device *dev); - - int autosuspend_delay_ms; /* if zero, the default value is used */ - bool autosuspend; -}; - -bool link_pm_set_active(struct usb_link_device *usb_ld); -bool link_pm_is_connected(struct usb_link_device *usb_ld); -void link_pm_preactive(struct link_pm_data *pm_data); -int link_pm_init(struct usb_link_device *usb_ld, void *data); - -#endif diff --git a/drivers/misc/modem_if/modem_modemctl_device_cbp71.c b/drivers/misc/modem_if/modem_modemctl_device_cbp71.c deleted file mode 100644 index 28f2ce7736f..00000000000 --- a/drivers/misc/modem_if/modem_modemctl_device_cbp71.c +++ /dev/null @@ -1,233 +0,0 @@ -/* /linux/drivers/misc/modem_if/modem_modemctl_device_cbp7.1.c - * - * Copyright (C) 2010 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/init.h> - -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/wait.h> -#include <linux/sched.h> - -#include <linux/platform_data/modem.h> -#include "modem_prj.h" -#include "modem_link_device_dpram.h" - -#define PIF_TIMEOUT (180 * HZ) -#define DPRAM_INIT_TIMEOUT (15 * HZ) - -static int cbp71_on(struct modem_ctl *mc) -{ - int RetVal = 0; - int dpram_init_RetVal = 0; - struct link_device *ld = get_current_link(mc->iod); - struct dpram_link_device *dpram_ld = to_dpram_link_device(ld); - - mif_info("cbp71_on()\n"); - - if (!mc->gpio_cp_off || !mc->gpio_cp_reset) { - mif_err("no gpio data\n"); - return -ENXIO; - } - gpio_set_value(mc->gpio_cp_reset, 0); - msleep(600); - gpio_set_value(mc->gpio_cp_reset, 1); - msleep(100); - gpio_set_value(mc->gpio_cp_off, 0); - msleep(300); - - gpio_set_value(mc->gpio_pda_active, 1); - - mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); - - /* Wait here until the PHONE is up. - * Waiting as the this called from IOCTL->UM thread */ - mif_debug("power control waiting for INT_MASK_CMD_PIF_INIT_DONE\n"); - - /* 1HZ = 1 clock tick, 100 default */ - dpram_ld->clear_interrupt(dpram_ld); - - dpram_init_RetVal = - wait_event_interruptible_timeout( - dpram_ld->dpram_init_cmd_wait_q, - dpram_ld->dpram_init_cmd_wait_condition, - DPRAM_INIT_TIMEOUT); - - if (!dpram_init_RetVal) { - /*RetVal will be 0 on timeout, non zero if interrupted */ - mif_err("INIT_START cmd was not arrived.\n"); - mif_err("init_cmd_wait_condition is 0 and wait timeout happend\n"); - return -ENXIO; - } - - RetVal = wait_event_interruptible_timeout( - dpram_ld->modem_pif_init_done_wait_q, - dpram_ld->modem_pif_init_wait_condition, - PIF_TIMEOUT); - - if (!RetVal) { - /*RetVal will be 0 on timeout, non zero if interrupted */ - mif_err("PIF init failed\n"); - mif_err("pif_init_wait_condition is 0 and wait timeout happend\n"); - return -ENXIO; - } - - mif_debug("complete cbp71_on\n"); - - mc->iod->modem_state_changed(mc->iod, STATE_ONLINE); - - return 0; -} - -static int cbp71_off(struct modem_ctl *mc) -{ - mif_debug("cbp71_off()\n"); - - if (!mc->gpio_cp_off || !mc->gpio_cp_reset) { - mif_err("no gpio data\n"); - return -ENXIO; - } - - mif_err("Phone power Off. - do nothing\n"); - - mc->iod->modem_state_changed(mc->iod, STATE_OFFLINE); - - return 0; -} - -static int cbp71_reset(struct modem_ctl *mc) -{ - int ret = 0; - - mif_debug("cbp71_reset()\n"); - - ret = cbp71_off(mc); - if (ret) - return -ENXIO; - - msleep(100); - - ret = cbp71_on(mc); - if (ret) - return -ENXIO; - - return 0; -} - -static int cbp71_boot_on(struct modem_ctl *mc) -{ - mif_debug("cbp71_boot_on()\n"); - - if (!mc->gpio_cp_reset) { - mif_err("no gpio data\n"); - return -ENXIO; - } - gpio_set_value(mc->gpio_cp_reset, 0); - msleep(600); - gpio_set_value(mc->gpio_cp_reset, 1); - - mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); - - return 0; -} - -static int cbp71_boot_off(struct modem_ctl *mc) -{ - mif_debug("cbp71_boot_off()\n"); - return 0; -} - -static irqreturn_t phone_active_irq_handler(int irq, void *_mc) -{ - int phone_reset = 0; - int phone_active_value = 0; - int phone_state = 0; - struct modem_ctl *mc = (struct modem_ctl *)_mc; - - if (!mc->gpio_cp_reset || !mc->gpio_phone_active) { - mif_err("no gpio data\n"); - return IRQ_HANDLED; - } - - phone_reset = gpio_get_value(mc->gpio_cp_reset); - phone_active_value = gpio_get_value(mc->gpio_phone_active); - - if (phone_reset && phone_active_value) - phone_state = STATE_ONLINE; - else if (phone_reset && !phone_active_value) - phone_state = STATE_CRASH_EXIT; - else - phone_state = STATE_OFFLINE; - - if (mc->iod && mc->iod->modem_state_changed) - mc->iod->modem_state_changed(mc->iod, phone_state); - - if (phone_active_value) - irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_LOW); - else - irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_HIGH); - - mif_info("phone_active_irq_handler : phone_state=%d\n", phone_state); - - return IRQ_HANDLED; -} - -static void cbp71_get_ops(struct modem_ctl *mc) -{ - mc->ops.modem_on = cbp71_on; - mc->ops.modem_off = cbp71_off; - mc->ops.modem_reset = cbp71_reset; - mc->ops.modem_boot_on = cbp71_boot_on; - mc->ops.modem_boot_off = cbp71_boot_off; -} - -int cbp71_init_modemctl_device(struct modem_ctl *mc, - struct modem_data *pdata) -{ - int ret = 0; - struct platform_device *pdev; - - mc->gpio_cp_on = pdata->gpio_cp_on; - mc->gpio_reset_req_n = pdata->gpio_reset_req_n; - mc->gpio_cp_reset = pdata->gpio_cp_reset; - mc->gpio_pda_active = pdata->gpio_pda_active; - mc->gpio_phone_active = pdata->gpio_phone_active; - mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int; - mc->gpio_flm_uart_sel = pdata->gpio_flm_uart_sel; - mc->gpio_cp_warm_reset = pdata->gpio_cp_warm_reset; - mc->gpio_cp_off = pdata->gpio_cp_off; - - pdev = to_platform_device(mc->dev); - mc->irq_phone_active = platform_get_irq(pdev, 0); - - cbp71_get_ops(mc); - - /*TODO: check*/ - ret = request_irq(mc->irq_phone_active, phone_active_irq_handler, - IRQF_TRIGGER_HIGH, "phone_active", mc); - if (ret) { - mif_err("failed to irq_phone_active request_irq: %d\n" - , ret); - return ret; - } - - ret = enable_irq_wake(mc->irq_phone_active); - if (ret) - mif_err("failed to enable_irq_wake:%d\n", ret); - - return ret; -} diff --git a/drivers/misc/modem_if/modem_modemctl_device_cbp72.c b/drivers/misc/modem_if/modem_modemctl_device_cbp72.c deleted file mode 100644 index 2617be8abaa..00000000000 --- a/drivers/misc/modem_if/modem_modemctl_device_cbp72.c +++ /dev/null @@ -1,273 +0,0 @@ -/* /linux/drivers/misc/modem_if/modem_modemctl_device_cbp7.1.c - * - * Copyright (C) 2010 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/init.h> - -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/wait.h> -#include <linux/sched.h> -#include <linux/platform_device.h> - -#include <linux/platform_data/modem.h> -#include "modem_prj.h" -#include "modem_link_device_dpram.h" - -#define PIF_TIMEOUT (180 * HZ) -#define DPRAM_INIT_TIMEOUT (30 * HZ) - - -static irqreturn_t phone_active_handler(int irq, void *arg) -{ - struct modem_ctl *mc = (struct modem_ctl *)arg; - int phone_reset = gpio_get_value(mc->gpio_cp_reset); - int phone_active = gpio_get_value(mc->gpio_phone_active); - int phone_state = mc->phone_state; - - mif_info("state = %d, phone_reset = %d, phone_active = %d\n", - phone_state, phone_reset, phone_active); - - if (phone_reset && phone_active) { - if (mc->phone_state == STATE_BOOTING) { - phone_state = STATE_ONLINE; - mc->bootd->modem_state_changed(mc->bootd, phone_state); - } - } else if (phone_reset && !phone_active) { - if (mc->phone_state == STATE_ONLINE) { - phone_state = STATE_CRASH_EXIT; - mc->bootd->modem_state_changed(mc->bootd, phone_state); - } - } else { - phone_state = STATE_OFFLINE; - if (mc->bootd && mc->bootd->modem_state_changed) - mc->bootd->modem_state_changed(mc->bootd, phone_state); - } - - if (phone_active) - irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_LOW); - else - irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_HIGH); - - mif_info("phone_state = %d\n", phone_state); - - return IRQ_HANDLED; -} - -static int cbp72_on(struct modem_ctl *mc) -{ - mif_info("start!!!\n"); - - /* prevent sleep during bootloader downloading */ - if (!wake_lock_active(&mc->mc_wake_lock)) - wake_lock(&mc->mc_wake_lock); - - gpio_set_value(mc->gpio_cp_on, 0); - if (mc->gpio_cp_off) - gpio_set_value(mc->gpio_cp_off, 1); - gpio_set_value(mc->gpio_cp_reset, 0); - - msleep(500); - - gpio_set_value(mc->gpio_cp_on, 1); - if (mc->gpio_cp_off) - gpio_set_value(mc->gpio_cp_off, 0); - - msleep(100); - - gpio_set_value(mc->gpio_cp_reset, 1); - - msleep(300); - - gpio_set_value(mc->gpio_pda_active, 1); - - mc->bootd->modem_state_changed(mc->bootd, STATE_BOOTING); - - mif_info("complete!!!\n"); - - return 0; -} - -static int cbp72_off(struct modem_ctl *mc) -{ - mif_info("cbp72_off()\n"); - - if (!mc->gpio_cp_off || !mc->gpio_cp_reset) { - mif_err("no gpio data\n"); - return -ENXIO; - } - - gpio_set_value(mc->gpio_cp_reset, 0); - gpio_set_value(mc->gpio_cp_on, 0); - gpio_set_value(mc->gpio_cp_off, 1); - - mc->bootd->modem_state_changed(mc->bootd, STATE_OFFLINE); - - return 0; -} - -static int cbp72_reset(struct modem_ctl *mc) -{ - int ret = 0; - - mif_debug("cbp72_reset()\n"); - - ret = cbp72_off(mc); - if (ret) - return -ENXIO; - - msleep(100); - - ret = cbp72_on(mc); - if (ret) - return -ENXIO; - - return 0; -} - -static int cbp72_boot_on(struct modem_ctl *mc) -{ - mif_info("\n"); - - if (!mc->gpio_cp_reset) { - mif_err("no gpio data\n"); - return -ENXIO; - } - - gpio_set_value(mc->gpio_cp_reset, 0); - - msleep(600); - - gpio_set_value(mc->gpio_cp_reset, 1); - - mc->bootd->modem_state_changed(mc->bootd, STATE_BOOTING); - - return 0; -} - -static int cbp72_boot_off(struct modem_ctl *mc) -{ - int ret; - struct link_device *ld = get_current_link(mc->bootd); - struct dpram_link_device *dpld = to_dpram_link_device(ld); - mif_debug("\n"); - /* Wait here until the PHONE is up. - * Waiting as the this called from IOCTL->UM thread */ - mif_info("Waiting for INT_CMD_PHONE_START\n"); - ret = wait_for_completion_interruptible_timeout( - &dpld->dpram_init_cmd, DPRAM_INIT_TIMEOUT); - if (!ret) { - /* ret == 0 on timeout, ret < 0 if interrupted */ - mif_err("Timeout!!! (PHONE_START was not arrived.)\n"); - return -ENXIO; - } - - mif_info("Waiting for INT_CMD_PIF_INIT_DONE\n"); - ret = wait_for_completion_interruptible_timeout( - &dpld->modem_pif_init_done, PIF_TIMEOUT); - if (!ret) { - mif_err("Timeout!!! (PIF_INIT_DONE was not arrived.)\n"); - return -ENXIO; - } - mc->bootd->modem_state_changed(mc->bootd, STATE_ONLINE); - - wake_unlock(&mc->mc_wake_lock); - - return 0; -} - -static int cbp72_force_crash_exit(struct modem_ctl *mc) -{ - struct link_device *ld = get_current_link(mc->bootd); - - mif_err("device = %s\n", mc->bootd->name); - - /* Make DUMP start */ - ld->force_dump(ld, mc->bootd); - - msleep_interruptible(1000); - - mc->bootd->modem_state_changed(mc->bootd, STATE_CRASH_EXIT); - - return 0; -} - -static void cbp72_get_ops(struct modem_ctl *mc) -{ - mc->ops.modem_on = cbp72_on; - mc->ops.modem_off = cbp72_off; - mc->ops.modem_reset = cbp72_reset; - mc->ops.modem_boot_on = cbp72_boot_on; - mc->ops.modem_boot_off = cbp72_boot_off; - mc->ops.modem_force_crash_exit = cbp72_force_crash_exit; -} - -int cbp72_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata) -{ - int ret = 0; - int irq = 0; - unsigned long flag = 0; - struct platform_device *pdev = NULL; - - mc->gpio_cp_on = pdata->gpio_cp_on; - mc->gpio_cp_off = pdata->gpio_cp_off; - mc->gpio_reset_req_n = pdata->gpio_reset_req_n; - mc->gpio_cp_reset = pdata->gpio_cp_reset; - mc->gpio_pda_active = pdata->gpio_pda_active; - mc->gpio_phone_active = pdata->gpio_phone_active; - mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int; - mc->gpio_flm_uart_sel = pdata->gpio_flm_uart_sel; - mc->gpio_cp_warm_reset = pdata->gpio_cp_warm_reset; - - if (!mc->gpio_cp_on || !mc->gpio_cp_reset || !mc->gpio_phone_active) { - mif_err("no GPIO data\n"); - return -ENXIO; - } - - gpio_set_value(mc->gpio_cp_reset, 0); - if (mc->gpio_cp_off) - gpio_set_value(mc->gpio_cp_off, 1); - gpio_set_value(mc->gpio_cp_on, 0); - - cbp72_get_ops(mc); - - pdev = to_platform_device(mc->dev); - mc->irq_phone_active = platform_get_irq_byname(pdev, "cp_active_irq"); - if (!mc->irq_phone_active) { - mif_err("get irq fail\n"); - return -1; - } - - irq = mc->irq_phone_active; - mif_info("PHONE_ACTIVE IRQ# = %d\n", irq); - - flag = IRQF_TRIGGER_HIGH; - ret = request_irq(irq, phone_active_handler, flag, "cbp_active", mc); - if (ret) { - mif_err("request_irq fail (%d)\n", ret); - return ret; - } - - wake_lock_init(&mc->mc_wake_lock, WAKE_LOCK_SUSPEND, "cbp72_wake_lock"); - - ret = enable_irq_wake(irq); - if (ret) - mif_err("enable_irq_wake fail (%d)\n", ret); - - return 0; -} - diff --git a/drivers/misc/modem_if/modem_modemctl_device_cmc221.c b/drivers/misc/modem_if/modem_modemctl_device_cmc221.c deleted file mode 100644 index eddc91ae15b..00000000000 --- a/drivers/misc/modem_if/modem_modemctl_device_cmc221.c +++ /dev/null @@ -1,317 +0,0 @@ -/* /linux/drivers/misc/modem_if/modem_modemctl_device_cmc221.c - * - * Copyright (C) 2010 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/init.h> - -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/platform_device.h> - -#include <linux/platform_data/modem.h> -#include "modem_prj.h" -#include "modem_link_device_usb.h" -#include "modem_link_device_dpram.h" -#include "modem_utils.h" - -#define PIF_TIMEOUT (180 * HZ) -#define DPRAM_INIT_TIMEOUT (30 * HZ) - -static void mc_state_fsm(struct modem_ctl *mc) -{ - struct link_device *ld = get_current_link(mc->iod); - int cp_on = gpio_get_value(mc->gpio_cp_on); - int cp_reset = gpio_get_value(mc->gpio_cp_reset); - int cp_active = gpio_get_value(mc->gpio_phone_active); - int old_state = mc->phone_state; - int new_state = mc->phone_state; - - mif_err("%s: old_state:%d cp_on:%d cp_reset:%d cp_active:%d\n", - mc->name, old_state, cp_on, cp_reset, cp_active); - - if (!cp_active) { - if (!cp_on) { - gpio_set_value(mc->gpio_cp_reset, 0); - new_state = STATE_OFFLINE; - ld->mode = LINK_MODE_OFFLINE; - mif_err("%s: new_state = PHONE_PWR_OFF\n", mc->name); - } else if (old_state == STATE_ONLINE) { - new_state = STATE_CRASH_EXIT; - mif_err("%s: new_state = CRASH_EXIT\n", mc->name); - } else { - mif_err("%s: Don't care!!!\n", mc->name); - } - } - - if (old_state != new_state) { - mc->bootd->modem_state_changed(mc->bootd, new_state); - mc->iod->modem_state_changed(mc->iod, new_state); - } -} - -static irqreturn_t phone_active_handler(int irq, void *arg) -{ - struct modem_ctl *mc = (struct modem_ctl *)arg; - int cp_reset = gpio_get_value(mc->gpio_cp_reset); - - if (cp_reset) - mc_state_fsm(mc); - - return IRQ_HANDLED; -} - -/* TX dynamic switching between DPRAM and USB in one modem */ -static irqreturn_t dynamic_switching_handler(int irq, void *arg) -{ - struct modem_ctl *mc = (struct modem_ctl *)arg; - int txpath = gpio_get_value(mc->gpio_dynamic_switching); - bool enumerated = usb_is_enumerated(mc->msd); - - mif_err("txpath=%d, enumeration=%d\n", txpath, enumerated); - - /* do not switch to USB, when USB is not enumerated. */ - if (!enumerated && txpath) { - mc->need_switch_to_usb = true; - return IRQ_HANDLED; - } - - mc->need_switch_to_usb = false; - rawdevs_set_tx_link(mc->msd, txpath ? LINKDEV_USB : LINKDEV_DPRAM); - - return IRQ_HANDLED; -} - -static int cmc221_on(struct modem_ctl *mc) -{ - struct link_device *ld = get_current_link(mc->iod); - - if (!wake_lock_active(&mc->mc_wake_lock)) - wake_lock(&mc->mc_wake_lock); - set_sromc_access(true); - - mc->phone_state = STATE_OFFLINE; - ld->mode = LINK_MODE_OFFLINE; - - mif_err("%s\n", mc->name); - - disable_irq_nosync(mc->irq_phone_active); - - gpio_set_value(mc->gpio_cp_on, 0); - msleep(100); - - gpio_set_value(mc->gpio_cp_reset, 0); - msleep(500); - - gpio_set_value(mc->gpio_cp_on, 1); - msleep(100); - - gpio_set_value(mc->gpio_cp_reset, 1); - - return 0; -} - -static int cmc221_off(struct modem_ctl *mc) -{ - int cp_on = gpio_get_value(mc->gpio_cp_on); - - mif_err("%s\n", mc->name); - - if (mc->phone_state == STATE_OFFLINE || cp_on == 0) - return 0; - - if (!wake_lock_active(&mc->mc_wake_lock)) - wake_lock(&mc->mc_wake_lock); - set_sromc_access(true); - - gpio_set_value(mc->gpio_cp_on, 0); - - return 0; -} - -static int cmc221_force_crash_exit(struct modem_ctl *mc) -{ - struct link_device *ld = get_current_link(mc->bootd); - - mif_err("%s\n", mc->name); - - /* Make DUMP start */ - ld->force_dump(ld, mc->bootd); - - return 0; -} - -static int cmc221_dump_reset(struct modem_ctl *mc) -{ - mif_err("%s\n", mc->name); - - if (!wake_lock_active(&mc->mc_wake_lock)) - wake_lock(&mc->mc_wake_lock); - set_sromc_access(true); - - gpio_set_value(mc->gpio_host_active, 0); - gpio_set_value(mc->gpio_cp_reset, 0); - - udelay(200); - - gpio_set_value(mc->gpio_cp_reset, 1); - - msleep(300); - - return 0; -} - -static int cmc221_reset(struct modem_ctl *mc) -{ - mif_err("%s\n", mc->name); - - if (cmc221_off(mc)) - return -ENXIO; - - msleep(100); - - if (cmc221_on(mc)) - return -ENXIO; - - return 0; -} - -static int cmc221_boot_on(struct modem_ctl *mc) -{ - mif_err("%s\n", mc->name); - - gpio_set_value(mc->gpio_pda_active, 1); - - mc->bootd->modem_state_changed(mc->bootd, STATE_BOOTING); - mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); - - return 0; -} - -static int cmc221_boot_off(struct modem_ctl *mc) -{ - int ret; - struct link_device *ld = get_current_link(mc->bootd); - struct dpram_link_device *dpld = to_dpram_link_device(ld); - - mif_err("%s\n", mc->name); - - ret = wait_for_completion_interruptible_timeout(&dpld->dpram_init_cmd, - DPRAM_INIT_TIMEOUT); - if (!ret) { - /* ret == 0 on timeout, ret < 0 if interrupted */ - mif_err("%s: ERR! timeout (CP_START not arrived)\n", mc->name); - return -ENXIO; - } - - enable_irq(mc->irq_phone_active); - - return 0; -} - -static int cmc221_boot_done(struct modem_ctl *mc) -{ - mif_err("%s\n", mc->name); - - set_sromc_access(false); - if (wake_lock_active(&mc->mc_wake_lock)) - wake_unlock(&mc->mc_wake_lock); - - return 0; -} - -static void cmc221_get_ops(struct modem_ctl *mc) -{ - mc->ops.modem_on = cmc221_on; - mc->ops.modem_off = cmc221_off; - mc->ops.modem_reset = cmc221_reset; - mc->ops.modem_boot_on = cmc221_boot_on; - mc->ops.modem_boot_off = cmc221_boot_off; - mc->ops.modem_boot_done = cmc221_boot_done; - mc->ops.modem_force_crash_exit = cmc221_force_crash_exit; - mc->ops.modem_dump_reset = cmc221_dump_reset; -} - -int cmc221_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata) -{ - int ret = 0; - int irq = 0; - unsigned long flag = 0; - struct platform_device *pdev = NULL; - - mc->gpio_cp_on = pdata->gpio_cp_on; - mc->gpio_cp_reset = pdata->gpio_cp_reset; - mc->gpio_phone_active = pdata->gpio_phone_active; - mc->gpio_pda_active = pdata->gpio_pda_active; -#if 0 /*TODO: check the GPIO map*/ - mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int; - mc->gpio_flm_uart_sel = pdata->gpio_flm_uart_sel; - mc->gpio_slave_wakeup = pdata->gpio_slave_wakeup; - mc->gpio_host_active = pdata->gpio_host_active; - mc->gpio_host_wakeup = pdata->gpio_host_wakeup; -#endif - mc->gpio_dynamic_switching = pdata->gpio_dynamic_switching; - mc->need_switch_to_usb = false; - - if (!mc->gpio_cp_on || !mc->gpio_cp_reset || !mc->gpio_phone_active) { - mif_err("%s: ERR! no GPIO data\n", mc->name); - return -ENXIO; - } - - gpio_set_value(mc->gpio_cp_reset, 0); - gpio_set_value(mc->gpio_cp_on, 0); - - cmc221_get_ops(mc); - dev_set_drvdata(mc->dev, mc); - - pdev = to_platform_device(mc->dev); - mc->irq_phone_active = platform_get_irq_byname(pdev, STR_CP_ACTIVE_IRQ); - if (!mc->irq_phone_active) { - mif_err("%s: ERR! get cp_active_irq fail\n", mc->name); - return -1; - } - mif_err("%s: PHONE_ACTIVE IRQ# = %d\n", mc->name, mc->irq_phone_active); - - wake_lock_init(&mc->mc_wake_lock, WAKE_LOCK_SUSPEND, "cmc_wake_lock"); - - flag = IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND; - irq = mc->irq_phone_active; - ret = request_irq(irq, phone_active_handler, flag, "cmc_active", mc); - if (ret) { - mif_err("%s: ERR! request_irq(#%d) fail (err %d)\n", - mc->name, irq, ret); - return ret; - } - ret = enable_irq_wake(irq); - if (ret) { - mif_err("%s: WARNING! enable_irq_wake(#%d) fail (err %d)\n", - mc->name, irq, ret); - } - - flag = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND; - if (mc->gpio_dynamic_switching) { - irq = gpio_to_irq(mc->gpio_dynamic_switching); - mif_err("%s: DYNAMIC_SWITCH IRQ# = %d\n", mc->name, irq); - ret = request_irq(irq, dynamic_switching_handler, flag, - "dynamic_switching", mc); - if (ret) { - mif_err("%s: ERR! request_irq(#%d) fail (err %d)\n", - mc->name, irq, ret); - return ret; - } - } - - return 0; -} diff --git a/drivers/misc/modem_if/modem_modemctl_device_esc6270.c b/drivers/misc/modem_if/modem_modemctl_device_esc6270.c deleted file mode 100644 index f35e4ccd95c..00000000000 --- a/drivers/misc/modem_if/modem_modemctl_device_esc6270.c +++ /dev/null @@ -1,348 +0,0 @@ -/* /linux/drivers/misc/modem_if/modem_modemctl_device_esc6270.c - * - * Copyright (C) 2010 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/init.h> - -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/wait.h> -#include <linux/sched.h> -#include <linux/platform_device.h> - -#include <linux/platform_data/modem.h> -#include "modem_prj.h" -#include <linux/regulator/consumer.h> - -#include <plat/gpio-cfg.h> - -#if defined(CONFIG_LINK_DEVICE_DPRAM) -#include "modem_link_device_dpram.h" -#elif defined(CONFIG_LINK_DEVICE_PLD) -#include "modem_link_device_pld.h" -#endif - -#if defined(CONFIG_LINK_DEVICE_DPRAM) || defined(CONFIG_LINK_DEVICE_PLD) -#include <linux/mfd/max77693.h> - -#define PIF_TIMEOUT (180 * HZ) -#define DPRAM_INIT_TIMEOUT (30 * HZ) - -static int esc6270_on(struct modem_ctl *mc) -{ - int ret; - struct link_device *ld = get_current_link(mc->iod); - - pr_info("[MODEM_IF:ESC] <%s> start!!!\n", __func__); - - if (!mc->gpio_cp_reset) { - pr_err("[MODEM_IF:ESC] no gpio data\n"); - return -ENXIO; - } - - if (mc->gpio_reset_req_n) - gpio_set_value(mc->gpio_reset_req_n, 1); - - gpio_set_value(mc->gpio_cp_reset, 1); - msleep(30); - - gpio_set_value(mc->gpio_cp_on, 1); - msleep(500); - - gpio_set_value(mc->gpio_cp_on, 0); - msleep(500); - - gpio_set_value(mc->gpio_pda_active, 1); - - mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); - ld->mode = LINK_MODE_BOOT; - - return 0; -} - -static int esc6270_off(struct modem_ctl *mc) -{ - pr_info("[MODEM_IF:ESC] esc6270_off()\n"); - -#if 1 - if (!mc->gpio_cp_reset) { - pr_err("[MODEM_IF:ESC] no gpio data\n"); - return -ENXIO; - } - - gpio_set_value(mc->gpio_cp_reset, 0); - gpio_set_value(mc->gpio_cp_on, 0); -#endif - - mc->iod->modem_state_changed(mc->iod, STATE_OFFLINE); - - return 0; -} - -static int esc6270_reset(struct modem_ctl *mc) -{ - int ret = 0; - - pr_debug("[MODEM_IF:ESC] esc6270_reset()\n"); - - ret = esc6270_off(mc); - if (ret) - return -ENXIO; - - msleep(100); - - ret = esc6270_on(mc); - if (ret) - return -ENXIO; - - return 0; -} - -int esc6270_boot_on(struct modem_ctl *mc) -{ - struct link_device *ld = get_current_link(mc->iod); - - pr_info("[MODEM_IF:ESC] <%s>\n", __func__); - - /* Need to init uart byt gpio_flm_uart_sel GPIO */ - if (!mc->gpio_cp_reset || !mc->gpio_flm_uart_sel) { - pr_err("[MODEM_IF:ESC] no gpio data\n"); - return -ENXIO; - } - gpio_set_value(mc->gpio_flm_uart_sel, 1); - - pr_info(" - ESC_PHONE_ON : %d, ESC_RESET_N : %d\n", - gpio_get_value(mc->gpio_cp_on), - gpio_get_value(mc->gpio_cp_reset)); - - gpio_set_value(mc->gpio_cp_on, 0); - gpio_direction_output(mc->gpio_cp_reset, 0); - msleep(100); - - gpio_direction_output(mc->gpio_cp_on, 1); - msleep(44); - - pr_info(" - ESC_PHONE_ON : %d, ESC_RESET_N : %d\n", - gpio_get_value(mc->gpio_cp_on), - gpio_get_value(mc->gpio_cp_reset)); - - gpio_direction_input(mc->gpio_cp_reset); - msleep(600); - gpio_direction_output(mc->gpio_cp_on, 0); - - msleep(20); - pr_info(" - ESC_PHONE_ON : %d, ESC_RESET_N : %d\n", - gpio_get_value(mc->gpio_cp_on), - gpio_get_value(mc->gpio_cp_reset)); - - mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); - ld->mode = LINK_MODE_BOOT; - - return 0; -} - -static int esc6270_boot_off(struct modem_ctl *mc) -{ - pr_info("[MODEM_IF:ESC] <%s>\n", __func__); - - if (!mc->gpio_flm_uart_sel) { - pr_err("[MODEM_IF:ESC] no gpio data\n"); - return -ENXIO; - } - - gpio_set_value(mc->gpio_flm_uart_sel, 0); - - mc->iod->modem_state_changed(mc->iod, STATE_OFFLINE); - - return 0; -} - -static int esc6270_active_count; - -static irqreturn_t phone_active_irq_handler(int irq, void *arg) -{ - struct modem_ctl *mc = (struct modem_ctl *)arg; - int phone_reset = 0; - int phone_active = 0; - int phone_state = 0; - int cp_dump_int = 0; - - if (!mc->gpio_cp_reset || - !mc->gpio_phone_active) { /* || !mc->gpio_cp_dump_int) { */ - pr_err("[MODEM_IF:ESC] no gpio data\n"); - return IRQ_HANDLED; - } - - phone_reset = gpio_get_value(mc->gpio_cp_reset); - phone_active = gpio_get_value(mc->gpio_phone_active); - cp_dump_int = gpio_get_value(mc->gpio_cp_dump_int); - - pr_info("[MODEM_IF:ESC] <%s> phone_reset=%d, phone_active=%d, cp_dump_int=%d\n", - __func__, phone_reset, phone_active, cp_dump_int); - - if (phone_reset && phone_active) { - phone_state = STATE_ONLINE; - if (mc->iod && mc->iod->modem_state_changed) - mc->iod->modem_state_changed(mc->iod, phone_state); - } else if (phone_reset && !phone_active) { - if (mc->phone_state == STATE_ONLINE) { - phone_state = STATE_CRASH_EXIT; - if (mc->iod && mc->iod->modem_state_changed) - mc->iod->modem_state_changed(mc->iod, - phone_state); - } - } else { - phone_state = STATE_OFFLINE; - if (mc->iod && mc->iod->modem_state_changed) - mc->iod->modem_state_changed(mc->iod, phone_state); - } - - if (phone_active) - irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_LOW); - else - irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_HIGH); - - pr_info("[MODEM_IF::ESC] <%s> phone_state = %d\n", - __func__, phone_state); - - return IRQ_HANDLED; -} - -#if defined(CONFIG_SIM_DETECT) -#if defined(CONFIG_MACH_GRANDE) -static void sim_detect_work(struct work_struct *work) -{ - struct modem_ctl *mc = - container_of(work, struct modem_ctl, sim_det_dwork.work); - - pr_info("[MODEM_IF:ESC] <%s> gpio_sim_detect = %d\n", - __func__, gpio_get_value(mc->gpio_sim_detect)); - - if (mc->iod && mc->iod->sim_state_changed) - mc->iod->sim_state_changed(mc->iod, - !gpio_get_value(mc->gpio_sim_detect)); -} -#endif -static irqreturn_t sim_detect_irq_handler(int irq, void *_mc) -{ - struct modem_ctl *mc = (struct modem_ctl *)_mc; - - pr_info("[MODEM_IF:ESC] <%s> gpio_sim_detect = %d\n", - __func__, gpio_get_value(mc->gpio_sim_detect)); - -#if defined(CONFIG_MACH_GRANDE) - schedule_delayed_work(&mc->sim_det_dwork, msecs_to_jiffies(400)); -#else - if (mc->iod && mc->iod->sim_state_changed) - mc->iod->sim_state_changed(mc->iod, - !gpio_get_value(mc->gpio_sim_detect)); -#endif - return IRQ_HANDLED; -} -#endif - -static void esc6270_get_ops(struct modem_ctl *mc) -{ - mc->ops.modem_on = esc6270_on; - mc->ops.modem_off = esc6270_off; - mc->ops.modem_reset = esc6270_reset; - mc->ops.modem_boot_on = esc6270_boot_on; - mc->ops.modem_boot_off = esc6270_boot_off; -} - -int esc6270_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata) -{ - int ret = 0; - struct platform_device *pdev; - - mc->gpio_cp_on = pdata->gpio_cp_on; - mc->gpio_reset_req_n = pdata->gpio_reset_req_n; - mc->gpio_cp_reset = pdata->gpio_cp_reset; - mc->gpio_pda_active = pdata->gpio_pda_active; - mc->gpio_phone_active = pdata->gpio_phone_active; - mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int; - mc->gpio_flm_uart_sel = pdata->gpio_flm_uart_sel; - mc->gpio_cp_warm_reset = pdata->gpio_cp_warm_reset; - mc->gpio_sim_detect = pdata->gpio_sim_detect; - - gpio_set_value(mc->gpio_cp_reset, 0); - gpio_set_value(mc->gpio_cp_on, 0); - - pdev = to_platform_device(mc->dev); - mc->irq_phone_active = platform_get_irq_byname(pdev, "cp_active_irq"); - pr_info("[MODEM_IF:ESC] <%s> PHONE_ACTIVE IRQ# = %d\n", - __func__, mc->irq_phone_active); - - esc6270_get_ops(mc); - - if (mc->irq_phone_active) { - ret = request_irq(mc->irq_phone_active, - phone_active_irq_handler, - IRQF_TRIGGER_HIGH, - "esc_active", - mc); - if (ret) { - pr_err("[MODEM_IF:ESC] <%s> failed to request_irq IRQ# %d (err=%d)\n", - __func__, mc->irq_phone_active, ret); - return ret; - } - - ret = enable_irq_wake(mc->irq_phone_active); - if (ret) { - pr_err("[MODEM_IF:ESC] %s: failed to enable_irq_wake IRQ# %d (err=%d)\n", - __func__, mc->irq_phone_active, ret); - free_irq(mc->irq_phone_active, mc); - return ret; - } - } - -#if defined(CONFIG_SIM_DETECT) -#if defined(CONFIG_MACH_GRANDE) - INIT_DELAYED_WORK(&mc->sim_det_dwork, sim_detect_work); -#endif - mc->irq_sim_detect = platform_get_irq_byname(pdev, "sim_irq"); - pr_info("[MODEM_IF:ESC] <%s> SIM_DECTCT IRQ# = %d\n", - __func__, mc->irq_sim_detect); - - if (mc->irq_sim_detect) { - ret = request_irq(mc->irq_sim_detect, sim_detect_irq_handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "esc_sim_detect", mc); - if (ret) { - mif_err("failed to request_irq: %d\n", ret); - mc->sim_state.online = false; - mc->sim_state.changed = false; - return ret; - } - - ret = enable_irq_wake(mc->irq_sim_detect); - if (ret) { - mif_err("failed to enable_irq_wake: %d\n", ret); - free_irq(mc->irq_sim_detect, mc); - mc->sim_state.online = false; - mc->sim_state.changed = false; - return ret; - } - - /* initialize sim_state => insert: gpio=0, remove: gpio=1 */ - mc->sim_state.online = !gpio_get_value(mc->gpio_sim_detect); - } -#endif - - return ret; -} -#endif diff --git a/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c b/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c deleted file mode 100644 index 129f790fdf8..00000000000 --- a/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c +++ /dev/null @@ -1,801 +0,0 @@ -/* /linux/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c - * - * Copyright (C) 2010 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/init.h> - -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/wait.h> -#include <linux/sched.h> -#include <linux/platform_device.h> - -#include <linux/platform_data/modem.h> -#include "modem_prj.h" -#include <linux/regulator/consumer.h> - -#include <plat/gpio-cfg.h> - -#if defined(CONFIG_MACH_M0_CTC) -#include <linux/mfd/max77693.h> -#endif - -#if defined(CONFIG_MACH_U1_KOR_LGT) -#include <linux/mfd/max8997.h> - -static int mdm6600_on(struct modem_ctl *mc) -{ - pr_info("[MODEM_IF] mdm6600_on()\n"); - - if (!mc->gpio_cp_reset || !mc->gpio_cp_reset_msm || !mc->gpio_cp_on) { - pr_err("[MODEM_IF] no gpio data\n"); - return -ENXIO; - } - - gpio_set_value(mc->gpio_pda_active, 0); - gpio_set_value(mc->gpio_cp_reset, 1); - gpio_set_value(mc->gpio_cp_reset_msm, 1); - msleep(30); - gpio_set_value(mc->gpio_cp_on, 1); - msleep(300); - gpio_set_value(mc->gpio_cp_on, 0); - msleep(500); - - gpio_set_value(mc->gpio_pda_active, 1); - - mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); - - return 0; -} - -static int mdm6600_off(struct modem_ctl *mc) -{ - pr_info("[MODEM_IF] mdm6600_off()\n"); - - if (!mc->gpio_cp_reset || !mc->gpio_cp_reset_msm || !mc->gpio_cp_on) { - pr_err("[MODEM_IF] no gpio data\n"); - return -ENXIO; - } - - gpio_set_value(mc->gpio_cp_on, 0); - gpio_set_value(mc->gpio_cp_reset, 0); - gpio_set_value(mc->gpio_cp_reset_msm, 0); - - mc->iod->modem_state_changed(mc->iod, STATE_OFFLINE); - - return 0; -} - -static int mdm6600_reset(struct modem_ctl *mc) -{ - int ret; - - pr_info("[MODEM_IF] mdm6600_reset()\n"); - - if (!mc->gpio_cp_reset || !mc->gpio_cp_reset_msm || !mc->gpio_cp_on) { - pr_err("[MODEM_IF] no gpio data\n"); - return -ENXIO; - } - - if (system_rev >= 0x05) { - dev_err(mc->dev, "[%s] system_rev: %d\n", __func__, system_rev); - - gpio_set_value(mc->gpio_cp_reset_msm, 0); - msleep(100); /* no spec, confirm later exactly how much time - needed to initialize CP with RESET_PMU_N */ - gpio_set_value(mc->gpio_cp_reset_msm, 1); - msleep(40); /* > 37.2 + 2 msec */ - } else { - dev_err(mc->dev, "[%s] system_rev: %d\n", __func__, system_rev); - - gpio_set_value(mc->gpio_cp_reset, 0); - msleep(500); /* no spec, confirm later exactly how much time - needed to initialize CP with RESET_PMU_N */ - gpio_set_value(mc->gpio_cp_reset, 1); - msleep(40); /* > 37.2 + 2 msec */ - } - - return 0; -} - -static int mdm6600_boot_on(struct modem_ctl *mc) -{ - pr_info("[MODEM_IF] mdm6600_boot_on()\n"); - - if (!mc->gpio_boot_sw_sel) { - pr_err("[MODEM_IF] no gpio data\n"); - return -ENXIO; - } - - if (mc->vbus_on) - mc->vbus_on(); - - if (mc->gpio_boot_sw_sel) - gpio_set_value(mc->gpio_boot_sw_sel, 0); - mc->usb_boot = true; - - return 0; -} - -static int mdm6600_boot_off(struct modem_ctl *mc) -{ - pr_info("[MODEM_IF] mdm6600_boot_off()\n"); - - if (!mc->gpio_boot_sw_sel) { - pr_err("[MODEM_IF] no gpio data\n"); - return -ENXIO; - } - - if (mc->vbus_off) - mc->vbus_off(); - - if (mc->gpio_boot_sw_sel) - gpio_set_value(mc->gpio_boot_sw_sel, 1); - mc->usb_boot = false; - - return 0; -} - -static int count; - -static irqreturn_t phone_active_irq_handler(int irq, void *_mc) -{ - int phone_reset = 0; - int phone_active_value = 0; - int cp_dump_value = 0; - int phone_state = 0; - struct modem_ctl *mc = (struct modem_ctl *)_mc; - - if (!mc->gpio_cp_reset || !mc->gpio_phone_active -/*|| !mc->gpio_cp_dump_int */) { - pr_err("[MODEM_IF] no gpio data\n"); - return IRQ_HANDLED; - } - - phone_reset = gpio_get_value(mc->gpio_cp_reset); - phone_active_value = gpio_get_value(mc->gpio_phone_active); - - pr_info("[MODEM_IF] PA EVENT : reset =%d, pa=%d, cp_dump=%d\n", - phone_reset, phone_active_value, cp_dump_value); - - if (phone_reset && phone_active_value) { - phone_state = STATE_ONLINE; - if (mc->iod && mc->iod->modem_state_changed) - mc->iod->modem_state_changed(mc->iod, phone_state); - } else if (phone_reset && !phone_active_value) { - if (count == 1) { - phone_state = STATE_CRASH_EXIT; - if (mc->iod) { - ld = get_current_link(mc->iod); - if (ld->terminate_comm) - ld->terminate_comm(ld, mc->iod); - } - if (mc->iod && mc->iod->modem_state_changed) - mc->iod->modem_state_changed - (mc->iod, phone_state); - count = 0; - } else { - count++; - } - } else { - phone_state = STATE_OFFLINE; - if (mc->iod && mc->iod->modem_state_changed) - mc->iod->modem_state_changed(mc->iod, phone_state); - } - - pr_info("phone_active_irq_handler : phone_state=%d\n", phone_state); - - return IRQ_HANDLED; -} - -static void mdm6600_get_ops(struct modem_ctl *mc) -{ - mc->ops.modem_on = mdm6600_on; - mc->ops.modem_off = mdm6600_off; - mc->ops.modem_reset = mdm6600_reset; - mc->ops.modem_boot_on = mdm6600_boot_on; - mc->ops.modem_boot_off = mdm6600_boot_off; -} - -int mdm6600_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata) -{ - int ret; - struct platform_device *pdev; - - mc->gpio_cp_on = pdata->gpio_cp_on; - mc->gpio_cp_reset = pdata->gpio_cp_reset; - mc->gpio_pda_active = pdata->gpio_pda_active; - mc->gpio_phone_active = pdata->gpio_phone_active; - mc->gpio_cp_reset_msm = pdata->gpio_cp_reset_msm; - mc->gpio_boot_sw_sel = pdata->gpio_boot_sw_sel; - - mc->vbus_on = pdata->vbus_on; - mc->vbus_off = pdata->vbus_off; - - pdev = to_platform_device(mc->dev); - mc->irq_phone_active = platform_get_irq_byname(pdev, "cp_active_irq"); - pr_info("[MODEM_IF] <%s> PHONE_ACTIVE IRQ# = %d\n", - __func__, mc->irq_phone_active); - - mdm6600_get_ops(mc); - - ret = request_irq(mc->irq_phone_active, phone_active_irq_handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "phone_active", mc); - if (ret) { - pr_err("[MODEM_IF] %s: failed to request_irq:%d\n", - __func__, ret); - goto err_request_irq; - } - - ret = enable_irq_wake(mc->irq_phone_active); - if (ret) { - pr_err("[MODEM_IF] %s: failed to enable_irq_wake:%d\n", - __func__, ret); - goto err_set_wake_irq; - } - - return ret; - - err_set_wake_irq: - free_irq(mc->irq_phone_active, mc); - err_request_irq: - return ret; -} -#endif /* CONFIG_MACH_U1_KOR_LGT */ - -#if defined(CONFIG_MACH_M0_CTC) || defined(CONFIG_MACH_T0_CHN_CTC) - -#if defined(CONFIG_LINK_DEVICE_DPRAM) -#include "modem_link_device_dpram.h" -#elif defined(CONFIG_LINK_DEVICE_PLD) -#include "modem_link_device_pld.h" -#endif - -#define PIF_TIMEOUT (180 * HZ) -#define DPRAM_INIT_TIMEOUT (30 * HZ) - -#if defined(CONFIG_MACH_M0_DUOSCTC) || defined(CONFIG_MACH_M0_GRANDECTC) || \ - defined(CONFIG_MACH_T0_CHN_CTC) -static void mdm6600_vbus_on(void) -{ - struct regulator *regulator; - - pr_info("[MSM] <%s>\n", __func__); - -#if defined(CONFIG_MACH_T0_CHN_CTC) - if (system_rev == 4) - regulator = regulator_get(NULL, "vcc_1.8v_lcd"); - else - regulator = regulator_get(NULL, "vcc_1.8v_usb"); -#else - regulator = regulator_get(NULL, "vusbhub_osc_1.8v"); -#endif - if (IS_ERR(regulator)) { - pr_err("[MSM] error getting regulator_get <%s>\n", __func__); - return ; - } - regulator_enable(regulator); - regulator_put(regulator); - - pr_info("[MSM] <%s> enable\n", __func__); -} - -static void mdm6600_vbus_off(void) -{ - struct regulator *regulator; - - pr_info("[MSM] <%s>\n", __func__); - -#if defined(CONFIG_MACH_T0_CHN_CTC) - if (system_rev == 4) - regulator = regulator_get(NULL, "vcc_1.8v_lcd"); - else - regulator = regulator_get(NULL, "vcc_1.8v_usb"); -#else - regulator = regulator_get(NULL, "vusbhub_osc_1.8v"); -#endif - if (IS_ERR(regulator)) { - pr_err("[MSM] error getting regulator_get <%s>\n", __func__); - return ; - } - regulator_disable(regulator); - regulator_put(regulator); - - pr_info("[MSM] <%s> disable\n", __func__); -} -#endif - -static int mdm6600_on(struct modem_ctl *mc) -{ - struct link_device *ld = get_current_link(mc->iod); - - pr_info("[MSM] <%s>\n", __func__); - - if (!mc->gpio_reset_req_n || !mc->gpio_cp_reset - || !mc->gpio_cp_on || !mc->gpio_pda_active) { - pr_err("[MSM] no gpio data\n"); - return -ENXIO; - } - - gpio_set_value(mc->gpio_pda_active, 0); - - gpio_set_value(mc->gpio_cp_on, 1); - msleep(500); - - gpio_set_value(mc->gpio_reset_req_n, 1); - msleep(50); - - gpio_set_value(mc->gpio_cp_reset, 1); - msleep(50); - - gpio_set_value(mc->gpio_cp_on, 0); - msleep(500); - - gpio_set_value(mc->gpio_pda_active, 1); - - mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); - ld->mode = LINK_MODE_BOOT; - - return 0; -} - -static int mdm6600_off(struct modem_ctl *mc) -{ - pr_info("[MSM] <%s>\n", __func__); - - if (!mc->gpio_cp_reset || !mc->gpio_cp_on) { - pr_err("[MSM] no gpio data\n"); - return -ENXIO; - } - - gpio_set_value(mc->gpio_cp_reset, 0); - gpio_set_value(mc->gpio_reset_req_n, 0); - gpio_set_value(mc->gpio_cp_on, 0); - - msleep(200); - - mc->iod->modem_state_changed(mc->iod, STATE_OFFLINE); - - return 0; -} - -static int mdm6600_reset(struct modem_ctl *mc) -{ - int ret = 0; - struct link_device *ld = get_current_link(mc->iod); - - pr_info("[MSM] <%s>\n", __func__); - - if (!mc->gpio_reset_req_n || !mc->gpio_cp_reset - || !mc->gpio_cp_on || !mc->gpio_pda_active) { - pr_err("[MSM] no gpio data\n"); - return -ENXIO; - } - - gpio_set_value(mc->gpio_cp_reset, 0); - gpio_set_value(mc->gpio_reset_req_n, 0); - gpio_set_value(mc->gpio_cp_on, 0); - - msleep(100); - - gpio_set_value(mc->gpio_cp_on, 1); - msleep(300); - - gpio_set_value(mc->gpio_reset_req_n, 1); - msleep(50); - - gpio_set_value(mc->gpio_cp_reset, 1); - msleep(50); - - gpio_set_value(mc->gpio_cp_on, 0); - msleep(100); - - gpio_set_value(mc->gpio_pda_active, 1); - - mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); - ld->mode = LINK_MODE_BOOT; - - return 0; -} - -static int mdm6600_boot_on(struct modem_ctl *mc) -{ - struct regulator *regulator; - - pr_info("[MSM] <%s>\n", __func__); - - if (!mc->gpio_flm_uart_sel) { - pr_err("[MSM] no gpio data\n"); - return -ENXIO; - } - -#if defined(CONFIG_MACH_M0_DUOSCTC) || defined(CONFIG_MACH_T0_CHN_CTC) - mdm6600_vbus_on(); -#elif defined(CONFIG_MACH_M0_GRANDECTC) - if (system_rev >= 14) - mdm6600_vbus_on(); -#endif - - pr_info("[MSM] <%s> %s\n", __func__, "USB_BOOT_EN initializing"); - if (system_rev < 11) { - - gpio_direction_output(GPIO_USB_BOOT_EN, 0); - s3c_gpio_setpull(GPIO_USB_BOOT_EN, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN, 0); - - gpio_direction_output(GPIO_BOOT_SW_SEL, 0); - s3c_gpio_setpull(GPIO_BOOT_SW_SEL, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_BOOT_SW_SEL, 0); - - msleep(100); - - gpio_direction_output(GPIO_USB_BOOT_EN, 1); - gpio_set_value(GPIO_USB_BOOT_EN, 1); - - pr_info("[MSM] <%s> USB_BOOT_EN:[%d]\n", __func__, - gpio_get_value(GPIO_USB_BOOT_EN)); - - gpio_direction_output(GPIO_BOOT_SW_SEL, 1); - gpio_set_value(GPIO_BOOT_SW_SEL, 1); - - pr_info("[MSM] <%s> BOOT_SW_SEL : [%d]\n", __func__, - gpio_get_value(GPIO_BOOT_SW_SEL)); - } else if (system_rev == 11) { - gpio_direction_output(GPIO_USB_BOOT_EN, 0); - s3c_gpio_setpull(GPIO_USB_BOOT_EN, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN, 0); - - gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 0); - s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN_REV06, 0); - - msleep(100); - - gpio_direction_output(GPIO_USB_BOOT_EN, 1); - gpio_set_value(GPIO_USB_BOOT_EN, 1); - - pr_info("[MSM] <%s> USB_BOOT_EN:[%d]\n", __func__, - gpio_get_value(GPIO_USB_BOOT_EN)); - - gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 1); - gpio_set_value(GPIO_USB_BOOT_EN_REV06, 1); - - pr_info("[MSM(%d)] <%s> USB_BOOT_EN:[%d]\n", system_rev, - __func__, gpio_get_value(GPIO_USB_BOOT_EN_REV06)); - - gpio_direction_output(GPIO_BOOT_SW_SEL, 0); - s3c_gpio_setpull(GPIO_BOOT_SW_SEL, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_BOOT_SW_SEL, 0); - - gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 0); - s3c_gpio_setpull(GPIO_BOOT_SW_SEL_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 0); - - msleep(100); - - gpio_direction_output(GPIO_BOOT_SW_SEL, 1); - gpio_set_value(GPIO_BOOT_SW_SEL, 1); - - pr_info("[MSM] <%s> BOOT_SW_SEL : [%d]\n", __func__, - gpio_get_value(GPIO_BOOT_SW_SEL)); - - gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 1); - gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 1); - - pr_info("[MSM(%d)] <%s> BOOT_SW_SEL : [%d]\n", system_rev, - __func__, gpio_get_value(GPIO_BOOT_SW_SEL_REV06)); - - } else { /* system_rev>11 */ - gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 0); - s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN_REV06, 0); - - gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 0); - s3c_gpio_setpull(GPIO_BOOT_SW_SEL_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 0); - - msleep(100); - - gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 1); - gpio_set_value(GPIO_USB_BOOT_EN_REV06, 1); - - pr_info("[MSM] <%s> USB_BOOT_EN:[%d]\n", __func__, - gpio_get_value(GPIO_USB_BOOT_EN_REV06)); - - gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 1); - gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 1); - - pr_info("[MSM] <%s> BOOT_SW_SEL : [%d]\n", __func__, - gpio_get_value(GPIO_BOOT_SW_SEL_REV06)); - - } - - mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); - - return 0; -} - -static int mdm6600_boot_off(struct modem_ctl *mc) -{ - pr_info("[MSM] <%s>\n", __func__); - - if (!mc->gpio_flm_uart_sel -#if defined(CONFIG_MACH_M0_CTC) - || !mc->gpio_flm_uart_sel_rev06 -#endif - ) { - pr_err("[MSM] no gpio data\n"); - return -ENXIO; - } - -#if defined(CONFIG_MACH_M0_DUOSCTC) || defined(CONFIG_MACH_T0_CHN_CTC) - mdm6600_vbus_off(); -#elif defined(CONFIG_MACH_M0_GRANDECTC) - if (system_rev >= 14) - mdm6600_vbus_off(); -#endif - - if (system_rev < 11) { - gpio_direction_output(GPIO_USB_BOOT_EN, 0); - s3c_gpio_setpull(GPIO_USB_BOOT_EN, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN, 0); - gpio_direction_output(GPIO_BOOT_SW_SEL, 0); - s3c_gpio_setpull(GPIO_BOOT_SW_SEL, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_BOOT_SW_SEL, 0); - - } else if (system_rev == 11) { - gpio_direction_output(GPIO_USB_BOOT_EN, 0); - s3c_gpio_setpull(GPIO_USB_BOOT_EN, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN, 0); - - gpio_direction_output(GPIO_BOOT_SW_SEL, 0); - s3c_gpio_setpull(GPIO_BOOT_SW_SEL, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_BOOT_SW_SEL, 0); - -#if defined(CONFIG_MACH_M0_CTC) - gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 0); - s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN_REV06, 0); - - gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 0); - s3c_gpio_setpull(GPIO_BOOT_SW_SEL_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 0); -#endif - - } else { /* system_rev>11 */ -#if defined(CONFIG_MACH_M0_CTC) - gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 0); - s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN_REV06, 0); - - gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 0); - s3c_gpio_setpull(GPIO_BOOT_SW_SEL_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 0); -#endif - } - -#if defined(CONFIG_MACH_M0_CTC) - if (max7693_muic_cp_usb_state()) { - msleep(30); - gpio_direction_output(GPIO_USB_BOOT_EN, 1); - s3c_gpio_setpull(GPIO_USB_BOOT_EN, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN, 1); - gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 1); - s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN_REV06, 1); - } -#endif - - gpio_set_value(GPIO_BOOT_SW_SEL, 0); - - return 0; -} - - -static int mdm6600_force_crash_exit(struct modem_ctl *mc) -{ - pr_info("[MSM] <%s>\n", __func__); - - if (!mc->gpio_cp_reset || !mc->gpio_cp_on) { - pr_err("[MSM] no gpio data\n"); - return -ENXIO; - } - - s3c_gpio_cfgpin(mc->gpio_cp_dump_int, S3C_GPIO_OUTPUT); - gpio_direction_output(mc->gpio_cp_dump_int, 1); - - gpio_set_value(mc->gpio_cp_reset, 0); - gpio_set_value(mc->gpio_cp_on, 0); - gpio_set_value(mc->gpio_cp_reset, 1); - - return 0; -} - -static irqreturn_t phone_active_irq_handler(int irq, void *arg) -{ - struct modem_ctl *mc = (struct modem_ctl *)arg; - int phone_reset = 0; - int phone_active = 0; - int phone_state = 0; - int cp_dump_int = 0; - - if (!mc->gpio_cp_reset || - !mc->gpio_phone_active || !mc->gpio_cp_dump_int) { - pr_err("[MSM] no gpio data\n"); - return IRQ_HANDLED; - } - - phone_reset = gpio_get_value(mc->gpio_cp_reset); - phone_active = gpio_get_value(mc->gpio_phone_active); - cp_dump_int = gpio_get_value(mc->gpio_cp_dump_int); - - pr_info("[MSM] <%s> phone_reset=%d, phone_active=%d, cp_dump_int=%d\n", - __func__, phone_reset, phone_active, cp_dump_int); - - if (phone_reset && phone_active) { - phone_state = STATE_ONLINE; - if (mc->iod && mc->iod->modem_state_changed) - mc->iod->modem_state_changed(mc->iod, phone_state); - } else if (phone_reset && !phone_active) { - if (mc->phone_state == STATE_ONLINE) { - phone_state = STATE_CRASH_EXIT; - - if (mc->iod && mc->iod->modem_state_changed) - mc->iod->modem_state_changed(mc->iod, - phone_state); - } - } else { - phone_state = STATE_OFFLINE; - if (mc->iod && mc->iod->modem_state_changed) - mc->iod->modem_state_changed(mc->iod, phone_state); - } - - if (phone_active) - irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_LOW); - else - irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_HIGH); - - pr_info("[MSM] <%s> phone_state = %d\n", __func__, phone_state); - - return IRQ_HANDLED; -} - -#if defined(CONFIG_SIM_DETECT) -#if defined(CONFIG_MACH_GRANDE) -static void sim_detect_work(struct work_struct *work) -{ - struct modem_ctl *mc = - container_of(work, struct modem_ctl, sim_det_dwork.work); - - pr_info("[MSM] <%s> gpio_sim_detect = %d\n", - __func__, gpio_get_value(mc->gpio_sim_detect)); - - if (mc->iod && mc->iod->sim_state_changed) - mc->iod->sim_state_changed(mc->iod, - !gpio_get_value(mc->gpio_sim_detect)); -} -#endif -static irqreturn_t sim_detect_irq_handler(int irq, void *_mc) -{ - struct modem_ctl *mc = (struct modem_ctl *)_mc; - - pr_info("[MSM] <%s> gpio_sim_detect = %d\n", - __func__, gpio_get_value(mc->gpio_sim_detect)); - -#if defined(CONFIG_MACH_GRANDE) - schedule_delayed_work(&mc->sim_det_dwork, msecs_to_jiffies(400)); -#else - if (mc->iod && mc->iod->sim_state_changed) - mc->iod->sim_state_changed(mc->iod, - !gpio_get_value(mc->gpio_sim_detect)); -#endif - return IRQ_HANDLED; -} -#endif - -static void mdm6600_get_ops(struct modem_ctl *mc) -{ - mc->ops.modem_on = mdm6600_on; - mc->ops.modem_off = mdm6600_off; - mc->ops.modem_reset = mdm6600_reset; - mc->ops.modem_boot_on = mdm6600_boot_on; - mc->ops.modem_boot_off = mdm6600_boot_off; - mc->ops.modem_force_crash_exit = mdm6600_force_crash_exit; -} - -int mdm6600_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata) -{ - int ret = 0; - struct platform_device *pdev; - - mc->gpio_cp_on = pdata->gpio_cp_on; - mc->gpio_reset_req_n = pdata->gpio_reset_req_n; - mc->gpio_cp_reset = pdata->gpio_cp_reset; - mc->gpio_pda_active = pdata->gpio_pda_active; - mc->gpio_phone_active = pdata->gpio_phone_active; - mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int; - mc->gpio_flm_uart_sel = pdata->gpio_flm_uart_sel; -#if defined(CONFIG_MACH_M0_CTC) - mc->gpio_flm_uart_sel_rev06 = pdata->gpio_flm_uart_sel_rev06; -#endif - mc->gpio_cp_warm_reset = pdata->gpio_cp_warm_reset; - mc->gpio_sim_detect = pdata->gpio_sim_detect; - - gpio_set_value(mc->gpio_cp_reset, 0); - gpio_set_value(mc->gpio_cp_on, 0); - - pdev = to_platform_device(mc->dev); - mc->irq_phone_active = platform_get_irq_byname(pdev, "cp_active_irq"); - pr_info("[MSM] <%s> PHONE_ACTIVE IRQ# = %d\n", - __func__, mc->irq_phone_active); - - mdm6600_get_ops(mc); - - ret = request_irq(mc->irq_phone_active, - phone_active_irq_handler, - IRQF_TRIGGER_HIGH, "msm_active", mc); - if (ret) { - pr_err("[MSM] <%s> failed to request_irq IRQ# %d (err=%d)\n", - __func__, mc->irq_phone_active, ret); - return ret; - } - - ret = enable_irq_wake(mc->irq_phone_active); - if (ret) { - pr_err("[MSM] %s: failed to enable_irq_wake IRQ# %d (err=%d)\n", - __func__, mc->irq_phone_active, ret); - free_irq(mc->irq_phone_active, mc); - return ret; - } - -#if defined(CONFIG_SIM_DETECT) -#if defined(CONFIG_MACH_GRANDE) - INIT_DELAYED_WORK(&mc->sim_det_dwork, sim_detect_work); -#endif - mc->irq_sim_detect = platform_get_irq_byname(pdev, "sim_irq"); - pr_info("[MSM] <%s> SIM_DECTCT IRQ# = %d\n", - __func__, mc->irq_sim_detect); - - if (mc->irq_sim_detect) { - ret = request_irq(mc->irq_sim_detect, sim_detect_irq_handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "msm_sim_detect", mc); - if (ret) { - mif_err("[MSM] failed to request_irq: %d\n", ret); - mc->sim_state.online = false; - mc->sim_state.changed = false; - return ret; - } - - ret = enable_irq_wake(mc->irq_sim_detect); - if (ret) { - mif_err("[MSM] failed to enable_irq_wake: %d\n", ret); - free_irq(mc->irq_sim_detect, mc); - mc->sim_state.online = false; - mc->sim_state.changed = false; - return ret; - } - - /* initialize sim_state => insert: gpio=0, remove: gpio=1 */ - mc->sim_state.online = !gpio_get_value(mc->gpio_sim_detect); - } -#endif - - return ret; -} -#endif diff --git a/drivers/misc/modem_if/modem_modemctl_device_xmm6260.c b/drivers/misc/modem_if/modem_modemctl_device_xmm6260.c index c2d50677aa6..6a43a67c215 100644 --- a/drivers/misc/modem_if/modem_modemctl_device_xmm6260.c +++ b/drivers/misc/modem_if/modem_modemctl_device_xmm6260.c @@ -22,7 +22,7 @@ #include <linux/delay.h> #include <linux/platform_device.h> -#include <linux/platform_data/modem.h> +#include "modem_tizen.h" #include "modem_prj.h" static int xmm6260_on(struct modem_ctl *mc) @@ -180,7 +180,7 @@ static irqreturn_t phone_active_irq_handler(int irq, void *_mc) if (cp_dump_value) phone_state = STATE_CRASH_EXIT; else - phone_state = STATE_CRASH_RESET; + phone_state = STATE_CRASH_EXIT; if (mc->iod) { ld = get_current_link(mc->iod); if (ld->terminate_comm) diff --git a/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c b/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c index 7438471db3c..2c2e7881688 100644 --- a/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c +++ b/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c @@ -24,7 +24,7 @@ #include <linux/platform_device.h> #include <plat/devs.h> #include <plat/gpio-cfg.h> -#include <linux/platform_data/modem.h> +#include "modem_tizen.h" #include "modem_prj.h" static void xmm_gpio_revers_bias_clear(struct modem_ctl *mc) @@ -54,7 +54,6 @@ static void xmm_gpio_revers_bias_restore(struct modem_ctl *mc) /* unsigned gpio_sim_detect = umts_modem_data.gpio_sim_detect; */ - if (!IS_ERR(mc->pinctrl_active)) pinctrl_select_state(mc->pinctrl, mc->pinctrl_active); @@ -152,7 +151,6 @@ static int xmm6262_reset(struct modem_ctl *mc) xmm_gpio_revers_bias_restore(mc); -/* vvv added by Kamil */ gpio_direction_input(mc->gpio_cp_dump_int); gpio_set_value(mc->gpio_pda_active, 1); @@ -161,7 +159,8 @@ static int xmm6262_reset(struct modem_ctl *mc) gpio_set_value(mc->mdm_data->link_pm_data->gpio_link_active, 1); gpio_set_value(mc->mdm_data->link_pm_data->gpio_link_slavewake, 1); -/* ^^^ added by Kamil */ + + xmm_gpio_revers_bias_restore(mc); mc->phone_state = STATE_BOOTING; @@ -291,6 +290,7 @@ int xmm6262_init_modemctl_device(struct modem_ctl *mc, goto err_phone_active_set_wake_irq; } */ + /* initialize sim_state if gpio_sim_detect exists */ mc->sim_state.online = false; mc->sim_state.changed = false; diff --git a/drivers/misc/modem_if/modem_net_flowcontrol_device.c b/drivers/misc/modem_if/modem_net_flowcontrol_device.c index 4e8b3142cbb..1b9c7a41be8 100644 --- a/drivers/misc/modem_if/modem_net_flowcontrol_device.c +++ b/drivers/misc/modem_if/modem_net_flowcontrol_device.c @@ -15,6 +15,7 @@ */ #include <linux/kernel.h> +#include <linux/module.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/types.h> @@ -22,12 +23,10 @@ #include <linux/sched.h> #include <linux/netdevice.h> #include <linux/if_arp.h> -#include <linux/platform_data/modem.h> -#include <linux/module.h> +#include "modem_tizen.h" #include "modem_prj.h" - #define NET_FLOWCONTROL_DEV_NAME_LEN 8 static int modem_net_flowcontrol_device_open( @@ -113,5 +112,5 @@ static int __init modem_net_flowcontrol_device_init(void) module_init(modem_net_flowcontrol_device_init); -//MODULE_LICENSE("GPL"); -//MODULE_DESCRIPTION("Samsung Modem IF Net Flowcontrol Driver"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Samsung Modem IF Net Flowcontrol Driver"); diff --git a/drivers/misc/modem_if/modem_prj.h b/drivers/misc/modem_if/modem_prj.h index f074655c456..abb0c4f05be 100644 --- a/drivers/misc/modem_if/modem_prj.h +++ b/drivers/misc/modem_if/modem_prj.h @@ -59,6 +59,8 @@ #define IOCTL_MODEM_CP_UPLOAD _IO('o', 0x35) #define IOCTL_MODEM_DUMP_RESET _IO('o', 0x36) +#define IOCTL_CG_DATA_SEND _IO('o', 0x37) + #define IOCTL_DPRAM_SEND_BOOT _IO('o', 0x40) #define IOCTL_DPRAM_INIT_STATUS _IO('o', 0x43) @@ -90,23 +92,88 @@ #define PSD_DATA_CHID_BEGIN 0x2A #define PSD_DATA_CHID_END 0x38 -#define PS_DATA_CH_0 10 -#define PS_DATA_CH_LAST 24 -#define RMNET0_CH_ID PS_DATA_CH_0 +#define PS_DATA_CH_0 10 +#define PS_DATA_CH_LAST 24 #define IP6VERSION 6 #define SOURCE_MAC_ADDR {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC} -/* IP loopback */ -#define CP2AP_LOOPBACK_CHANNEL 30 /* CP -> AP -> CP */ -#define DATA_LOOPBACK_CHANNEL 31 /* AP -> CP -> AP */ +/* loopback: CP -> AP -> CP */ +#define CP2AP_LOOPBACK_CHANNEL 30 + +/* ip loopback */ +#define RMNET0_CH_ID 10 +#define DATA_LOOPBACK_CHANNEL 31 + +/*send cg data*/ +#define CG_LEN 23 +#define CG_AT_CMD "AT+CGDATA=\"M-RAW_IP\"," +#define CG_AT_TAIL "\r" /* Debugging features */ -#define MIF_LOG_DIR "/sdcard/log" -#define MIF_MAX_PATH_LEN 256 -#define MIF_MAX_NAME_LEN 64 -#define MIF_MAX_STR_LEN 32 +#define MAX_MIF_LOG_PATH_LEN 128 +#define MAX_MIF_LOG_FILE_SIZE 0x800000 /* 8 MB */ + +#define MAX_MIF_EVT_BUFF_SIZE 256 +#define MAX_MIF_TIME_LEN 32 +#define MAX_MIF_NAME_LEN 16 +#define MAX_MIF_STR_LEN 127 +#define MAX_MIF_LOG_LEN 128 + +enum mif_event_id { + MIF_IRQ_EVT = 0, + MIF_LNK_RX_EVT, + MIF_MUX_RX_EVT, + MIF_IOD_RX_EVT, + MIF_IOD_TX_EVT, + MIF_MUX_TX_EVT, + MIF_LNK_TX_EVT, + MAX_MIF_EVT +}; + +struct dpram_queue_status { + unsigned in; + unsigned out; +}; + +struct dpram_queue_status_pair { + struct dpram_queue_status txq; + struct dpram_queue_status rxq; +}; + +struct dpram_irq_buff { + unsigned magic; + unsigned access; + struct dpram_queue_status_pair qsp[MAX_IPC_DEV]; + unsigned int2ap; + unsigned int2cp; +}; + +/* Not use */ +struct mif_event_buff { + char time[MAX_MIF_TIME_LEN]; + + struct timeval tv; + enum mif_event_id evt; + + char mc[MAX_MIF_NAME_LEN]; + + char iod[MAX_MIF_NAME_LEN]; + + char ld[MAX_MIF_NAME_LEN]; + enum modem_link link_type; + + unsigned rcvd; + unsigned len; + union { + u8 data[MAX_MIF_LOG_LEN]; + struct dpram_irq_buff dpram_irqb; + }; +}; + +#define MIF_LOG_DIR "/sdcard" +#define MIF_LOG_LV_FILE "/data/.mif_log_level" /* Does modem ctl structure will use state ? or status defined below ?*/ enum modem_state { @@ -380,9 +447,6 @@ struct link_device { enum modem_link link_type; unsigned aligned; - /* Maximum IPC device = the last IPC device (e.g. IPC_RFS) + 1 */ - int max_ipc_dev; - /* SIPC version */ enum sipc_ver ipc_version; @@ -413,11 +477,7 @@ struct link_device { struct workqueue_struct *tx_wq; struct work_struct tx_work; struct delayed_work tx_delayed_work; - - struct delayed_work *tx_dwork[MAX_IPC_DEV]; - struct delayed_work fmt_tx_dwork; - struct delayed_work raw_tx_dwork; - struct delayed_work rfs_tx_dwork; + struct delayed_work tx_dwork; struct workqueue_struct *rx_wq; struct work_struct rx_work; @@ -466,7 +526,7 @@ static inline struct sk_buff *rx_alloc_skb(unsigned int length, { struct sk_buff *skb; - if (iod->format == IPC_MULTI_RAW || iod->format == IPC_RAW) + if (iod->format == IPC_PDP0 || iod->format == IPC_PDP1) skb = dev_alloc_skb(length); else skb = alloc_skb(length, GFP_ATOMIC); @@ -560,11 +620,7 @@ struct modem_ctl { struct delayed_work dwork; #endif /*CONFIG_LTE_MODEM_CMC221*/ -#if defined(CONFIG_MACH_GRANDE) - struct delayed_work sim_det_dwork; -#ifdef CONFIG_HAS_WAKELOCK -#endif -#endif /* For checking sim detect pin */ + struct work_struct work; #if defined(CONFIG_MACH_U1_KOR_LGT) @@ -579,8 +635,8 @@ struct modem_ctl { struct io_device *iod; struct io_device *bootd; - /* Wakelock for modem_ctl */ #ifdef CONFIG_HAS_WAKELOCK + /* Wakelock for modem_ctl */ struct wake_lock mc_wake_lock; #endif @@ -593,30 +649,8 @@ struct modem_ctl { int sipc4_init_io_device(struct io_device *iod); int sipc5_init_io_device(struct io_device *iod); - -/** - * get_dev_name - * @dev: IPC device (enum dev_format) - * - * Returns IPC device name as a string. - * - */ -static const inline char *get_dev_name(int dev) -{ - if (dev == IPC_FMT) - return "FMT"; - else if (dev == IPC_RAW) - return "RAW"; - else if (dev == IPC_RFS) - return "RFS"; - else if (dev == IPC_BOOT) - return "BOOT"; - else if (dev == IPC_RAMDUMP) - return "DUMP"; - else - return "NONE"; -} - +int send_cg_data(struct link_device *ld, + struct io_device *iod, unsigned long arg); /** * sipc5_start_valid * @cfg: configuration field of an SIPC5 link frame @@ -698,40 +732,6 @@ static inline unsigned sipc5_calc_padding_size(unsigned len) return residue ? (4 - residue) : 0; } -/** - * sipc5_check_frame_in_dev - * @ld: pointer to the link device structure - * @dev: IPC device (enum dev_format) - * @frm: pointer to the start of an SIPC5 frame - * @rest: size of the rest data in the device buffer including this frame - * - * Returns - * < 0 : error - * == 0 : no data - * > 0 : valid data - * - */ -static inline int sipc5_check_frame_in_dev(struct link_device *ld, int dev, - u8 *frm, int rest) -{ - unsigned int len; - - if (unlikely(!sipc5_start_valid(frm[0]))) { - mif_err("%s: ERR! %s invalid start 0x%02X\n", - ld->name, get_dev_name(dev), frm[0]); - return -EBADMSG; - } - - len = sipc5_get_frame_sz16(frm); - if (unlikely(len > rest)) { - mif_err("%s: ERR! %s len %d > rest %d\n", - ld->name, get_dev_name(dev), len, rest); - return -EBADMSG; - } - - return len; -} - extern void set_sromc_access(bool access); #endif diff --git a/drivers/misc/modem_if/modem_sim_slot_switch.c b/drivers/misc/modem_if/modem_sim_slot_switch.c deleted file mode 100644 index 1dd4c6764ce..00000000000 --- a/drivers/misc/modem_if/modem_sim_slot_switch.c +++ /dev/null @@ -1,92 +0,0 @@ -#include <linux/i2c.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/err.h> - -#include <plat/gpio-cfg.h> - -#include <mach/gpio.h> - -extern struct class *sec_class; -struct device *slot_switch_dev; - -static ssize_t get_slot_switch(struct device *dev, struct device_attribute *attr, char *buf) -{ - int value; - - //return '0' slot path is '||', return '1' slot path is 'X' - value = gpio_get_value(GPIO_UIM_SIM_SEL); - printk("Current Slot is %x\n", value); - - return sprintf(buf, "%d\n", value); -} - -static ssize_t set_slot_switch(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) -{ - int value; - - sscanf(buf, "%d", &value); - - switch(value) { - case 0: - gpio_set_value(GPIO_UIM_SIM_SEL, 0); - printk("set slot switch to %x\n", gpio_get_value(GPIO_UIM_SIM_SEL)); - break; - case 1: - gpio_set_value(GPIO_UIM_SIM_SEL, 1); - printk("set slot switch to %x\n", gpio_get_value(GPIO_UIM_SIM_SEL)); - break; - default: - printk("Enter 0 or 1!!\n"); - } - - return size; -} - -static DEVICE_ATTR(slot_sel, S_IRUGO |S_IWUGO | S_IRUSR | S_IWUSR, get_slot_switch, set_slot_switch); - -static int __init slot_switch_manager_init(void) -{ - int ret = 0; - int err = 0; - - printk("slot_switch_manager_init\n"); - - //initailize uim_sim_switch gpio - err = gpio_request(GPIO_UIM_SIM_SEL, "PDA_ACTIVE"); - if (err) { - pr_err("fail to request gpio %s, gpio %d, errno %d\n", - "PDA_ACTIVE", GPIO_UIM_SIM_SEL, err); - } else { - gpio_direction_output(GPIO_UIM_SIM_SEL, 1); - s3c_gpio_setpull(GPIO_UIM_SIM_SEL, S3C_GPIO_PULL_NONE); -#if defined(CONFIG_MACH_T0_CHN_CTC) - gpio_set_value(GPIO_UIM_SIM_SEL, 1); -#else - gpio_set_value(GPIO_UIM_SIM_SEL, 0); -#endif - } - - //initailize slot switch device - slot_switch_dev = device_create(sec_class, - NULL, 0, NULL, "slot_switch"); - if (IS_ERR(slot_switch_dev)) - pr_err("Failed to create device(switch)!\n"); - - if (device_create_file(slot_switch_dev, &dev_attr_slot_sel) < 0) - pr_err("Failed to create device file(%s)!\n", - dev_attr_slot_sel.attr.name); - - return ret; -} - -static void __exit slot_switch_manager_exit(void) -{ -} - -module_init(slot_switch_manager_init); -module_exit(slot_switch_manager_exit); - -MODULE_AUTHOR("SAMSUNG ELECTRONICS CO., LTD"); -MODULE_DESCRIPTION("Slot Switch"); -MODULE_LICENSE("GPL"); diff --git a/drivers/misc/modem_if/modem_tizen.h b/drivers/misc/modem_if/modem_tizen.h new file mode 100644 index 00000000000..cb3ea08e067 --- /dev/null +++ b/drivers/misc/modem_if/modem_tizen.h @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2010 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. + * + */ + +#ifndef __MODEM_IF_H__ +#define __MODEM_IF_H__ + +enum modem_t { + IMC_XMM6260, + IMC_XMM6262, + VIA_CBP71, + VIA_CBP72, + SEC_CMC221, + QC_MDM6600, + QC_ESC6270, + DUMMY, + MAX_MODEM_TYPE +}; + +enum dev_format { + IPC_BYPASS, + IPC_PDP0, + IPC_PDP1, + IPC_RFS, + IPC_BOOT, + IPC_RAMDUMP, + MAX_DEV_FORMAT, +}; +#define MAX_IPC_DEV (IPC_RFS + 1) /* BYPASS, PDP0, PDP1, PDP2 */ +#define MAX_SIPC5_DEV (IPC_PDP0 + 1) /* FMT, RAW */ + +enum modem_io { + IODEV_MISC, + IODEV_NET, + IODEV_DUMMY, +}; + +enum modem_link { + LINKDEV_UNDEFINED, + LINKDEV_MIPI, + LINKDEV_DPRAM, + LINKDEV_SPI, + LINKDEV_USB, + LINKDEV_HSIC, + LINKDEV_C2C, + LINKDEV_MAX, +}; +#define LINKTYPE(modem_link) (1u << (modem_link)) + +enum modem_network { + UMTS_NETWORK, + CDMA_NETWORK, + LTE_NETWORK, +}; + +enum sipc_ver { + NO_SIPC_VER = 0, + SIPC_VER_40 = 40, + SIPC_VER_41 = 41, + SIPC_VER_42 = 42, + SIPC_VER_50 = 50, + MAX_SIPC_VER, +}; + +/** + * struct modem_io_t - declaration for io_device + * @name: device name + * @id: contain format & channel information + * (id & 11100000b)>>5 = format (eg, 0=FMT, 1=RAW, 2=RFS) + * (id & 00011111b) = channel (valid only if format is RAW) + * @format: device format + * @io_type: type of this io_device + * @links: list of link_devices to use this io_device + * for example, if you want to use DPRAM and USB in an io_device. + * .links = LINKTYPE(LINKDEV_DPRAM) | LINKTYPE(LINKDEV_USB) + * @tx_link: when you use 2+ link_devices, set the link for TX. + * If define multiple link_devices in @links, + * you can receive data from them. But, cannot send data to all. + * TX is only one link_device. + * + * This structure is used in board-*-modem.c + */ +struct modem_io_t { + char *name; + int id; + enum dev_format format; + enum modem_io io_type; + enum modem_link links; + enum modem_link tx_link; + bool rx_gather; +}; + +struct modemlink_pm_data { + char *name; + /* link power contol 2 types : pin & regulator control */ + int (*link_ldo_enable)(bool); + unsigned gpio_link_enable; + unsigned gpio_link_active; + unsigned gpio_link_hostwake; + unsigned gpio_link_slavewake; + int (*link_reconnect)(void); + + /* usb hub only */ + int (*port_enable)(int, int); + int (*hub_standby)(void *); + void *hub_pm_data; + bool has_usbhub; + + /* cpu/bus frequency lock */ + atomic_t freqlock; + int (*freq_lock)(struct device *dev); + int (*freq_unlock)(struct device *dev); + + int autosuspend_delay_ms; /* if zero, the default value is used */ +}; + +struct modemlink_pm_link_activectl { + int gpio_initialized; + int gpio_request_host_active; +}; + +enum dpram_type { + EXT_DPRAM, + AP_IDPRAM, + CP_IDPRAM, + SHM_DPRAM, + MAX_DPRAM_TYPE +}; + +#define DPRAM_SIZE_8KB 0x02000 +#define DPRAM_SIZE_16KB 0x04000 +#define DPRAM_SIZE_32KB 0x08000 +#define DPRAM_SIZE_64KB 0x10000 +#define DPRAM_SIZE_128KB 0x20000 + +enum dpram_speed { + DPRAM_SPEED_LOW, + DPRAM_SPEED_MID, + DPRAM_SPEED_HIGH, + MAX_DPRAM_SPEED +}; + +struct dpram_circ { + u16 __iomem *head; + u16 __iomem *tail; + u8 __iomem *buff; + u32 size; +}; + +struct dpram_ipc_device { + char name[16]; + int id; + + struct dpram_circ txq; + struct dpram_circ rxq; + + u16 mask_req_ack; + u16 mask_res_ack; + u16 mask_send; +}; + +struct dpram_ipc_map { + u16 __iomem *magic; + u16 __iomem *access; + + struct dpram_ipc_device dev[MAX_IPC_DEV]; + + u16 __iomem *mbx_cp2ap; + u16 __iomem *mbx_ap2cp; +}; + +struct modemlink_dpram_control { + void (*reset)(void); + void (*clear_intr)(void); + u16 (*recv_intr)(void); + void (*send_intr)(u16); + u16 (*recv_msg)(void); + void (*send_msg)(u16); + + int (*wakeup)(void); + void (*sleep)(void); + + void (*setup_speed)(enum dpram_speed); + + enum dpram_type dp_type; /* DPRAM type */ + int aligned; /* aligned access is required */ + u8 __iomem *dp_base; + u32 dp_size; + + int dpram_irq; + unsigned long dpram_irq_flags; + + int max_ipc_dev; + struct dpram_ipc_map *ipc_map; + + unsigned boot_size_offset; + unsigned boot_tag_offset; + unsigned boot_count_offset; + unsigned max_boot_frame_size; +}; + +/* platform data */ +struct modem_data { + char *name; + + unsigned gpio_cp_on; + unsigned gpio_cp_off; + unsigned gpio_reset_req_n; + unsigned gpio_cp_reset; + unsigned gpio_pda_active; + unsigned gpio_phone_active; + unsigned gpio_cp_dump_int; + unsigned gpio_ap_dump_int; + unsigned gpio_flm_uart_sel; +#if defined(CONFIG_MACH_M0_CTC) + unsigned gpio_flm_uart_sel_rev06; + unsigned gpio_host_wakeup; +#endif + unsigned gpio_cp_warm_reset; + unsigned gpio_sim_detect; +#ifdef CONFIG_LINK_DEVICE_DPRAM + unsigned gpio_dpram_int; +#endif + +#ifdef CONFIG_LTE_MODEM_CMC221 + unsigned gpio_dpram_status; + unsigned gpio_dpram_wakeup; + unsigned gpio_slave_wakeup; + unsigned gpio_host_active; + unsigned gpio_host_wakeup; + int irq_host_wakeup; +#endif +#ifdef CONFIG_MACH_U1_KOR_LGT + unsigned gpio_cp_reset_msm; + unsigned gpio_boot_sw_sel; + void (*vbus_on)(void); + void (*vbus_off)(void); + struct regulator *cp_vbus; +#endif + + /* Switch with 2 links in a modem */ + unsigned gpio_dynamic_switching; + + /* Modem component */ + enum modem_network modem_net; + enum modem_t modem_type; + enum modem_link link_types; + char *link_name; +#ifdef CONFIG_LINK_DEVICE_DPRAM + /* Link to DPRAM control functions dependent on each platform */ + struct modemlink_dpram_control *dpram_ctl; +#endif + + /* SIPC version */ + enum sipc_ver ipc_version; + + /* Information of IO devices */ + unsigned num_iodevs; + struct modem_io_t *iodevs; + + /* Modem link PM support */ + struct modemlink_pm_data *link_pm_data; + + void (*gpio_revers_bias_clear)(void); + void (*gpio_revers_bias_restore)(void); + + /* Handover with 2+ modems */ + bool use_handover; + + /* Debugging option */ + bool use_mif_log; + bool sim_polarity; +}; + +#define LOG_TAG "mif: " + +#define mif_err(fmt, ...) \ + pr_err(LOG_TAG "%s: " pr_fmt(fmt), __func__, ##__VA_ARGS__) +#define mif_debug(fmt, ...) \ + pr_debug(LOG_TAG "%s: " pr_fmt(fmt), __func__, ##__VA_ARGS__) +#define mif_info(fmt, ...) \ + pr_info(LOG_TAG "%s: " pr_fmt(fmt), __func__, ##__VA_ARGS__) +#define mif_trace(fmt, ...) \ + printk(KERN_DEBUG "mif: %s: %d: called(%pF): " fmt, \ + __func__, __LINE__, __builtin_return_address(0), ##__VA_ARGS__) + +#endif diff --git a/drivers/misc/modem_if/modem_utils.c b/drivers/misc/modem_if/modem_utils.c index 229e93f49ab..6adec3529a3 100644 --- a/drivers/misc/modem_if/modem_utils.c +++ b/drivers/misc/modem_if/modem_utils.c @@ -12,38 +12,18 @@ * */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/miscdevice.h> #include <linux/netdevice.h> +#include <linux/platform_device.h> #include <linux/skbuff.h> #include <linux/ip.h> -#include <net/ip.h> #include <linux/tcp.h> #include <linux/udp.h> #include <linux/rtc.h> #include <linux/time.h> +#include <net/ip.h> -#include <linux/uaccess.h> -#include <linux/fs.h> -#include <linux/io.h> -#include <linux/wait.h> -#include <linux/time.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#ifdef CONFIG_HAS_WAKELOCK -#include <linux/wakelock.h> -#endif - -#include <linux/platform_data/modem.h> +#include "modem_tizen.h" #include "modem_prj.h" -#include "modem_variation.h" #include "modem_utils.h" #define CMD_SUSPEND ((unsigned short)(0x00CA)) @@ -55,43 +35,20 @@ "mif: ------------------------------------------------------------" #define LINE_BUFF_SIZE 80 -static const char *hex = "0123456789abcdef"; - -void ts2utc(struct timespec *ts, struct utc_time *utc) -{ - struct tm tm; - - time_to_tm((ts->tv_sec - (sys_tz.tz_minuteswest * 60)), 0, &tm); - utc->year = 1900 + tm.tm_year; - utc->mon = 1 + tm.tm_mon; - utc->day = tm.tm_mday; - utc->hour = tm.tm_hour; - utc->min = tm.tm_min; - utc->sec = tm.tm_sec; - utc->msec = (ts->tv_nsec > 0) ? (ts->tv_nsec / 1000000) : 0; -} - -void get_utc_time(struct utc_time *utc) -{ - struct timespec ts; - getnstimeofday(&ts); - ts2utc(&ts, utc); -} - #ifdef CONFIG_LINK_DEVICE_DPRAM #include "modem_link_device_dpram.h" int mif_dump_dpram(struct io_device *iod) { struct link_device *ld = get_current_link(iod); struct dpram_link_device *dpld = to_dpram_link_device(ld); - u32 size = dpld->size; + u32 size = dpld->dp_size; unsigned long read_len = 0; struct sk_buff *skb; char *buff; buff = kzalloc(size, GFP_ATOMIC); if (!buff) { - mif_err("ERR! kzalloc fail\n"); + pr_err("[MIF] <%s> alloc dpram buff failed\n", __func__); return -ENOMEM; } else { dpld->dpram_dump(ld, buff); @@ -100,7 +57,7 @@ int mif_dump_dpram(struct io_device *iod) while (read_len < size) { skb = alloc_skb(MAX_IPC_SKB_SIZE, GFP_ATOMIC); if (!skb) { - mif_err("ERR! alloc_skb fail\n"); + pr_err("[MIF] <%s> alloc skb failed\n", __func__); kfree(buff); return -ENOMEM; } @@ -125,7 +82,7 @@ int mif_dump_log(struct modem_shared *msd, struct io_device *iod) while (read_len < MAX_MIF_BUFF_SIZE) { skb = alloc_skb(MAX_IPC_SKB_SIZE, GFP_ATOMIC); if (!skb) { - mif_err("ERR! alloc_skb fail\n"); + pr_err("[MIF] <%s> alloc skb failed\n", __func__); spin_unlock_irqrestore(&msd->lock, flags); return -ENOMEM; } @@ -252,12 +209,13 @@ void _mif_time_log(enum mif_log_id id, struct modem_shared *msd, /* dump2hex * dump data to hex as fast as possible. - * the length of @buff must be greater than "@len * 3" + * the length of @buf must be greater than "@len * 3" * it need 3 bytes per one data byte to print. */ -static inline int dump2hex(char *buff, const char *data, size_t len) +static inline int dump2hex(char *buf, const char *data, size_t len) { - char *dest = buff; + static const char *hex = "0123456789abcdef"; + char *dest = buf; int i; for (i = 0; i < len; i++) { @@ -270,18 +228,24 @@ static inline int dump2hex(char *buff, const char *data, size_t len) *dest = '\0'; - return dest - buff; + return dest - buf; } -void pr_ipc(const char *tag, const char *data, size_t len) +int pr_ipc(const char *str, const char *data, size_t len) { - struct utc_time utc; - unsigned char str[128]; + struct timeval tv; + struct tm date; + unsigned char hexstr[128]; + + do_gettimeofday(&tv); + time_to_tm((tv.tv_sec - sys_tz.tz_minuteswest * 60), 0, &date); + + dump2hex(hexstr, data, (len > 40 ? 40 : len)); - get_utc_time(&utc); - dump2hex(str, data, (len > 32 ? 32 : len)); - pr_info("%s: %s: [%02d:%02d:%02d.%03d] %s\n", - MIF_TAG, tag, utc.hour, utc.min, utc.sec, utc.msec, str); + return pr_info("mif: %s: [%02d-%02d %02d:%02d:%02d.%03ld] %s\n", + str, date.tm_mon + 1, date.tm_mday, + date.tm_hour, date.tm_min, date.tm_sec, + (tv.tv_usec > 0 ? tv.tv_usec / 1000 : 0), hexstr); } /* print buffer as hex string */ @@ -289,12 +253,12 @@ int pr_buffer(const char *tag, const char *data, size_t data_len, size_t max_len) { size_t len = min(data_len, max_len); - unsigned char str[len ? len * 3 : 1]; /* 1 <= sizeof <= max_len*3 */ - dump2hex(str, data, len); + unsigned char hexstr[len ? len * 3 : 1]; /* 1 <= sizeof <= max_len*3 */ + dump2hex(hexstr, data, len); /* don't change this printk to mif_debug for print this as level7 */ - return printk(KERN_INFO "%s: %s(%u): %s%s\n", MIF_TAG, tag, data_len, - str, (len == data_len) ? "" : " ..."); + return printk(KERN_INFO "mif: %s(%u): %s%s\n", tag, data_len, hexstr, + len == data_len ? "" : " ..."); } /* flow control CM from CP, it use in serial devices */ @@ -434,7 +398,8 @@ void iodev_netif_stop(struct io_device *iod, void *args) static void iodev_set_tx_link(struct io_device *iod, void *args) { struct link_device *ld = (struct link_device *)args; - if (iod->format == IPC_RAW && IS_CONNECTED(iod, ld)) { + if ((iod->format == IPC_PDP0 || iod->format == IPC_PDP1) + && IS_CONNECTED(iod, ld)) { set_current_link(iod, ld); mif_err("%s -> %s\n", iod->name, ld->name); } @@ -447,32 +412,6 @@ void rawdevs_set_tx_link(struct modem_shared *msd, enum modem_link link_type) iodevs_for_each(msd, iodev_set_tx_link, ld); } -void mif_netif_stop(struct link_device *ld) -{ - struct io_device *iod; - - if (ld->ipc_version < SIPC_VER_50) - iod = link_get_iod_with_channel(ld, 0x20 | RMNET0_CH_ID); - else - iod = link_get_iod_with_channel(ld, RMNET0_CH_ID); - - if (iod) - iodevs_for_each(iod->msd, iodev_netif_stop, 0); -} - -void mif_netif_wake(struct link_device *ld) -{ - struct io_device *iod; - - if (ld->ipc_version < SIPC_VER_50) - iod = link_get_iod_with_channel(ld, 0x20 | RMNET0_CH_ID); - else - iod = link_get_iod_with_channel(ld, RMNET0_CH_ID); - - if (iod) - iodevs_for_each(iod->msd, iodev_netif_wake, 0); -} - /** * ipv4str_to_be32 - ipv4 string to be32 (big endian 32bits integer) * @return: return zero when errors occurred @@ -509,7 +448,7 @@ void mif_add_timer(struct timer_list *timer, unsigned long expire, add_timer(timer); } -void mif_print_data(const char *buff, int len) +void mif_print_data(char *buf, int len) { int words = len >> 4; int residue = len - (words << 4); @@ -522,7 +461,7 @@ void mif_print_data(const char *buff, int len) if (residue > 0) { memset(last, 0, sizeof(last)); memset(tb, 0, sizeof(tb)); - b = (char *)buff + (words << 4); + b = buf + (words << 4); sprintf(last, "%04X: ", (words << 4)); for (i = 0; i < residue; i++) { @@ -536,7 +475,7 @@ void mif_print_data(const char *buff, int len) } for (i = 0; i < words; i++) { - b = (char *)buff + (i << 4); + b = buf + (i << 4); mif_err("%04X: " "%02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n", @@ -550,134 +489,6 @@ void mif_print_data(const char *buff, int len) mif_err("%s\n", last); } -void mif_dump2format16(const char *data, int len, char *buff, char *tag) -{ - char *d; - int i; - int words = len >> 4; - int residue = len - (words << 4); - char line[LINE_BUFF_SIZE]; - char tb[8]; - - for (i = 0; i < words; i++) { - memset(line, 0, LINE_BUFF_SIZE); - d = (char *)data + (i << 4); - - if (tag) - sprintf(line, "%s%04X| " - "%02x %02x %02x %02x " - "%02x %02x %02x %02x " - "%02x %02x %02x %02x " - "%02x %02x %02x %02x\n", - tag, (i << 4), - d[0], d[1], d[2], d[3], - d[4], d[5], d[6], d[7], - d[8], d[9], d[10], d[11], - d[12], d[13], d[14], d[15]); - else - sprintf(line, "%04X| " - "%02x %02x %02x %02x " - "%02x %02x %02x %02x " - "%02x %02x %02x %02x " - "%02x %02x %02x %02x\n", - (i << 4), - d[0], d[1], d[2], d[3], - d[4], d[5], d[6], d[7], - d[8], d[9], d[10], d[11], - d[12], d[13], d[14], d[15]); - - strcat(buff, line); - } - - /* Make the last line, if (len % 16) > 0 */ - if (residue > 0) { - memset(line, 0, LINE_BUFF_SIZE); - memset(tb, 0, sizeof(tb)); - d = (char *)data + (words << 4); - - if (tag) - sprintf(line, "%s%04X|", tag, (words << 4)); - else - sprintf(line, "%04X|", (words << 4)); - - for (i = 0; i < residue; i++) { - sprintf(tb, " %02x", d[i]); - strcat(line, tb); - if ((i & 0x3) == 0x3) { - sprintf(tb, " "); - strcat(line, tb); - } - } - strcat(line, "\n"); - - strcat(buff, line); - } -} - -void mif_dump2format4(const char *data, int len, char *buff, char *tag) -{ - char *d; - int i; - int words = len >> 2; - int residue = len - (words << 2); - char line[LINE_BUFF_SIZE]; - char tb[8]; - - for (i = 0; i < words; i++) { - memset(line, 0, LINE_BUFF_SIZE); - d = (char *)data + (i << 2); - - if (tag) - sprintf(line, "%s%04X| %02x %02x %02x %02x\n", - tag, (i << 2), d[0], d[1], d[2], d[3]); - else - sprintf(line, "%04X| %02x %02x %02x %02x\n", - (i << 2), d[0], d[1], d[2], d[3]); - - strcat(buff, line); - } - - /* Make the last line, if (len % 4) > 0 */ - if (residue > 0) { - memset(line, 0, LINE_BUFF_SIZE); - memset(tb, 0, sizeof(tb)); - d = (char *)data + (words << 2); - - if (tag) - sprintf(line, "%s%04X|", tag, (words << 2)); - else - sprintf(line, "%04X|", (words << 2)); - - for (i = 0; i < residue; i++) { - sprintf(tb, " %02x", d[i]); - strcat(line, tb); - } - strcat(line, "\n"); - - strcat(buff, line); - } -} - -void mif_print_dump(const char *data, int len, int width) -{ - char *buff; - - buff = kzalloc(len << 3, GFP_ATOMIC); - if (!buff) { - mif_err("ERR! kzalloc fail\n"); - return; - } - - if (width == 16) - mif_dump2format16(data, len, buff, LOG_TAG); - else - mif_dump2format4(data, len, buff, LOG_TAG); - - pr_info("%s", buff); - - kfree(buff); -} - void print_sipc4_hdlc_fmt_frame(const u8 *psrc) { u8 *frm; /* HDLC Frame */ @@ -822,14 +633,14 @@ static void strcat_tcp_header(char *buff, u8 *pkt) memset(line, 0, LINE_BUFF_SIZE); snprintf(line, LINE_BUFF_SIZE, - "%s: TCP:: Src.Port %u, Dst.Port %u\n", - MIF_TAG, ntohs(tcph->source), ntohs(tcph->dest)); + "mif: TCP:: Src.Port %u, Dst.Port %u\n", + ntohs(tcph->source), ntohs(tcph->dest)); strcat(buff, line); memset(line, 0, LINE_BUFF_SIZE); snprintf(line, LINE_BUFF_SIZE, - "%s: TCP:: SEQ 0x%08X(%u), ACK 0x%08X(%u)\n", - MIF_TAG, ntohs(tcph->seq), ntohs(tcph->seq), + "mif: TCP:: SEQ 0x%08X(%u), ACK 0x%08X(%u)\n", + ntohs(tcph->seq), ntohs(tcph->seq), ntohs(tcph->ack_seq), ntohs(tcph->ack_seq)); strcat(buff, line); @@ -854,13 +665,12 @@ static void strcat_tcp_header(char *buff, u8 *pkt) eol = strlen(flag_str) - 1; if (eol > 0) flag_str[eol] = 0; - snprintf(line, LINE_BUFF_SIZE, "%s: TCP:: Flags {%s}\n", - MIF_TAG, flag_str); + snprintf(line, LINE_BUFF_SIZE, "mif: TCP:: Flags {%s}\n", flag_str); strcat(buff, line); memset(line, 0, LINE_BUFF_SIZE); snprintf(line, LINE_BUFF_SIZE, - "%s: TCP:: Window %u, Checksum 0x%04X, Urgent %u\n", MIF_TAG, + "mif: TCP:: Window %u, Checksum 0x%04X, Urg Pointer %u\n", ntohs(tcph->window), ntohs(tcph->check), ntohs(tcph->urg_ptr)); strcat(buff, line); } @@ -886,36 +696,34 @@ static void strcat_udp_header(char *buff, u8 *pkt) memset(line, 0, LINE_BUFF_SIZE); snprintf(line, LINE_BUFF_SIZE, - "%s: UDP:: Src.Port %u, Dst.Port %u\n", - MIF_TAG, ntohs(udph->source), ntohs(udph->dest)); + "mif: UDP:: Src.Port %u, Dst.Port %u\n", + ntohs(udph->source), ntohs(udph->dest)); strcat(buff, line); memset(line, 0, LINE_BUFF_SIZE); snprintf(line, LINE_BUFF_SIZE, - "%s: UDP:: Length %u, Checksum 0x%04X\n", - MIF_TAG, ntohs(udph->len), ntohs(udph->check)); + "mif: UDP:: Length %u, Checksum 0x%04X\n", + ntohs(udph->len), ntohs(udph->check)); strcat(buff, line); if (ntohs(udph->dest) == 53) { memset(line, 0, LINE_BUFF_SIZE); - snprintf(line, LINE_BUFF_SIZE, "%s: UDP:: DNS query!!!\n", - MIF_TAG); + snprintf(line, LINE_BUFF_SIZE, "mif: UDP:: DNS query!!!\n"); strcat(buff, line); } if (ntohs(udph->source) == 53) { memset(line, 0, LINE_BUFF_SIZE); - snprintf(line, LINE_BUFF_SIZE, "%s: UDP:: DNS response!!!\n", - MIF_TAG); + snprintf(line, LINE_BUFF_SIZE, "mif: UDP:: DNS response!!!\n"); strcat(buff, line); } } -void print_ip4_packet(const u8 *ip_pkt, bool tx) +void print_ip4_packet(u8 *ip_pkt, bool tx) { char *buff; struct iphdr *iph = (struct iphdr *)ip_pkt; - u8 *pkt = (u8 *)ip_pkt + (iph->ihl << 2); + u8 *pkt = ip_pkt + (iph->ihl << 2); u16 flags = (ntohs(iph->frag_off) & 0xE000); u16 frag_off = (ntohs(iph->frag_off) & 0x1FFF); int eol; @@ -971,14 +779,14 @@ void print_ip4_packet(const u8 *ip_pkt, bool tx) memset(line, 0, LINE_BUFF_SIZE); snprintf(line, LINE_BUFF_SIZE, - "%s: IP4:: Version %u, Header Length %u, TOS %u, Length %u\n", - MIF_TAG, iph->version, (iph->ihl << 2), iph->tos, - ntohs(iph->tot_len)); + "mif: IP4:: Version %u, Header Length %u, TOS %u, Length %u\n", + iph->version, (iph->ihl << 2), iph->tos, ntohs(iph->tot_len)); strcat(buff, line); memset(line, 0, LINE_BUFF_SIZE); - snprintf(line, LINE_BUFF_SIZE, "%s: IP4:: ID %u, Fragment Offset %u\n", - MIF_TAG, ntohs(iph->id), frag_off); + snprintf(line, LINE_BUFF_SIZE, + "mif: IP4:: ID %u, Fragment Offset %u\n", + ntohs(iph->id), frag_off); strcat(buff, line); memset(line, 0, LINE_BUFF_SIZE); @@ -992,20 +800,19 @@ void print_ip4_packet(const u8 *ip_pkt, bool tx) eol = strlen(flag_str) - 1; if (eol > 0) flag_str[eol] = 0; - snprintf(line, LINE_BUFF_SIZE, "%s: IP4:: Flags {%s}\n", - MIF_TAG, flag_str); + snprintf(line, LINE_BUFF_SIZE, "mif: IP4:: Flags {%s}\n", flag_str); strcat(buff, line); memset(line, 0, LINE_BUFF_SIZE); snprintf(line, LINE_BUFF_SIZE, - "%s: IP4:: TTL %u, Protocol %u, Header Checksum 0x%04X\n", - MIF_TAG, iph->ttl, iph->protocol, ntohs(iph->check)); + "mif: IP4:: TTL %u, Protocol %u, Header Checksum 0x%04X\n", + iph->ttl, iph->protocol, ntohs(iph->check)); strcat(buff, line); memset(line, 0, LINE_BUFF_SIZE); snprintf(line, LINE_BUFF_SIZE, - "%s: IP4:: Src.IP %u.%u.%u.%u, Dst.IP %u.%u.%u.%u\n", - MIF_TAG, ip_pkt[12], ip_pkt[13], ip_pkt[14], ip_pkt[15], + "mif: IP4:: Src.IP %u.%u.%u.%u, Dst.IP %u.%u.%u.%u\n", + ip_pkt[12], ip_pkt[13], ip_pkt[14], ip_pkt[15], ip_pkt[16], ip_pkt[17], ip_pkt[18], ip_pkt[19]); strcat(buff, line); @@ -1031,7 +838,7 @@ void print_ip4_packet(const u8 *ip_pkt, bool tx) kfree(buff); } -bool is_dns_packet(const u8 *ip_pkt) +bool is_dns_packet(u8 *ip_pkt) { struct iphdr *iph = (struct iphdr *)ip_pkt; struct udphdr *udph = (struct udphdr *)(ip_pkt + (iph->ihl << 2)); @@ -1046,7 +853,7 @@ bool is_dns_packet(const u8 *ip_pkt) return false; } -bool is_syn_packet(const u8 *ip_pkt) +bool is_syn_packet(u8 *ip_pkt) { struct iphdr *iph = (struct iphdr *)ip_pkt; struct tcphdr *tcph = (struct tcphdr *)(ip_pkt + (iph->ihl << 2)); @@ -1182,48 +989,3 @@ int mif_test_dpram(char *dp_name, u8 __iomem *start, u32 size) return 0; } -struct file *mif_open_file(const char *path) -{ - struct file *fp; - mm_segment_t old_fs; - - old_fs = get_fs(); - set_fs(get_ds()); - - fp = filp_open(path, O_RDWR|O_CREAT|O_APPEND, 0666); - - set_fs(old_fs); - - if (IS_ERR(fp)) - return NULL; - - return fp; -} - -void mif_save_file(struct file *fp, const char *buff, size_t size) -{ - int ret; - mm_segment_t old_fs; - - old_fs = get_fs(); - set_fs(get_ds()); - - ret = fp->f_op->write(fp, buff, size, &fp->f_pos); - if (ret < 0) - mif_err("ERR! write fail\n"); - - set_fs(old_fs); -} - -void mif_close_file(struct file *fp) -{ - mm_segment_t old_fs; - - old_fs = get_fs(); - set_fs(get_ds()); - - filp_close(fp, NULL); - - set_fs(old_fs); -} - diff --git a/drivers/misc/modem_if/modem_utils.h b/drivers/misc/modem_if/modem_utils.h index 219e0597ec2..1df5fd07dec 100644 --- a/drivers/misc/modem_if/modem_utils.h +++ b/drivers/misc/modem_if/modem_utils.h @@ -26,8 +26,6 @@ #define MAX_IPC_SKB_SIZE 4096 #define MAX_LOG_SIZE 64 -#define MIF_TAG "mif" - #define MAX_LOG_CNT (MAX_MIF_BUFF_SIZE / MAX_LOG_SIZE) #define MIF_ID_SIZE sizeof(enum mif_log_id) @@ -98,19 +96,6 @@ struct mif_time_block { char buff[MAX_TIM_LOG_SIZE]; }; -struct utc_time { - u16 year; - u8 mon:4, - day:4; - u8 hour; - u8 min; - u8 sec; - u16 msec; -} __packed; - -void ts2utc(struct timespec *ts, struct utc_time *utc); -void get_utc_time(struct utc_time *utc); - int mif_dump_dpram(struct io_device *); int mif_dump_log(struct modem_shared *, struct io_device *); @@ -156,7 +141,7 @@ static inline unsigned int countbits(unsigned int n) } /* print IPC message as hex string with UTC time */ -void pr_ipc(const char *tag, const char *data, size_t len); +int pr_ipc(const char *str, const char *data, size_t len); /* print buffer as hex string */ int pr_buffer(const char *tag, const char *data, size_t data_len, @@ -171,13 +156,10 @@ int pr_buffer(const char *tag, const char *data, size_t data_len, pr_buffer(tag, (char *)((urb)->transfer_buffer), \ (size_t)((urb)->actual_length), (size_t)16) -/* Stop/wake all TX queues in network interfaces */ -void mif_netif_stop(struct link_device *ld); -void mif_netif_wake(struct link_device *ld); - /* flow control CMD from CP, it use in serial devices */ int link_rx_flowctl_cmd(struct link_device *ld, const char *data, size_t len); + /* get iod from tree functions */ struct io_device *get_iod_with_format(struct modem_shared *msd, @@ -222,14 +204,12 @@ void mif_add_timer(struct timer_list *timer, unsigned long expire, void (*function)(unsigned long), unsigned long data); /* debug helper functions for sipc4, sipc5 */ -void mif_print_data(const char *buff, int len); -void mif_dump2format16(const char *data, int len, char *buff, char *tag); -void mif_dump2format4(const char *data, int len, char *buff, char *tag); -void mif_print_dump(const char *data, int len, int width); +void mif_print_data(char *buf, int len); void print_sipc4_hdlc_fmt_frame(const u8 *psrc); void print_sipc4_fmt_frame(const u8 *psrc); void print_sipc5_link_fmt_frame(const u8 *psrc); + /*--------------------------------------------------------------------------- IPv4 Header Format @@ -302,14 +282,25 @@ void print_sipc5_link_fmt_frame(const u8 *psrc); -------------------------------------------------------------------------*/ #define UDP_HDR_SIZE 8 -void print_ip4_packet(const u8 *ip_pkt, bool tx); -bool is_dns_packet(const u8 *ip_pkt); -bool is_syn_packet(const u8 *ip_pkt); +void print_ip4_packet(u8 *ip_pkt, bool tx); +bool is_dns_packet(u8 *ip_pkt); +bool is_syn_packet(u8 *ip_pkt); int memcmp16_to_io(const void __iomem *to, void *from, int size); int mif_test_dpram(char *dp_name, u8 __iomem *start, u32 size); -struct file *mif_open_file(const char *path); -void mif_save_file(struct file *fp, const char *buff, size_t size); -void mif_close_file(struct file *fp); + +static const inline char *get_dev_name(int dev) +{ + if (dev == IPC_BYPASS) + return "BYPASS"; + else if (dev == IPC_PDP0) + return "pdp0"; + else if (dev == IPC_PDP1) + return "pdp1"; + else if (dev == IPC_RFS) + return "RFS"; + else + return "NONE"; +} #endif/*__MODEM_UTILS_H__*/ diff --git a/drivers/misc/modem_if/modem_variation.h b/drivers/misc/modem_if/modem_variation.h index 2865f7bc10e..efc076470bd 100644 --- a/drivers/misc/modem_if/modem_variation.h +++ b/drivers/misc/modem_if/modem_variation.h @@ -16,7 +16,7 @@ #ifndef __MODEM_VARIATION_H__ #define __MODEM_VARIATION_H__ -#include <linux/platform_data/modem.h> +#include "modem_tizen.h" #define DECLARE_MODEM_INIT(type) \ int type ## _init_modemctl_device(struct modem_ctl *mc, \ @@ -94,12 +94,6 @@ DECLARE_LINK_INIT(dpram); DECLARE_LINK_INIT_DUMMY(dpram) #endif -#ifdef CONFIG_LINK_DEVICE_PLD -DECLARE_LINK_INIT(pld); -#else -DECLARE_LINK_INIT_DUMMY(pld) -#endif - #ifdef CONFIG_LINK_DEVICE_SPI DECLARE_LINK_INIT(spi); #else @@ -145,7 +139,6 @@ static link_init_call link_init_func[] = { LINK_INIT_CALL(usb), LINK_INIT_CALL(hsic), LINK_INIT_CALL(c2c), - LINK_INIT_CALL(pld), }; static int call_modem_init_func(struct modem_ctl *mc, struct modem_data *pdata) diff --git a/drivers/misc/modem_if/sipc5_io_device.c b/drivers/misc/modem_if/sipc5_io_device.c deleted file mode 100644 index 636e191997b..00000000000 --- a/drivers/misc/modem_if/sipc5_io_device.c +++ /dev/null @@ -1,1624 +0,0 @@ -/* /linux/drivers/misc/modem_if/sipc5_io_device.c - * - * 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/init.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/poll.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/if_arp.h> -#include <linux/ip.h> -#include <linux/if_ether.h> -#include <linux/etherdevice.h> -#include <linux/device.h> -#include <linux/module.h> - -#include <linux/platform_data/modem.h> -#ifdef CONFIG_LINK_DEVICE_C2C -#include <linux/platform_data/c2c.h> -#endif -#include "modem_prj.h" -#include "modem_utils.h" - -static ssize_t show_waketime(struct device *dev, - struct device_attribute *attr, char *buf) -{ - unsigned int msec; - char *p = buf; - struct miscdevice *miscdev = dev_get_drvdata(dev); - struct io_device *iod = container_of(miscdev, struct io_device, - miscdev); - - msec = jiffies_to_msecs(iod->waketime); - - p += sprintf(buf, "raw waketime : %ums\n", msec); - - return p - buf; -} - -static ssize_t store_waketime(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned long msec; - int ret; - struct miscdevice *miscdev = dev_get_drvdata(dev); - struct io_device *iod = container_of(miscdev, struct io_device, - miscdev); - - ret = strict_strtoul(buf, 10, &msec); - if (ret) - return count; - - iod->waketime = msecs_to_jiffies(msec); - - return count; -} - -static struct device_attribute attr_waketime = - __ATTR(waketime, S_IRUGO | S_IWUSR, show_waketime, store_waketime); - -static ssize_t show_loopback(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct miscdevice *miscdev = dev_get_drvdata(dev); - struct modem_shared *msd = - container_of(miscdev, struct io_device, miscdev)->msd; - unsigned char *ip = (unsigned char *)&msd->loopback_ipaddr; - char *p = buf; - - p += sprintf(buf, "%u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]); - - return p - buf; -} - -static ssize_t store_loopback(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct miscdevice *miscdev = dev_get_drvdata(dev); - struct modem_shared *msd = - container_of(miscdev, struct io_device, miscdev)->msd; - - msd->loopback_ipaddr = ipv4str_to_be32(buf, count); - - return count; -} - -static struct device_attribute attr_loopback = - __ATTR(loopback, S_IRUGO | S_IWUSR, show_loopback, store_loopback); - -static void iodev_showtxlink(struct io_device *iod, void *args) -{ - char **p = (char **)args; - struct link_device *ld = get_current_link(iod); - - if (iod->io_typ == IODEV_NET && IS_CONNECTED(iod, ld)) - *p += sprintf(*p, "%s: %s\n", iod->name, ld->name); -} - -static ssize_t show_txlink(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct miscdevice *miscdev = dev_get_drvdata(dev); - struct modem_shared *msd = - container_of(miscdev, struct io_device, miscdev)->msd; - char *p = buf; - - iodevs_for_each(msd, iodev_showtxlink, &p); - - return p - buf; -} - -static ssize_t store_txlink(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - /* don't change without gpio dynamic switching */ - return -EINVAL; -} - -static struct device_attribute attr_txlink = - __ATTR(txlink, S_IRUGO | S_IWUSR, show_txlink, store_txlink); - -/** - * rx_check_frame_cfg - * @cfg: configuration field of a link layer header - * @frm: pointer to the sipc5_frame_data buffer - * - * 1) Checks whether or not an extended field exists - * 2) Calculates the length of a link layer header - * - * Returns the size of a link layer header - * - * Must be invoked only when the configuration field of the link layer header - * is validated with sipc5_start_valid() function - */ -static int rx_check_frame_cfg(u8 cfg, struct sipc5_frame_data *frm) -{ - frm->config = cfg; - - if (likely(cfg & SIPC5_PADDING_EXIST)) - frm->padding = true; - - if (unlikely(cfg & SIPC5_EXT_FIELD_EXIST)) { - if (cfg & SIPC5_CTL_FIELD_EXIST) { - frm->ctl_fld = true; - frm->hdr_len = SIPC5_HEADER_SIZE_WITH_CTL_FLD; - } else { - frm->ext_len = true; - frm->hdr_len = SIPC5_HEADER_SIZE_WITH_EXT_LEN; - } - } else { - frm->hdr_len = SIPC5_MIN_HEADER_SIZE; - } - - return frm->hdr_len; -} - -/** - * rx_build_meta_data - * @ld: pointer to the link device - * @frm: pointer to the sipc5_frame_data buffer - * - * Fills each field of sipc5_frame_data from a link layer header - * 1) Extracts the channel ID - * 2) Calculates the length of a link layer frame - * 3) Extracts a control field if exists - * 4) Calculates the length of an IPC message packet in the link layer frame - * - */ -static void rx_build_meta_data(struct link_device *ld, - struct sipc5_frame_data *frm) -{ - u16 *sz16 = (u16 *)(frm->hdr + SIPC5_LEN_OFFSET); - u32 *sz32 = (u32 *)(frm->hdr + SIPC5_LEN_OFFSET); - - frm->ch_id = frm->hdr[SIPC5_CH_ID_OFFSET]; - - if (unlikely(frm->ext_len)) - frm->len = *sz32; - else - frm->len = *sz16; - - if (unlikely(frm->ctl_fld)) - frm->control = frm->hdr[SIPC5_CTL_OFFSET]; - - frm->data_len = frm->len - frm->hdr_len; - - mif_debug("%s: FRM ch:%d len:%d ctl:%02X data.len:%d\n", - ld->name, frm->ch_id, frm->len, frm->control, frm->data_len); -} - -/** - * tx_build_link_header - * @frm: pointer to the sipc5_frame_data buffer - * @iod: pointer to the IO device - * @ld: pointer to the link device - * @count: length of the data to be transmitted - * - * Builds the meta data for an SIPC5 frame and the link layer header of it - * Returns the link layer header length for an SIPC5 frame or 0 for other frame - */ -static unsigned tx_build_link_header(struct sipc5_frame_data *frm, - struct io_device *iod, struct link_device *ld, ssize_t count) -{ - u8 *buff = frm->hdr; - u16 *sz16 = (u16 *)(buff + SIPC5_LEN_OFFSET); - u32 *sz32 = (u32 *)(buff + SIPC5_LEN_OFFSET); - - memset(frm, 0, sizeof(struct sipc5_frame_data)); - - if (iod->format == IPC_CMD || - iod->format == IPC_BOOT || - iod->format == IPC_RAMDUMP) { - frm->len = count; - return 0; - } - - frm->config = SIPC5_START_MASK; - - if (iod->format == IPC_FMT && count > 2048) { - frm->ctl_fld = true; - frm->config |= SIPC5_EXT_FIELD_EXIST; - frm->config |= SIPC5_CTL_FIELD_EXIST; - } - - if (iod->id >= SIPC5_CH_ID_RFS_0 && count > 0xFFFF) { - frm->ext_len = true; - frm->config |= SIPC5_EXT_FIELD_EXIST; - } - - if (ld->aligned) - frm->config |= SIPC5_PADDING_EXIST; - - frm->ch_id = iod->id; - - frm->hdr_len = sipc5_get_hdr_len(frm->config); - frm->data_len = count; - frm->len = frm->hdr_len + frm->data_len; - - buff[SIPC5_CONFIG_OFFSET] = frm->config; - buff[SIPC5_CH_ID_OFFSET] = frm->ch_id; - - if (unlikely(frm->ext_len)) - *sz32 = (u32)frm->len; - else - *sz16 = (u16)frm->len; - - if (unlikely(frm->ctl_fld)) - buff[SIPC5_CTL_OFFSET] = frm->control; - - return frm->hdr_len; -} - -static int rx_fmt_frame(struct sk_buff *skb) -{ - struct io_device *iod = skbpriv(skb)->iod; - struct link_device *ld = skbpriv(skb)->ld; - struct sk_buff_head *rxq = &iod->sk_rx_q; - struct sipc_fmt_hdr *fh; - struct sk_buff *rx_skb; - u8 ctrl = skbpriv(skb)->control; - unsigned id = ctrl & 0x7F; - - if (iod->skb[id] == NULL) { - /* - ** There has been no multiple frame with this ID. - */ - if ((ctrl & 0x80) == 0) { - /* - ** It is a single frame because the "more" bit is 0. - */ - skb_queue_tail(rxq, skb); - if (unlikely(rxq->qlen > 2048)) { - struct sk_buff *victim; - mif_info("%s: WARNING! rxq->qlen %d > 2048\n", - iod->name, rxq->qlen); - victim = skb_dequeue(rxq); - dev_kfree_skb_any(victim); - } else { - mif_debug("%s: rxq->qlen = %d\n", - iod->name, rxq->qlen); - } - - wake_up(&iod->wq); - return 0; - } - - /* - ** The start of multiple frames - */ - fh = (struct sipc_fmt_hdr *)skb->data; - mif_debug("%s: start multi-frame (ID:%d len:%d)\n", - iod->name, id, fh->len); - - rx_skb = rx_alloc_skb(fh->len, iod, ld); - if (!rx_skb) { - mif_info("%s: ERR! rx_alloc_skb fail\n", iod->name); - return -ENOMEM; - } - - iod->skb[id] = rx_skb; - } else { - rx_skb = iod->skb[id]; - } - - /* - ** Start multi-frame processing - */ - memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len); - dev_kfree_skb_any(skb); - - if (ctrl & 0x80) { - /* The last frame has not arrived yet. */ - mif_debug("%s: recv multi-frame (ID:%d rcvd:%d)\n", - iod->name, id, rx_skb->len); - } else { - /* It is the last frame because the "more" bit is 0. */ - mif_debug("%s: end multi-frame (ID:%d rcvd:%d)\n", - iod->name, id, rx_skb->len); - skb_queue_tail(rxq, rx_skb); - if (unlikely(rxq->qlen > 2048)) { - struct sk_buff *victim; - mif_info("%s: WARNING! rxq->qlen %d > 2048\n", - iod->name, rxq->qlen); - victim = skb_dequeue(rxq); - dev_kfree_skb_any(victim); - } else { - mif_debug("%s: rxq->qlen = %d\n", iod->name, rxq->qlen); - } - - iod->skb[id] = NULL; - wake_up(&iod->wq); - } - - return 0; -} - -static int rx_rfs_frame(struct sk_buff *skb) -{ - struct io_device *iod = skbpriv(skb)->iod; - struct sk_buff_head *rxq = &iod->sk_rx_q; - - skb_queue_tail(rxq, skb); - if (unlikely(rxq->qlen > 2048)) { - struct sk_buff *victim; - mif_debug("%s: rxq->qlen %d > 2048\n", iod->name, rxq->qlen); - victim = skb_dequeue(rxq); - dev_kfree_skb_any(victim); - } else { - mif_debug("%s: rxq->qlen %d\n", iod->name, rxq->qlen); - } - - wake_up(&iod->wq); - - return 0; -} - -static int rx_loopback(struct sk_buff *skb) -{ - struct io_device *iod = skbpriv(skb)->iod; - struct link_device *ld = get_current_link(iod); - struct sipc5_frame_data frm; - unsigned headroom; - unsigned tailroom = 0; - int ret; - - headroom = tx_build_link_header(&frm, iod, ld, skb->len); - - if (ld->aligned) - tailroom = sipc5_calc_padding_size(headroom + skb->len); - - /* We need not to expand skb in here. dev_alloc_skb (in rx_alloc_skb) - * already alloc 32bytes padding in headroom. 32bytes are enough. - */ - - /* store IPC link header to start of skb - * this is skb_push not skb_put. different with misc_write. - */ - memcpy(skb_push(skb, headroom), frm.hdr, headroom); - - /* store padding */ - if (tailroom) - skb_put(skb, tailroom); - - /* forward */ - ret = ld->send(ld, iod, skb); - if (ret < 0) - mif_err("%s->%s: ld->send fail: %d\n", iod->name, - ld->name, ret); - return ret; -} - -static int rx_raw_misc(struct sk_buff *skb) -{ - struct io_device *iod = skbpriv(skb)->iod; /* same with real_iod */ - struct sk_buff_head *rxq = &iod->sk_rx_q; - - skb_queue_tail(rxq, skb); - if (unlikely(rxq->qlen > 2048)) { - struct sk_buff *victim; - mif_debug("%s: rxq->qlen %d > 2048\n", iod->name, rxq->qlen); - victim = skb_dequeue(rxq); - dev_kfree_skb_any(victim); - } else { - mif_debug("%s: rxq->qlen %d\n", iod->name, rxq->qlen); - } - - wake_up(&iod->wq); - - return 0; -} - -static int rx_multi_pdp(struct sk_buff *skb) -{ - struct io_device *iod = skbpriv(skb)->iod; /* same with real_iod */ - struct net_device *ndev; - struct iphdr *iphdr; - struct ethhdr *ehdr; - int ret; - const char source[ETH_ALEN] = SOURCE_MAC_ADDR; - - ndev = iod->ndev; - if (!ndev) { - mif_info("%s: ERR! no iod->ndev\n", iod->name); - return -ENODEV; - } - - skb->dev = ndev; - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += skb->len; - - /* check the version of IP */ - iphdr = (struct iphdr *)skb->data; - if (iphdr->version == IP6VERSION) - skb->protocol = htons(ETH_P_IPV6); - else - skb->protocol = htons(ETH_P_IP); - - if (iod->use_handover) { - skb_push(skb, sizeof(struct ethhdr)); - ehdr = (void *)skb->data; - memcpy(ehdr->h_dest, ndev->dev_addr, ETH_ALEN); - memcpy(ehdr->h_source, source, ETH_ALEN); - ehdr->h_proto = skb->protocol; - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb_reset_mac_header(skb); - - skb_pull(skb, sizeof(struct ethhdr)); - } - - if (in_interrupt()) - ret = netif_rx(skb); - else - ret = netif_rx_ni(skb); - - if (ret != NET_RX_SUCCESS) - mif_info("%s: ERR! netif_rx fail (err %d)\n", iod->name, ret); - - return ret; -} - -static int rx_demux(struct link_device *ld, struct sk_buff *skb) -{ - struct io_device *iod = NULL; - char *link = ld->name; - u8 ch = skbpriv(skb)->ch_id; - - if (unlikely(ch == SIPC5_CH_ID_MAX || ch == 0)) { - mif_info("%s: ERR! invalid ch# %d\n", link, ch); - return -ENODEV; - } - - /* IP loopback */ - if (ch == DATA_LOOPBACK_CHANNEL && ld->msd->loopback_ipaddr) - ch = RMNET0_CH_ID; - - iod = link_get_iod_with_channel(ld, ch); - if (unlikely(!iod)) { - mif_info("%s: ERR! no iod for ch# %d\n", link, ch); - return -ENODEV; - } - - skbpriv(skb)->ld = ld; - skbpriv(skb)->iod = iod; - skbpriv(skb)->real_iod = iod; - - /* don't care about CP2AP_LOOPBACK_CHANNEL is opened */ - if (unlikely(iod->id == CP2AP_LOOPBACK_CHANNEL)) - return rx_loopback(skb); - - if (atomic_read(&iod->opened) <= 0) { - mif_info("%s: ERR! %s is not opened\n", link, iod->name); - return -ENODEV; - } - - if (ch >= SIPC5_CH_ID_RFS_0) - return rx_rfs_frame(skb); - else if (ch >= SIPC5_CH_ID_FMT_0) - return rx_fmt_frame(skb); - else if (iod->io_typ == IODEV_MISC) - return rx_raw_misc(skb); - else - return rx_multi_pdp(skb); -} - -/* Check and store link layer header, then alloc an skb */ -static int rx_header_from_serial(struct io_device *iod, struct link_device *ld, - u8 *buff, unsigned size, struct sipc5_frame_data *frm) -{ - char *link = ld->name; - struct sk_buff *skb; - int len; - u8 cfg = buff[0]; - - mif_debug("%s: size %d\n", link, size); - - if (!frm->config) { - if (unlikely(!sipc5_start_valid(cfg))) { - mif_info("%s: ERR! wrong start (0x%02x)\n", link, cfg); - return -EBADMSG; - } - rx_check_frame_cfg(cfg, frm); - - /* Copy the link layer header to the header buffer */ - len = min(frm->hdr_len, size); - memcpy(frm->hdr, buff, len); - } else { - /* Copy the link layer header to the header buffer */ - len = min((frm->hdr_len - frm->hdr_rcvd), size); - memcpy((frm->hdr + frm->hdr_rcvd), buff, len); - } - - frm->hdr_rcvd += len; - - mif_debug("%s: FRM hdr_len:%d, hdr_rcvd:%d\n", - link, frm->hdr_len, frm->hdr_rcvd); - - if (frm->hdr_rcvd >= frm->hdr_len) { - rx_build_meta_data(ld, frm); - skb = rx_alloc_skb(frm->data_len, iod, ld); - fragdata(iod, ld)->skb_recv = skb; - skbpriv(skb)->ch_id = frm->ch_id; - skbpriv(skb)->control = frm->control; - } - - return len; -} - -/* copy data to skb */ -static int rx_payload_from_serial(struct io_device *iod, struct link_device *ld, - u8 *buff, unsigned size, struct sipc5_frame_data *frm) -{ - struct sk_buff *skb = fragdata(iod, ld)->skb_recv; - char *link = ld->name; - unsigned rest = frm->data_len - frm->data_rcvd; - unsigned len; - - /* rest == (frm->data_len - frm->data_rcvd) == tailroom of skb */ - rest = frm->data_len - frm->data_rcvd; - mif_debug("%s: FRM data.len:%d data.rcvd:%d rest:%d size:%d\n", - link, frm->data_len, frm->data_rcvd, rest, size); - - /* If there is no skb, data must be dropped. */ - len = min(rest, size); - if (skb) - memcpy(skb_put(skb, len), buff, len); - - frm->data_rcvd += len; - - mif_debug("%s: FRM data_len:%d, data_rcvd:%d\n", - link, frm->data_len, frm->data_rcvd); - - return len; -} - -static int rx_frame_from_serial(struct io_device *iod, struct link_device *ld, - const char *data, unsigned size) -{ - struct sipc5_frame_data *frm = &fragdata(iod, ld)->f_data; - struct sk_buff *skb; - char *link = ld->name; - u8 *buff = (u8 *)data; - int rest = (int)size; - int err = 0; - int done = 0; - - mif_debug("%s: size = %d\n", link, size); - - if (frm->hdr_rcvd >= frm->hdr_len && frm->data_rcvd < frm->data_len) { - /* - ** There is an skb that is waiting for more SIPC5 data. - ** In this case, rx_header_from_serial() must be skipped. - */ - mif_debug("%s: FRM data.len:%d data.rcvd:%d -> recv_data\n", - link, frm->data_len, frm->data_rcvd); - goto recv_data; - } - -next_frame: - /* Receive and analyze header, then prepare an akb */ - err = done = rx_header_from_serial(iod, ld, buff, rest, frm); - if (err < 0) - goto err_exit; - - buff += done; - rest -= done; - mif_debug("%s: rx_header() -> done:%d rest:%d\n", link, done, rest); - if (rest < 0) - goto err_range; - - if (rest == 0) - return size; - -recv_data: - err = 0; - - mif_debug("%s: done:%d rest:%d -> rx_payload()\n", link, done, rest); - - done = rx_payload_from_serial(iod, ld, buff, rest, frm); - buff += done; - rest -= done; - - mif_debug("%s: rx_payload() -> done:%d rest:%d\n", link, done, rest); - - if (rest == 0 && frm->data_rcvd < frm->data_len) { - /* - Data is being received and more data will come within the next - frame from the link device. - */ - return size; - } - - /* At this point, one complete link layer frame has been received. */ - - /* A padding size is applied to access the next IPC frame. */ - if (frm->padding) { - done = sipc5_calc_padding_size(frm->len); - if (done > rest) { - mif_info("%s: ERR! padding %d > rest %d\n", - link, done, rest); - goto err_exit; - } - - buff += done; - rest -= done; - - mif_debug("%s: padding:%d -> rest:%d\n", link, done, rest); - - if (rest < 0) - goto err_range; - - } - - skb = fragdata(iod, ld)->skb_recv; - if (likely(skb)) { - mif_debug("%s: len:%d -> rx_demux()\n", link, skb->len); - err = rx_demux(ld, skb); - if (err < 0) - dev_kfree_skb_any(skb); - } else { - mif_debug("%s: len:%d -> drop\n", link, skb->len); - } - - /* initialize the skb_recv and the frame_data buffer */ - fragdata(iod, ld)->skb_recv = NULL; - memset(frm, 0, sizeof(struct sipc5_frame_data)); - - if (rest > 0) - goto next_frame; - - if (rest <= 0) - return size; - -err_exit: - if (fragdata(iod, ld)->skb_recv && - frm->hdr_rcvd >= frm->hdr_len && frm->data_rcvd >= frm->data_len) { - dev_kfree_skb_any(fragdata(iod, ld)->skb_recv); - memset(frm, 0, sizeof(struct sipc5_frame_data)); - fragdata(iod, ld)->skb_recv = NULL; - mif_info("%s: ERR! clear frag\n", link); - } - return err; - -err_range: - mif_info("%s: ERR! size:%d vs. rest:%d\n", link, size, rest); - return size; -} - -/** - * rx_header_from_mem - * @ld: pointer to the link device - * @buff: pointer to the frame - * @rest: size of the frame - * @frm: pointer to the sipc5_frame_data buffer - * - * 1) Verifies a link layer header configuration of a frame - * 2) Stores the link layer header to the header buffer - * 3) Builds and stores the meta data of the frame into a meta data buffer - * 4) Verifies the length of the frame - * - * Returns SIPC5 header length - */ -static int rx_header_from_mem(struct link_device *ld, u8 *buff, unsigned rest, - struct sipc5_frame_data *frm) -{ - char *link = ld->name; - u8 cfg = buff[0]; - - /* Verify link layer header configuration */ - if (unlikely(!sipc5_start_valid(cfg))) { - mif_info("%s: ERR! wrong start (0x%02x)\n", link, cfg); - return -EBADMSG; - } - rx_check_frame_cfg(cfg, frm); - - /* Store the link layer header to the header buffer */ - memcpy(frm->hdr, buff, frm->hdr_len); - frm->hdr_rcvd = frm->hdr_len; - - /* Build and store the meta data of this frame */ - rx_build_meta_data(ld, frm); - - /* Verify frame length */ - if (unlikely(frm->len > rest)) { - mif_info("%s: ERR! frame length %d > rest %d\n", - link, frm->len, rest); - return -EBADMSG; - } - - return frm->hdr_rcvd; -} - -/* copy data to skb */ -static int rx_payload_from_mem(struct sk_buff *skb, u8 *buff, unsigned len) -{ - /* If there is no skb, data must be dropped. */ - if (skb) - memcpy(skb_put(skb, len), buff, len); - return len; -} - -static int rx_frame_from_mem(struct io_device *iod, struct link_device *ld, - const char *data, unsigned size) -{ - struct sipc5_frame_data *frm = &fragdata(iod, ld)->f_data; - struct sk_buff *skb; - char *link = ld->name; - u8 *buff = (u8 *)data; - int rest = (int)size; - int len; - int done; - - mif_debug("%s: size = %d\n", link, size); - - while (rest > 0) { - /* Initialize the frame data buffer */ - memset(frm, 0, sizeof(struct sipc5_frame_data)); - skb = NULL; - - /* Receive and analyze link layer header */ - done = rx_header_from_mem(ld, buff, rest, frm); - if (unlikely(done < 0)) - return -EBADMSG; - - /* Verify rest size */ - rest -= done; - if (rest < 0) { - mif_info("%s: ERR! rx_header -> rest %d\n", link, rest); - return -ERANGE; - } - - /* Move buff pointer to the payload */ - buff += done; - - /* Prepare an akb */ - len = frm->data_len; - skb = rx_alloc_skb(len, iod, ld); - - /* Store channel ID and control fields to the CB of the skb */ - skbpriv(skb)->ch_id = frm->ch_id; - skbpriv(skb)->control = frm->control; - - /* Receive payload */ - mif_debug("%s: done:%d rest:%d len:%d -> rx_payload()\n", - link, done, rest, len); - done = rx_payload_from_mem(skb, buff, len); - rest -= done; - if (rest < 0) { - mif_info("%s: ERR! rx_payload() -> rest %d\n", - link, rest); - if (skb) - dev_kfree_skb_any(skb); - return -ERANGE; - } - buff += done; - - /* A padding size is applied to access the next IPC frame. */ - if (frm->padding) { - done = sipc5_calc_padding_size(frm->len); - if (done > rest) { - mif_info("%s: ERR! padding %d > rest %d\n", - link, done, rest); - if (skb) - dev_kfree_skb_any(skb); - return -ERANGE; - } - buff += done; - rest -= done; - } - - if (likely(skb)) { - mif_debug("%s: len:%d -> rx_demux()\n", link, skb->len); - if (rx_demux(ld, skb) < 0) - dev_kfree_skb_any(skb); - } else { - mif_debug("%s: len:%d -> drop\n", link, skb->len); - } - } - - return 0; -} - -/* called from link device when a packet arrives for this io device */ -static int io_dev_recv_data_from_link_dev(struct io_device *iod, - struct link_device *ld, const char *data, unsigned int len) -{ - struct sk_buff_head *rxq = &iod->sk_rx_q; - struct sk_buff *skb; - char *link = ld->name; - int err; - - if (!data) { - mif_info("%s: ERR! !data\n", link); - return -EINVAL; - } - - if (len <= 0) { - mif_info("%s: ERR! len %d <= 0\n", link, len); - return -EINVAL; - } - - switch (iod->format) { - case IPC_FMT: - case IPC_RAW: - case IPC_RFS: - case IPC_MULTI_RAW: -#ifdef CONFIG_HAS_WAKELOCK - if (iod->waketime) - wake_lock_timeout(&iod->wakelock, iod->waketime); -#endif - - if (ld->link_type == LINKDEV_DPRAM && ld->aligned) - err = rx_frame_from_mem(iod, ld, data, len); - else - err = rx_frame_from_serial(iod, ld, data, len); - - if (err < 0) - mif_info("%s: ERR! rx_frame_from_link fail (err %d)\n", - link, err); - - return err; - - case IPC_CMD: - case IPC_BOOT: - case IPC_RAMDUMP: - /* save packet to sk_buff */ - skb = rx_alloc_skb(len, iod, ld); - if (!skb) { - mif_info("%s: ERR! rx_alloc_skb fail\n", link); - return -ENOMEM; - } - - mif_debug("%s: len:%d -> iod:%s\n", link, len, iod->name); - - memcpy(skb_put(skb, len), data, len); - skb_queue_tail(rxq, skb); - if (unlikely(rxq->qlen > 2048)) { - struct sk_buff *victim; - mif_info("%s: ERR! rxq->qlen %d > 2048\n", - iod->name, rxq->qlen); - victim = skb_dequeue(rxq); - dev_kfree_skb_any(victim); - } - wake_up(&iod->wq); - - return len; - - default: - mif_info("%s: ERR! unknown format %d\n", link, iod->format); - return -EINVAL; - } -} - -static int rx_frame_from_skb(struct io_device *iod, struct link_device *ld, - struct sk_buff *skb) -{ - struct sipc5_frame_data *frm = &fragdata(iod, ld)->f_data; - u8 cfg = skb->data[0]; - - /* Initialize the frame data buffer */ - memset(frm, 0, sizeof(struct sipc5_frame_data)); - - /* - ** The start of a link layer header has already been checked in the - ** link device. - */ - - /* Analyze the configuration of the link layer header */ - rx_check_frame_cfg(cfg, frm); - - /* Store the link layer header to the header buffer */ - memcpy(frm->hdr, skb->data, frm->hdr_len); - frm->hdr_rcvd = frm->hdr_len; - - /* Build and store the meta data of this frame */ - rx_build_meta_data(ld, frm); - - /* - ** The length of the frame has already been checked in the link device. - */ - - /* Trim the link layer header off the frame */ - skb_pull(skb, frm->hdr_len); - - /* Store channel ID and control fields to the CB of the skb */ - skbpriv(skb)->ch_id = frm->ch_id; - skbpriv(skb)->control = frm->control; - - /* Demux the frame */ - if (rx_demux(ld, skb) < 0) { - mif_err("%s: ERR! rx_demux fail\n", ld->name); - return -EINVAL; - } - - return 0; -} - -/* called from link device when a packet arrives for this io device */ -static int io_dev_recv_skb_from_link_dev(struct io_device *iod, - struct link_device *ld, struct sk_buff *skb) -{ - char *link = ld->name; - enum dev_format dev = iod->format; - int err; - - switch (dev) { - case IPC_FMT: - case IPC_RAW: - case IPC_RFS: - case IPC_MULTI_RAW: -#ifdef CONFIG_HAS_WAKELOCK - if (iod->waketime) - wake_lock_timeout(&iod->wakelock, iod->waketime); -#endif - - err = rx_frame_from_skb(iod, ld, skb); - if (err < 0) { - dev_kfree_skb_any(skb); - mif_info("%s: ERR! rx_frame_from_skb fail (err %d)\n", - link, err); - } - - return err; - - default: - mif_info("%s: ERR! unknown device %d\n", link, dev); - return -EINVAL; - } -} - -/* inform the IO device that the modem is now online or offline or - * crashing or whatever... - */ -static void io_dev_modem_state_changed(struct io_device *iod, - enum modem_state state) -{ - mif_info("%s: %s state changed (state %d)\n", - iod->name, iod->mc->name, state); - - iod->mc->phone_state = state; - - if (state == STATE_CRASH_RESET || state == STATE_CRASH_EXIT || - state == STATE_NV_REBUILDING) - wake_up(&iod->wq); -} - -/** - * io_dev_sim_state_changed - * @iod: IPC's io_device - * @sim_online: SIM is online? - */ -static void io_dev_sim_state_changed(struct io_device *iod, bool sim_online) -{ - if (atomic_read(&iod->opened) == 0) { - mif_info("%s: ERR! not opened\n", iod->name); - } else if (iod->mc->sim_state.online == sim_online) { - mif_info("%s: SIM state not changed\n", iod->name); - } else { - iod->mc->sim_state.online = sim_online; - iod->mc->sim_state.changed = true; - mif_info("%s: SIM state changed {online %d, changed %d}\n", - iod->name, iod->mc->sim_state.online, - iod->mc->sim_state.changed); - wake_up(&iod->wq); - } -} - -static void iodev_dump_status(struct io_device *iod, void *args) -{ - if (iod->format == IPC_RAW && iod->io_typ == IODEV_NET) { - struct link_device *ld = get_current_link(iod); - mif_com_log(iod->mc->msd, "%s: %s\n", iod->name, ld->name); - } -} - -static int misc_open(struct inode *inode, struct file *filp) -{ - struct io_device *iod = to_io_device(filp->private_data); - struct modem_shared *msd = iod->msd; - struct link_device *ld; - int ret; - filp->private_data = (void *)iod; - - atomic_inc(&iod->opened); - - list_for_each_entry(ld, &msd->link_dev_list, list) { - if (IS_CONNECTED(iod, ld) && ld->init_comm) { - ret = ld->init_comm(ld, iod); - if (ret < 0) { - mif_info("%s: init_comm fail(%d)\n", - ld->name, ret); - return ret; - } - } - } - - mif_err("%s (opened %d)\n", iod->name, atomic_read(&iod->opened)); - - return 0; -} - -static int misc_release(struct inode *inode, struct file *filp) -{ - struct io_device *iod = (struct io_device *)filp->private_data; - struct modem_shared *msd = iod->msd; - struct link_device *ld; - - atomic_dec(&iod->opened); - skb_queue_purge(&iod->sk_rx_q); - - list_for_each_entry(ld, &msd->link_dev_list, list) { - if (IS_CONNECTED(iod, ld) && ld->terminate_comm) - ld->terminate_comm(ld, iod); - } - - mif_err("%s (opened %d)\n", iod->name, atomic_read(&iod->opened)); - - return 0; -} - -static unsigned int misc_poll(struct file *filp, struct poll_table_struct *wait) -{ - struct io_device *iod = (struct io_device *)filp->private_data; - - poll_wait(filp, &iod->wq, wait); - - if (!skb_queue_empty(&iod->sk_rx_q) && - iod->mc->phone_state != STATE_OFFLINE) { - return POLLIN | POLLRDNORM; - } else if ((iod->mc->phone_state == STATE_CRASH_RESET) || - (iod->mc->phone_state == STATE_CRASH_EXIT) || - (iod->mc->phone_state == STATE_NV_REBUILDING) || - (iod->mc->sim_state.changed)) { - if (iod->format == IPC_RAW) { - msleep(20); - return 0; - } - return POLLHUP; - } else { - return 0; - } -} - -static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - int p_state; - struct io_device *iod = (struct io_device *)filp->private_data; - struct link_device *ld = get_current_link(iod); - char cpinfo_buf[530] = "CP Crash "; - unsigned long size; - int ret; - - switch (cmd) { - case IOCTL_MODEM_ON: - mif_info("%s: IOCTL_MODEM_ON\n", iod->name); - return iod->mc->ops.modem_on(iod->mc); - - case IOCTL_MODEM_OFF: - mif_info("%s: IOCTL_MODEM_OFF\n", iod->name); - return iod->mc->ops.modem_off(iod->mc); - - case IOCTL_MODEM_RESET: - mif_info("%s: IOCTL_MODEM_RESET\n", iod->name); - return iod->mc->ops.modem_reset(iod->mc); - - case IOCTL_MODEM_BOOT_ON: - mif_info("%s: IOCTL_MODEM_BOOT_ON\n", iod->name); - return iod->mc->ops.modem_boot_on(iod->mc); - - case IOCTL_MODEM_BOOT_OFF: - mif_info("%s: IOCTL_MODEM_BOOT_OFF\n", iod->name); - return iod->mc->ops.modem_boot_off(iod->mc); - - case IOCTL_MODEM_BOOT_DONE: - mif_err("%s: IOCTL_MODEM_BOOT_DONE\n", iod->name); - if (iod->mc->ops.modem_boot_done) - return iod->mc->ops.modem_boot_done(iod->mc); - else - return 0; - - case IOCTL_MODEM_STATUS: - mif_debug("%s: IOCTL_MODEM_STATUS\n", iod->name); - - p_state = iod->mc->phone_state; - if ((p_state == STATE_CRASH_RESET) || - (p_state == STATE_CRASH_EXIT)) { - mif_info("%s: IOCTL_MODEM_STATUS (state %d)\n", - iod->name, p_state); - } else if (iod->mc->sim_state.changed) { - int s_state = iod->mc->sim_state.online ? - STATE_SIM_ATTACH : STATE_SIM_DETACH; - iod->mc->sim_state.changed = false; - return s_state; - } else if (p_state == STATE_NV_REBUILDING) { - mif_info("%s: IOCTL_MODEM_STATUS (state %d)\n", - iod->name, p_state); - iod->mc->phone_state = STATE_ONLINE; - } - return p_state; - - case IOCTL_MODEM_PROTOCOL_SUSPEND: - mif_debug("%s: IOCTL_MODEM_PROTOCOL_SUSPEND\n", - iod->name); - - if (iod->format != IPC_MULTI_RAW) - return -EINVAL; - - iodevs_for_each(iod->msd, iodev_netif_stop, 0); - return 0; - - case IOCTL_MODEM_PROTOCOL_RESUME: - mif_info("%s: IOCTL_MODEM_PROTOCOL_RESUME\n", - iod->name); - - if (iod->format != IPC_MULTI_RAW) - return -EINVAL; - - iodevs_for_each(iod->msd, iodev_netif_wake, 0); - return 0; - - case IOCTL_MODEM_DUMP_START: - mif_info("%s: IOCTL_MODEM_DUMP_START\n", iod->name); - return ld->dump_start(ld, iod); - - case IOCTL_MODEM_DUMP_UPDATE: - mif_debug("%s: IOCTL_MODEM_DUMP_UPDATE\n", iod->name); - return ld->dump_update(ld, iod, arg); - - case IOCTL_MODEM_FORCE_CRASH_EXIT: - mif_info("%s: IOCTL_MODEM_FORCE_CRASH_EXIT\n", iod->name); - if (iod->mc->ops.modem_force_crash_exit) - return iod->mc->ops.modem_force_crash_exit(iod->mc); - return -EINVAL; - - case IOCTL_MODEM_CP_UPLOAD: - mif_info("%s: IOCTL_MODEM_CP_UPLOAD\n", iod->name); - if (copy_from_user(cpinfo_buf + strlen(cpinfo_buf), - (void __user *)arg, MAX_CPINFO_SIZE) != 0) - return -EFAULT; - panic(cpinfo_buf); - return 0; - - case IOCTL_MODEM_DUMP_RESET: - mif_info("%s: IOCTL_MODEM_DUMP_RESET\n", iod->name); - return iod->mc->ops.modem_dump_reset(iod->mc); - - case IOCTL_MIF_LOG_DUMP: - iodevs_for_each(iod->msd, iodev_dump_status, 0); - size = MAX_MIF_BUFF_SIZE; - ret = copy_to_user((void __user *)arg, &size, - sizeof(unsigned long)); - if (ret < 0) - return -EFAULT; - - mif_dump_log(iod->mc->msd, iod); - return 0; - - case IOCTL_MIF_DPRAM_DUMP: -#ifdef CONFIG_LINK_DEVICE_DPRAM - if (iod->mc->mdm_data->link_types & LINKTYPE(LINKDEV_DPRAM)) { - size = iod->mc->mdm_data->dpram_ctl->dp_size; - ret = copy_to_user((void __user *)arg, &size, - sizeof(unsigned long)); - if (ret < 0) - return -EFAULT; - mif_dump_dpram(iod); - return 0; - } -#endif - return -EINVAL; - - default: - /* If you need to handle the ioctl for specific link device, - * then assign the link ioctl handler to ld->ioctl - * It will be call for specific link ioctl */ - if (ld->ioctl) - return ld->ioctl(ld, iod, cmd, arg); - - mif_info("%s: ERR! cmd 0x%X not defined.\n", iod->name, cmd); - return -EINVAL; - } - return 0; -} - -static ssize_t misc_write(struct file *filp, const char __user *data, - size_t count, loff_t *fpos) -{ - struct io_device *iod = (struct io_device *)filp->private_data; - struct link_device *ld = get_current_link(iod); - struct sk_buff *skb; - int ret; - unsigned headroom = 0; - unsigned tailroom = 0; - size_t tx_size; - struct sipc5_frame_data frm; - - if (iod->format <= IPC_RFS && iod->id == 0) - return -EINVAL; - - headroom = tx_build_link_header(&frm, iod, ld, count); - - if (ld->aligned) - tailroom = sipc5_calc_padding_size(headroom + count); - - tx_size = headroom + count + tailroom; - - skb = alloc_skb(tx_size, GFP_KERNEL); - if (!skb) { - mif_info("%s: ERR! alloc_skb fail (tx_size:%d)\n", - iod->name, tx_size); - return -ENOMEM; - } - - /* store IPC link header*/ - memcpy(skb_put(skb, headroom), frm.hdr, headroom); - - /* store IPC message */ - if (copy_from_user(skb_put(skb, count), data, count) != 0) { - if (skb) - dev_kfree_skb_any(skb); - return -EFAULT; - } - - if (iod->format == IPC_FMT) { - struct timespec epoch; - u8 *msg = (skb->data + headroom); -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - char str[MIF_MAX_STR_LEN]; - snprintf(str, MIF_MAX_STR_LEN, "%s: RL2MIF", iod->mc->name); - pr_ipc(str, msg, (count > 16 ? 16 : count)); -#endif - getnstimeofday(&epoch); - mif_time_log(iod->mc->msd, epoch, NULL, 0); - mif_ipc_log(MIF_IPC_RL2AP, iod->mc->msd, msg, count); - } - - /* store padding */ - if (tailroom) - skb_put(skb, tailroom); - - /* send data with sk_buff, link device will put sk_buff - * into the specific sk_buff_q and run work-q to send data - */ - skbpriv(skb)->iod = iod; - skbpriv(skb)->ld = ld; - - ret = ld->send(ld, iod, skb); - if (ret < 0) { - mif_info("%s: ERR! ld->send fail (err %d)\n", iod->name, ret); - return ret; - } - - if (ret != tx_size) - mif_info("%s: wrong tx size (count:%d tx_size:%d ret:%d)\n", - iod->name, count, tx_size, ret); - - return count; -} - -static ssize_t misc_read(struct file *filp, char *buf, size_t count, - loff_t *fpos) -{ - struct io_device *iod = (struct io_device *)filp->private_data; - struct sk_buff_head *rxq = &iod->sk_rx_q; - struct sk_buff *skb; - int copied = 0; - - skb = skb_dequeue(rxq); - if (!skb) { - mif_info("%s: ERR! no data in rxq\n", iod->name); - return 0; - } - - if (iod->format == IPC_FMT) { - struct timespec epoch; -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - char str[MIF_MAX_STR_LEN]; - snprintf(str, MIF_MAX_STR_LEN, "%s: MIF2RL", iod->mc->name); - pr_ipc(str, skb->data, (skb->len > 16 ? 16 : skb->len)); -#endif - getnstimeofday(&epoch); - mif_time_log(iod->mc->msd, epoch, NULL, 0); - mif_ipc_log(MIF_IPC_AP2RL, iod->mc->msd, skb->data, skb->len); - } - - copied = skb->len > count ? count : skb->len; - - if (copy_to_user(buf, skb->data, copied)) { - mif_info("%s: ERR! copy_to_user fail\n", iod->name); - dev_kfree_skb_any(skb); - return -EFAULT; - } - - mif_debug("%s: data:%d copied:%d qlen:%d\n", - iod->name, skb->len, copied, rxq->qlen); - - if (skb->len > count) { - skb_pull(skb, count); - skb_queue_head(rxq, skb); - } else { - dev_kfree_skb_any(skb); - } - - return copied; -} - -#ifdef CONFIG_LINK_DEVICE_C2C -static int misc_mmap(struct file *filp, struct vm_area_struct *vma) -{ - int r = 0; - unsigned long size = 0; - unsigned long pfn = 0; - unsigned long offset = 0; - struct io_device *iod = (struct io_device *)filp->private_data; - - if (!vma) - return -EFAULT; - - size = vma->vm_end - vma->vm_start; - offset = vma->vm_pgoff << PAGE_SHIFT; - if (offset + size > (C2C_CP_RGN_SIZE + C2C_SH_RGN_SIZE)) { - mif_info("ERR: offset + size > C2C_CP_RGN_SIZE\n"); - return -EINVAL; - } - - /* Set the noncacheable property to the region */ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - vma->vm_flags |= VM_RESERVED | VM_IO; - - pfn = __phys_to_pfn(C2C_CP_RGN_ADDR + offset); - r = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot); - if (r) { - mif_info("ERR: Failed in remap_pfn_range()!!!\n"); - return -EAGAIN; - } - - mif_info("%s: VA = 0x%08lx, offset = 0x%lx, size = %lu\n", - iod->name, vma->vm_start, offset, size); - - return 0; -} -#endif - -static const struct file_operations misc_io_fops = { - .owner = THIS_MODULE, - .open = misc_open, - .release = misc_release, - .poll = misc_poll, - .unlocked_ioctl = misc_ioctl, - .write = misc_write, - .read = misc_read, -#ifdef CONFIG_LINK_DEVICE_C2C - .mmap = misc_mmap, -#endif -}; - -static int vnet_open(struct net_device *ndev) -{ - struct vnet *vnet = netdev_priv(ndev); - - mif_err("%s\n", vnet->iod->name); - - netif_start_queue(ndev); - atomic_inc(&vnet->iod->opened); - return 0; -} - -static int vnet_stop(struct net_device *ndev) -{ - struct vnet *vnet = netdev_priv(ndev); - - mif_err("%s\n", vnet->iod->name); - - atomic_dec(&vnet->iod->opened); - netif_stop_queue(ndev); - skb_queue_purge(&vnet->iod->sk_rx_q); - return 0; -} - -static int vnet_xmit(struct sk_buff *skb, struct net_device *ndev) -{ - struct vnet *vnet = netdev_priv(ndev); - struct io_device *iod = vnet->iod; - struct link_device *ld = get_current_link(iod); - struct sk_buff *skb_new; - int ret; - unsigned headroom = 0; - unsigned tailroom = 0; - unsigned long tx_bytes = skb->len; - struct iphdr *ip_header = NULL; - struct sipc5_frame_data frm; - - /* When use `handover' with Network Bridge, - * user -> bridge device(rmnet0) -> real rmnet(xxxx_rmnet0) -> here. - * bridge device is ethernet device unlike xxxx_rmnet(net device). - * We remove the an ethernet header of skb before using skb->len, - * because bridge device added an ethernet header to skb. - */ - if (iod->use_handover) { - if (iod->id >= PS_DATA_CH_0 && iod->id <= PS_DATA_CH_LAST) - skb_pull(skb, sizeof(struct ethhdr)); - } - - headroom = tx_build_link_header(&frm, iod, ld, skb->len); - - /* ip loop-back */ - ip_header = (struct iphdr *)skb->data; - if (iod->msd->loopback_ipaddr && - ip_header->daddr == iod->msd->loopback_ipaddr) { - swap(ip_header->saddr, ip_header->daddr); - frm.ch_id = DATA_LOOPBACK_CHANNEL; - frm.hdr[SIPC5_CH_ID_OFFSET] = DATA_LOOPBACK_CHANNEL; - } - - if (ld->aligned) - tailroom = sipc5_calc_padding_size(frm.len); - - if (skb_headroom(skb) < headroom || skb_tailroom(skb) < tailroom) { - mif_debug("%s: skb_copy_expand needed\n", iod->name); - skb_new = skb_copy_expand(skb, headroom, tailroom, GFP_ATOMIC); - /* skb_copy_expand success or not, free old skb from caller */ - dev_kfree_skb_any(skb); - if (!skb_new) { - mif_info("%s: ERR! skb_copy_expand fail\n", iod->name); - return NETDEV_TX_BUSY; - } - } else { - skb_new = skb; - } - - memcpy(skb_push(skb_new, headroom), frm.hdr, headroom); - if (tailroom) - skb_put(skb_new, tailroom); - - skbpriv(skb_new)->iod = iod; - skbpriv(skb_new)->ld = ld; - - ret = ld->send(ld, iod, skb_new); - if (ret < 0) { - netif_stop_queue(ndev); - mif_info("%s: ERR! ld->send fail (err %d)\n", iod->name, ret); - return NETDEV_TX_BUSY; - } - - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += tx_bytes; - - return NETDEV_TX_OK; -} - -static struct net_device_ops vnet_ops = { - .ndo_open = vnet_open, - .ndo_stop = vnet_stop, - .ndo_start_xmit = vnet_xmit, -}; - -static void vnet_setup(struct net_device *ndev) -{ - ndev->netdev_ops = &vnet_ops; - ndev->type = ARPHRD_PPP; - ndev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; - ndev->addr_len = 0; - ndev->hard_header_len = 0; - ndev->tx_queue_len = 1000; - ndev->mtu = ETH_DATA_LEN; - ndev->watchdog_timeo = 5 * HZ; -} - -static void vnet_setup_ether(struct net_device *ndev) -{ - ndev->netdev_ops = &vnet_ops; - ndev->type = ARPHRD_ETHER; - ndev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST | IFF_SLAVE; - ndev->addr_len = ETH_ALEN; - random_ether_addr(ndev->dev_addr); - ndev->hard_header_len = 0; - ndev->tx_queue_len = 1000; - ndev->mtu = ETH_DATA_LEN; - ndev->watchdog_timeo = 5 * HZ; -} - -int sipc5_init_io_device(struct io_device *iod) -{ - int ret = 0; - struct vnet *vnet; - - /* Get modem state from modem control device */ - iod->modem_state_changed = io_dev_modem_state_changed; - - iod->sim_state_changed = io_dev_sim_state_changed; - - /* Get data from link device */ - mif_debug("%s: SIPC version = %d\n", iod->name, iod->ipc_version); - iod->recv = io_dev_recv_data_from_link_dev; - iod->recv_skb = io_dev_recv_skb_from_link_dev; - - /* Register misc or net device */ - switch (iod->io_typ) { - case IODEV_MISC: - init_waitqueue_head(&iod->wq); - skb_queue_head_init(&iod->sk_rx_q); - - iod->miscdev.minor = MISC_DYNAMIC_MINOR; - iod->miscdev.name = iod->name; - iod->miscdev.fops = &misc_io_fops; - - ret = misc_register(&iod->miscdev); - if (ret) - mif_info("%s: ERR! misc_register failed\n", iod->name); - - break; - - case IODEV_NET: - skb_queue_head_init(&iod->sk_rx_q); - if (iod->use_handover) - iod->ndev = alloc_netdev(0, iod->name, - vnet_setup_ether); - else - iod->ndev = alloc_netdev(0, iod->name, vnet_setup); - - if (!iod->ndev) { - mif_info("%s: ERR! alloc_netdev fail\n", iod->name); - return -ENOMEM; - } - - ret = register_netdev(iod->ndev); - if (ret) { - mif_info("%s: ERR! register_netdev fail\n", iod->name); - free_netdev(iod->ndev); - } - - mif_debug("iod 0x%p\n", iod); - vnet = netdev_priv(iod->ndev); - mif_debug("vnet 0x%p\n", vnet); - vnet->iod = iod; - - break; - - case IODEV_DUMMY: - skb_queue_head_init(&iod->sk_rx_q); - - iod->miscdev.minor = MISC_DYNAMIC_MINOR; - iod->miscdev.name = iod->name; - iod->miscdev.fops = &misc_io_fops; - - ret = misc_register(&iod->miscdev); - if (ret) - mif_info("%s: ERR! misc_register fail\n", iod->name); - ret = device_create_file(iod->miscdev.this_device, - &attr_waketime); - if (ret) - mif_info("%s: ERR! device_create_file fail\n", - iod->name); - ret = device_create_file(iod->miscdev.this_device, - &attr_loopback); - if (ret) - mif_err("failed to create `loopback file' : %s\n", - iod->name); - ret = device_create_file(iod->miscdev.this_device, - &attr_txlink); - if (ret) - mif_err("failed to create `txlink file' : %s\n", - iod->name); - break; - - default: - mif_info("%s: ERR! wrong io_type %d\n", iod->name, iod->io_typ); - return -EINVAL; - } - - return ret; -} - diff --git a/drivers/misc/modem_if/sipc5_modem.c b/drivers/misc/modem_if/sipc5_modem.c deleted file mode 100644 index f7662df189c..00000000000 --- a/drivers/misc/modem_if/sipc5_modem.c +++ /dev/null @@ -1,389 +0,0 @@ -/* linux/drivers/modem/modem.c - * - * Copyright (C) 2010 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/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/miscdevice.h> -#include <linux/if_arp.h> - -#include <linux/uaccess.h> -#include <linux/fs.h> -#include <linux/io.h> -#include <linux/wait.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#ifdef CONFIG_HAS_WAKELOCK -#include <linux/wakelock.h> -#endif -#include <linux/rbtree.h> - -#include <linux/platform_data/modem.h> -#include "modem_prj.h" -#include "modem_variation.h" -#include "modem_utils.h" - -#define FMT_WAKE_TIME (HZ/2) -#define RAW_WAKE_TIME (HZ*6) - -static struct modem_shared *create_modem_shared_data(void) -{ - struct modem_shared *msd; - int size = MAX_MIF_BUFF_SIZE; - - msd = kzalloc(sizeof(struct modem_shared), GFP_KERNEL); - if (!msd) - return NULL; - - /* initialize link device list */ - INIT_LIST_HEAD(&msd->link_dev_list); - - /* initialize tree of io devices */ - msd->iodevs_tree_chan = RB_ROOT; - msd->iodevs_tree_fmt = RB_ROOT; - - msd->storage.cnt = 0; - msd->storage.addr = kzalloc(MAX_MIF_BUFF_SIZE + - (MAX_MIF_SEPA_SIZE * 2), GFP_KERNEL); - if (!msd->storage.addr) { - mif_err("IPC logger buff alloc failed!!\n"); - return NULL; - } - memset(msd->storage.addr, 0, size + (MAX_MIF_SEPA_SIZE * 2)); - memcpy(msd->storage.addr, MIF_SEPARATOR, MAX_MIF_SEPA_SIZE); - msd->storage.addr += MAX_MIF_SEPA_SIZE; - memcpy(msd->storage.addr, &size, MAX_MIF_SEPA_SIZE); - msd->storage.addr += MAX_MIF_SEPA_SIZE; - spin_lock_init(&msd->lock); - - return msd; -} - -static struct modem_ctl *create_modemctl_device(struct platform_device *pdev, - struct modem_shared *msd) -{ - int ret = 0; - struct modem_data *pdata; - struct modem_ctl *modemctl; - struct device *dev = &pdev->dev; - - /* create modem control device */ - modemctl = kzalloc(sizeof(struct modem_ctl), GFP_KERNEL); - if (!modemctl) - return NULL; - - modemctl->msd = msd; - modemctl->dev = dev; - modemctl->phone_state = STATE_OFFLINE; - - pdata = pdev->dev.platform_data; - modemctl->mdm_data = pdata; - modemctl->name = pdata->name; - - /* init modemctl device for getting modemctl operations */ - ret = call_modem_init_func(modemctl, pdata); - if (ret) { - kfree(modemctl); - return NULL; - } - - mif_info("%s is created!!!\n", pdata->name); - - return modemctl; -} - -static struct io_device *create_io_device(struct modem_io_t *io_t, - struct modem_shared *msd, struct modem_ctl *modemctl, - struct modem_data *pdata) -{ - int ret = 0; - struct io_device *iod = NULL; - - iod = kzalloc(sizeof(struct io_device), GFP_KERNEL); - if (!iod) { - mif_err("iod == NULL\n"); - return NULL; - } - - RB_CLEAR_NODE(&iod->node_chan); - RB_CLEAR_NODE(&iod->node_fmt); - - iod->name = io_t->name; - iod->id = io_t->id; - iod->format = io_t->format; - iod->io_typ = io_t->io_type; - iod->link_types = io_t->links; - iod->net_typ = pdata->modem_net; - iod->use_handover = pdata->use_handover; - iod->ipc_version = pdata->ipc_version; - atomic_set(&iod->opened, 0); - - /* link between io device and modem control */ - iod->mc = modemctl; - if (iod->format == IPC_FMT) - modemctl->iod = iod; - if (iod->format == IPC_BOOT) { - modemctl->bootd = iod; - mif_info("Bood device = %s\n", iod->name); - } - - /* link between io device and modem shared */ - iod->msd = msd; - - /* add iod to rb_tree */ - if (iod->format != IPC_RAW) - insert_iod_with_format(msd, iod->format, iod); - - if (sipc5_is_not_reserved_channel(iod->id)) - insert_iod_with_channel(msd, iod->id, iod); - - /* register misc device or net device */ - ret = sipc5_init_io_device(iod); - if (ret) { - kfree(iod); - mif_err("sipc5_init_io_device fail (%d)\n", ret); - return NULL; - } - - mif_debug("%s is created!!!\n", iod->name); - return iod; -} - -static int attach_devices(struct io_device *iod, enum modem_link tx_link) -{ - struct modem_shared *msd = iod->msd; - struct link_device *ld; - unsigned ch; - - /* find link type for this io device */ - list_for_each_entry(ld, &msd->link_dev_list, list) { - if (IS_CONNECTED(iod, ld)) { - /* The count 1 bits of iod->link_types is count - * of link devices of this iod. - * If use one link device, - * or, 2+ link devices and this link is tx_link, - * set iod's link device with ld - */ - if ((countbits(iod->link_types) <= 1) || - (tx_link == ld->link_type)) { - mif_debug("set %s->%s\n", iod->name, ld->name); - set_current_link(iod, ld); - } - } - } - - /* if use rx dynamic switch, set tx_link at modem_io_t of - * board-*-modems.c - */ - if (!get_current_link(iod)) { - mif_err("%s->link == NULL\n", iod->name); - BUG(); - } - -#ifdef CONFIG_HAS_WAKELOCK - switch (iod->format) { - case IPC_FMT: - wake_lock_init(&iod->wakelock, WAKE_LOCK_SUSPEND, iod->name); - iod->waketime = FMT_WAKE_TIME; - break; - - case IPC_RAW: - wake_lock_init(&iod->wakelock, WAKE_LOCK_SUSPEND, iod->name); - iod->waketime = RAW_WAKE_TIME; - break; - - case IPC_RFS: - wake_lock_init(&iod->wakelock, WAKE_LOCK_SUSPEND, iod->name); - iod->waketime = RAW_WAKE_TIME; - break; - - case IPC_MULTI_RAW: - wake_lock_init(&iod->wakelock, WAKE_LOCK_SUSPEND, iod->name); - iod->waketime = RAW_WAKE_TIME; - break; - - case IPC_BOOT: - wake_lock_init(&iod->wakelock, WAKE_LOCK_SUSPEND, iod->name); - iod->waketime = RAW_WAKE_TIME; - break; - - default: - break; - } -#endif - - return 0; -} - -static int modem_probe(struct platform_device *pdev) -{ - int i; - struct modem_data *pdata = pdev->dev.platform_data; - struct modem_shared *msd = NULL; - struct modem_ctl *modemctl = NULL; - struct io_device *iod[pdata->num_iodevs]; - struct link_device *ld; - - mif_err("%s\n", pdev->name); - memset(iod, 0, sizeof(iod)); - - msd = create_modem_shared_data(); - if (!msd) { - mif_err("msd == NULL\n"); - goto err_free_modemctl; - } - - modemctl = create_modemctl_device(pdev, msd); - if (!modemctl) { - mif_err("modemctl == NULL\n"); - goto err_free_modemctl; - } - - /* create link device */ - /* support multi-link device */ - for (i = 0; i < LINKDEV_MAX ; i++) { - /* find matching link type */ - if (pdata->link_types & LINKTYPE(i)) { - ld = call_link_init_func(pdev, i); - if (!ld) - goto err_free_modemctl; - - mif_err("link created: %s\n", ld->name); - ld->link_type = i; - ld->mc = modemctl; - ld->msd = msd; - list_add(&ld->list, &msd->link_dev_list); - } - } - - /* create io deivces and connect to modemctl device */ - for (i = 0; i < pdata->num_iodevs; i++) { - iod[i] = create_io_device(&pdata->iodevs[i], msd, modemctl, - pdata); - if (!iod[i]) { - mif_err("iod[%d] == NULL\n", i); - goto err_free_modemctl; - } - - attach_devices(iod[i], pdata->iodevs[i].tx_link); - } - - platform_set_drvdata(pdev, modemctl); - - mif_err("Complete!!!\n"); - - return 0; - -err_free_modemctl: - for (i = 0; i < pdata->num_iodevs; i++) - if (iod[i] != NULL) - kfree(iod[i]); - - if (modemctl != NULL) - kfree(modemctl); - - if (msd != NULL) - kfree(msd); - - return -ENOMEM; -} - -static void modem_shutdown(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct modem_ctl *mc = dev_get_drvdata(dev); - struct utc_time utc; - - mc->ops.modem_off(mc); - mc->phone_state = STATE_OFFLINE; - - get_utc_time(&utc); - mif_info("%s: at [%02d:%02d:%02d.%03d]\n", - mc->name, utc.hour, utc.min, utc.sec, utc.msec); -} - -static int modem_suspend(struct device *pdev) -{ -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - struct utc_time utc; -#endif - -#ifndef CONFIG_LINK_DEVICE_HSIC - struct modem_ctl *mc = dev_get_drvdata(pdev); - - if (mc->gpio_pda_active) { - gpio_set_value(mc->gpio_pda_active, 0); -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - get_utc_time(&utc); - mif_info("%s: at [%02d:%02d:%02d.%03d]\n", - mc->name, utc.hour, utc.min, utc.sec, utc.msec); -#endif - } -#endif - - return 0; -} - -static int modem_resume(struct device *pdev) -{ -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - struct utc_time utc; -#endif - -#ifndef CONFIG_LINK_DEVICE_HSIC - struct modem_ctl *mc = dev_get_drvdata(pdev); - - if (mc->gpio_pda_active) { - gpio_set_value(mc->gpio_pda_active, 1); -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP - get_utc_time(&utc); - mif_info("%s: at [%02d:%02d:%02d.%03d]\n", - mc->name, utc.hour, utc.min, utc.sec, utc.msec); -#endif - } -#endif - - return 0; -} - -static const struct dev_pm_ops modem_pm_ops = { - .suspend = modem_suspend, - .resume = modem_resume, -}; - -static struct platform_driver modem_driver = { - .probe = modem_probe, - .shutdown = modem_shutdown, - .driver = { - .name = "mif_sipc5", - .pm = &modem_pm_ops, - }, -}; - -static int __init modem_init(void) -{ - return platform_driver_register(&modem_driver); -} - -module_init(modem_init); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Samsung Modem Interface Driver"); diff --git a/drivers/misc/modem_if/sipc4_io_device.c b/drivers/misc/modem_if/tizen_io_device.c index aa8e4e99d9d..448e247a1f5 100644 --- a/drivers/misc/modem_if/sipc4_io_device.c +++ b/drivers/misc/modem_if/tizen_io_device.c @@ -25,12 +25,11 @@ #include <linux/if_ether.h> #include <linux/etherdevice.h> #include <linux/device.h> -#include <linux/module.h> -#include <linux/platform_data/modem.h> #ifdef CONFIG_LINK_DEVICE_C2C #include <linux/platform_data/c2c.h> #endif +#include "modem_tizen.h" #include "modem_prj.h" #include "modem_utils.h" @@ -118,20 +117,17 @@ static struct device_attribute attr_loopback = static int get_header_size(struct io_device *iod) { switch (iod->format) { - case IPC_FMT: - return sizeof(struct fmt_hdr); - +#if 0 /*for tizen modem*/ case IPC_RAW: case IPC_MULTI_RAW: return sizeof(struct raw_hdr); - - case IPC_RFS: - return sizeof(struct rfs_hdr); - +#endif case IPC_BOOT: /* minimum size for transaction align */ return 4; + case IPC_BYPASS: + case IPC_RFS: case IPC_RAMDUMP: default: return 0; @@ -140,70 +136,15 @@ static int get_header_size(struct io_device *iod) static int get_hdlc_size(struct io_device *iod, char *buf) { - struct fmt_hdr *fmt_header; - struct raw_hdr *raw_header; - struct rfs_hdr *rfs_header; - mif_debug("buf : %02x %02x %02x (%d)\n", *buf, *(buf + 1), *(buf + 2), __LINE__); - - switch (iod->format) { - case IPC_FMT: - fmt_header = (struct fmt_hdr *)buf; - if (iod->mc->mdm_data->ipc_version == SIPC_VER_42) - return fmt_header->len & 0x3FFF; - else - return fmt_header->len; - case IPC_RAW: - case IPC_MULTI_RAW: - raw_header = (struct raw_hdr *)buf; - return raw_header->len; - case IPC_RFS: - rfs_header = (struct rfs_hdr *)buf; - return rfs_header->len; - default: - break; - } return 0; } static void *get_header(struct io_device *iod, size_t count, char *frame_header_buf) { - struct fmt_hdr *fmt_h; - struct raw_hdr *raw_h; - struct rfs_hdr *rfs_h; - - switch (iod->format) { - case IPC_FMT: - fmt_h = (struct fmt_hdr *)frame_header_buf; - - fmt_h->len = count + sizeof(struct fmt_hdr); - fmt_h->control = 0; - - return (void *)frame_header_buf; - - case IPC_RAW: - case IPC_MULTI_RAW: - raw_h = (struct raw_hdr *)frame_header_buf; - - raw_h->len = count + sizeof(struct raw_hdr); - raw_h->channel = iod->id & 0x1F; - raw_h->control = 0; - - return (void *)frame_header_buf; - - case IPC_RFS: - rfs_h = (struct rfs_hdr *)frame_header_buf; - - rfs_h->len = count + sizeof(struct raw_hdr); - rfs_h->id = iod->id; - - return (void *)frame_header_buf; - - default: - return 0; - } + return NULL; } static inline int calc_padding_size(struct io_device *iod, @@ -253,14 +194,13 @@ static int rx_hdlc_head_check(struct io_device *iod, struct link_device *ld, /* debug print */ switch (iod->format) { - case IPC_FMT: - case IPC_RAW: - case IPC_MULTI_RAW: + case IPC_BYPASS: + case IPC_PDP0: + case IPC_PDP1: case IPC_RFS: /* TODO: print buf... */ break; - case IPC_CMD: case IPC_BOOT: case IPC_RAMDUMP: default: @@ -326,17 +266,6 @@ static int rx_hdlc_data_check(struct io_device *iod, struct link_device *ld, alloc_size = min(data_size, MAX_RXDATA_SIZE); alloc_size = min(alloc_size, rest_len); - /* exceptional case for RFS channel - * make skb for header info first - */ - if (iod->format == IPC_RFS && !hdr->frag_len) { - skb = rx_alloc_skb(head_size, iod, ld); - if (unlikely(!skb)) - return -ENOMEM; - memcpy(skb_put(skb, head_size), hdr->hdr, head_size); - rx_iodev_skb(skb); - } - /* allocate first packet for data, when its size exceed * MAX_RXDATA_SIZE, this packet will split to * multiple packets @@ -549,7 +478,7 @@ static int rx_multi_fmt_frame_sipc42(struct sk_buff *rx_skb) static int rx_iodev_skb_raw(struct sk_buff *skb) { int err = 0; - struct io_device *iod = skbpriv(skb)->real_iod; + struct io_device *iod = skbpriv(skb)->iod; struct net_device *ndev = NULL; struct iphdr *ip_header = NULL; struct ethhdr *ehdr = NULL; @@ -574,6 +503,7 @@ static int rx_iodev_skb_raw(struct sk_buff *skb) return 0; case IODEV_NET: + pr_skb("rx_iodev_skb_raw", skb); ndev = iod->ndev; if (!ndev) { mif_err("<%s> ndev == NULL", @@ -676,16 +606,14 @@ static int rx_iodev_skb(struct sk_buff *skb) struct io_device *iod = skbpriv(skb)->iod; switch (iod->format) { - case IPC_MULTI_RAW: - return rx_multipdp(skb); + case IPC_PDP0: + case IPC_PDP1: + skb_queue_tail(&iod->sk_rx_q, skb); + mif_debug("sk_rx_qlen:%d\n", iod->sk_rx_q.qlen); - case IPC_FMT: - if (iod->mc->mdm_data->ipc_version == SIPC_VER_42) - return rx_multi_fmt_frame_sipc42(skb); - else - return rx_multi_fmt_frame(skb); + schedule_delayed_work(&iod->rx_work, 0); + return 0; - case IPC_RFS: default: skb_queue_tail(&iod->sk_rx_q, skb); mif_debug("wake up wq of %s\n", iod->name); @@ -878,26 +806,23 @@ static int io_dev_recv_data_from_link_dev(struct io_device *iod, unsigned int alloc_size, rest_len; char *cur; - - /* check the iod(except IODEV_DUMMY) is open? - * if the iod is MULTIPDP, check this data on rx_iodev_skb_raw() - * because, we cannot know the channel no in here. - */ - /* - if (iod->io_typ != IODEV_DUMMY && atomic_read(&iod->opened) == 0) { - mif_err("<%s> is not opened.\n", iod->name); - pr_buffer("drop packet", data, len, 16u); - return -ENOENT; - } - */ - switch (iod->format) { - case IPC_RFS: -#ifdef CONFIG_IPC_CMC22x_OLD_RFS - err = rx_rfs_packet(iod, ld, data, len); - return err; + case IPC_PDP0: + case IPC_PDP1: + if (iod->waketime) +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_timeout(&iod->wakelock, iod->waketime); +#else + pm_wakeup_event(iod->miscdev.this_device, + jiffies_to_msecs(iod->waketime)); #endif - case IPC_FMT: + err = rx_iodev_skb((struct sk_buff *)data); + if (err < 0) + mif_err("fail process RX ether packet\n"); + return err; + + case IPC_BYPASS: + case IPC_RFS: /* alloc 3.5K a page.. in case of BYPASS,RFS */ /* should be smaller than user alloc size */ if (len >= MAX_RXDATA_SIZE) @@ -923,24 +848,6 @@ static int io_dev_recv_data_from_link_dev(struct io_device *iod, } wake_up(&iod->wq); return len; - case IPC_RAW: - case IPC_MULTI_RAW: - if (iod->waketime) -#ifdef CONFIG_HAS_WAKELOCK - wake_lock_timeout(&iod->wakelock, iod->waketime); -#else - pm_wakeup_event(iod->miscdev.this_device, - jiffies_to_msecs(iod->waketime)); -#endif - err = rx_hdlc_packet(iod, ld, data, len); - if (err < 0) - mif_err("fail process HDLC frame\n"); - return err; - - case IPC_CMD: - /* TODO- handle flow control command from CP */ - return 0; - case IPC_BOOT: case IPC_RAMDUMP: /* save packet to sk_buff */ @@ -1086,7 +993,7 @@ static unsigned int misc_poll(struct file *filp, struct poll_table_struct *wait) (iod->mc->phone_state == STATE_CRASH_EXIT) || (iod->mc->phone_state == STATE_NV_REBUILDING) || (iod->mc->sim_state.changed)) { - if (iod->format == IPC_RAW) { + if (iod->format != IPC_BYPASS) { msleep(20); return 0; } @@ -1104,7 +1011,6 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) char cpinfo_buf[530] = "CP Crash "; unsigned long size; int ret; - char str[TASK_COMM_LEN]; mif_debug("cmd = 0x%x\n", cmd); @@ -1142,13 +1048,10 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) (p_state == STATE_CRASH_EXIT)) { mif_err("<%s> send err state : %d\n", iod->name, p_state); - } else if (iod->mc->sim_state.changed && - !strcmp(get_task_comm(str, get_current()), "rild")) { + } else if (iod->mc->sim_state.changed) { int s_state = iod->mc->sim_state.online ? STATE_SIM_ATTACH : STATE_SIM_DETACH; iod->mc->sim_state.changed = false; - - mif_info("SIM states (%d) to %s\n", s_state, str); return s_state; } else if (p_state == STATE_NV_REBUILDING) { mif_info("send nv rebuild state : %d\n", @@ -1157,6 +1060,7 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } return p_state; +#if 0 /*for tizen modem*/ case IOCTL_MODEM_PROTOCOL_SUSPEND: mif_info("misc_ioctl : IOCTL_MODEM_PROTOCOL_SUSPEND\n"); @@ -1174,6 +1078,7 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) iodevs_for_each(iod->msd, iodev_netif_wake, 0); return 0; +#endif case IOCTL_MODEM_DUMP_START: mif_err("misc_ioctl : IOCTL_MODEM_DUMP_START\n"); @@ -1226,6 +1131,11 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) #endif return -EINVAL; + case IOCTL_CG_DATA_SEND: + mif_info("misc_ioctl : IOCTL_CG_DATA_SEND, arg = %lu\n", arg); + send_cg_data(ld, iod, arg); + return 0; + default: /* If you need to handle the ioctl for specific link device, * then assign the link ioctl handler to ld->ioctl @@ -1266,6 +1176,8 @@ static ssize_t misc_write(struct file *filp, const char __user *buf, } switch (iod->format) { + case IPC_BYPASS: + case IPC_RFS: case IPC_BOOT: case IPC_RAMDUMP: if (copy_from_user(skb_put(skb, count), buf, count) != 0) { @@ -1274,17 +1186,6 @@ static ssize_t misc_write(struct file *filp, const char __user *buf, } break; - case IPC_RFS: - memcpy(skb_put(skb, SIZE_OF_HDLC_START), hdlc_start, - SIZE_OF_HDLC_START); - if (copy_from_user(skb_put(skb, count), buf, count) != 0) { - dev_kfree_skb_any(skb); - return -EFAULT; - } - memcpy(skb_put(skb, SIZE_OF_HDLC_END), hdlc_end, - SIZE_OF_HDLC_END); - break; - default: memcpy(skb_put(skb, SIZE_OF_HDLC_START), hdlc_start, SIZE_OF_HDLC_START); @@ -1302,31 +1203,6 @@ static ssize_t misc_write(struct file *filp, const char __user *buf, skb_put(skb, calc_padding_size(iod, ld, skb->len)); -#if 0 - if (iod->format == IPC_FMT) { - mif_err("\n<%s> Tx HDLC FMT frame (len %d)\n", - iod->name, skb->len); - print_sipc4_hdlc_fmt_frame(skb->data); - mif_err("\n"); - } -#endif -#if 0 - if (iod->format == IPC_RAW) { - mif_err("\n<%s> Tx HDLC RAW frame (len %d)\n", - iod->name, skb->len); - mif_print_data(skb->data, (skb->len < 64 ? skb->len : 64)); - mif_err("\n"); - } -#endif -#if 0 - if (iod->format == IPC_RFS) { - mif_err("\n<%s> Tx HDLC RFS frame (len %d)\n", - iod->name, skb->len); - mif_print_data(skb->data, (skb->len < 64 ? skb->len : 64)); - mif_err("\n"); - } -#endif - /* send data with sk_buff, link device will put sk_buff * into the specific sk_buff_q and run work-q to send data */ @@ -1346,10 +1222,6 @@ static ssize_t misc_write(struct file *filp, const char __user *buf, "count=%d, tx_size=%d, return_size=%d", iod->name, iod->format, count, tx_size, err); - /* Temporaly enable t he RFS log for debugging IPC RX pedding issue */ - if (iod->format == IPC_RFS) - mif_info("write rfs size = %d\n", count); - return count; } @@ -1425,7 +1297,7 @@ static ssize_t misc_read(struct file *filp, char *buf, size_t count, dev_kfree_skb_any(skb); return -EFAULT; } - if (iod->format == IPC_FMT) + if (iod->format == IPC_BYPASS) mif_debug("copied %d bytes to user\n", pktsize); dev_kfree_skb_any(skb); @@ -1511,6 +1383,12 @@ static int vnet_xmit(struct sk_buff *skb, struct net_device *ndev) struct raw_hdr hd; struct iphdr *ip_header = NULL; + /* For pdp-acm */ + if (iod->io_typ == IODEV_NET) { + skb_new = skb; + goto skip_sipc; + } + /* When use `handover' with Network Bridge, * user -> TCP/IP(kernel) -> bridge device -> TCP/IP(kernel) -> this. * @@ -1554,6 +1432,7 @@ static int vnet_xmit(struct sk_buff *skb, struct net_device *ndev) memcpy(skb_put(skb_new, sizeof(hdlc_end)), hdlc_end, sizeof(hdlc_end)); skb_put(skb_new, calc_padding_size(iod, ld, skb_new->len)); +skip_sipc: skbpriv(skb_new)->iod = iod; skbpriv(skb_new)->ld = ld; @@ -1634,6 +1513,7 @@ int sipc4_init_io_device(struct io_device *iod) case IODEV_NET: skb_queue_head_init(&iod->sk_rx_q); + INIT_DELAYED_WORK(&iod->rx_work, rx_iodev_work); if (iod->use_handover) iod->ndev = alloc_netdev(0, iod->name, vnet_setup_ether); @@ -1653,7 +1533,6 @@ int sipc4_init_io_device(struct io_device *iod) vnet = netdev_priv(iod->ndev); mif_debug("(vnet:0x%p)\n", vnet); vnet->iod = iod; - break; case IODEV_DUMMY: @@ -1668,11 +1547,13 @@ int sipc4_init_io_device(struct io_device *iod) if (ret) mif_err("failed to register misc io device : %s\n", iod->name); + ret = device_create_file(iod->miscdev.this_device, &attr_waketime); if (ret) mif_err("failed to create `waketime' file : %s\n", iod->name); + ret = device_create_file(iod->miscdev.this_device, &attr_loopback); if (ret) diff --git a/drivers/misc/modem_if/sipc4_modem.c b/drivers/misc/modem_if/tizen_modem.c index e1169c798cb..1d717c2486d 100644 --- a/drivers/misc/modem_if/sipc4_modem.c +++ b/drivers/misc/modem_if/tizen_modem.c @@ -33,11 +33,10 @@ #ifdef CONFIG_HAS_WAKELOCK #include <linux/wakelock.h> #endif -#include <linux/rbtree.h> #include <linux/of.h> #include <linux/of_gpio.h> -#include <linux/platform_data/modem.h> +#include "modem_tizen.h" #include "modem_prj.h" #include "modem_variation.h" #include "modem_utils.h" @@ -46,88 +45,50 @@ #define RFS_WAKE_TIME (HZ*3) #define RAW_WAKE_TIME (HZ*6) -/* pdp for SLP, rmnet for others */ -#define NET_DEVICE_NAME(n) "pdp"#n - /* umts target platform data */ static struct modem_io_t umts_io_devices[] = { [0] = { .name = "umts_ipc0", .id = 0x1, - .format = IPC_FMT, + .format = IPC_BYPASS, .io_type = IODEV_MISC, .links = LINKTYPE(LINKDEV_HSIC), }, [1] = { - .name = "umts_rfs0", - .id = 0x41, - .format = IPC_RFS, - .io_type = IODEV_MISC, - .links = LINKTYPE(LINKDEV_HSIC), - }, - [2] = { .name = "umts_boot0", .id = 0x0, .format = IPC_BOOT, .io_type = IODEV_MISC, .links = LINKTYPE(LINKDEV_HSIC), }, - [3] = { - .name = "multipdp", - .id = 0x1, - .format = IPC_MULTI_RAW, - .io_type = IODEV_DUMMY, - .links = LINKTYPE(LINKDEV_HSIC), - }, - [4] = { - .name = NET_DEVICE_NAME(0), + [2] = { + .name = "pdp0", .id = 0x2A, - .format = IPC_RAW, + .format = IPC_PDP0, .io_type = IODEV_NET, .links = LINKTYPE(LINKDEV_HSIC), }, - [5] = { - .name = NET_DEVICE_NAME(1) , + [3] = { + .name = "pdp1", .id = 0x2B, - .format = IPC_RAW, - .io_type = IODEV_NET, - .links = LINKTYPE(LINKDEV_HSIC), - }, - [6] = { - .name = NET_DEVICE_NAME(2), - .id = 0x2C, - .format = IPC_RAW, + .format = IPC_PDP1, .io_type = IODEV_NET, .links = LINKTYPE(LINKDEV_HSIC), }, - [7] = { - .name = "umts_router", - .id = 0x39, - .format = IPC_RAW, - .io_type = IODEV_MISC, - .links = LINKTYPE(LINKDEV_HSIC), - }, - [8] = { - .name = "umts_csd", - .id = 0x21, - .format = IPC_RAW, + [4] = { + .name = "umts_rfs0", + .id = 0x41, + .format = IPC_RFS, .io_type = IODEV_MISC, .links = LINKTYPE(LINKDEV_HSIC), }, - [9] = { + [5] = { .name = "umts_ramdump0", .id = 0x0, .format = IPC_RAMDUMP, .io_type = IODEV_MISC, .links = LINKTYPE(LINKDEV_HSIC), }, - [10] = { - .name = "umts_loopback0", - .id = 0x3f, - .format = IPC_RAW, - .io_type = IODEV_MISC, - .links = LINKTYPE(LINKDEV_HSIC), - }, }; static struct modem_shared *create_modem_shared_data(void) @@ -168,6 +129,8 @@ static struct modem_ctl *create_modemctl_device(struct platform_device *pdev, struct modem_ctl *modemctl; struct device *dev = &pdev->dev; + mif_info("START!\n"); + /* create modem control device */ modemctl = kzalloc(sizeof(struct modem_ctl), GFP_KERNEL); if (!modemctl) @@ -200,6 +163,7 @@ static struct io_device *create_io_device(struct modem_io_t *io_t, int ret = 0; struct io_device *iod = NULL; + mif_info("start!\n"); iod = kzalloc(sizeof(struct io_device), GFP_KERNEL); if (!iod) { mif_err("iod == NULL\n"); @@ -220,8 +184,10 @@ static struct io_device *create_io_device(struct modem_io_t *io_t, atomic_set(&iod->opened, 0); /* link between io device and modem control */ + mif_info("name : %s, format : %d, type : %d\n", + iod->name, iod->format, iod->io_typ); iod->mc = modemctl; - if (iod->format == IPC_FMT) + if (iod->format == IPC_BYPASS) modemctl->iod = iod; if (iod->format == IPC_BOOT) { modemctl->bootd = iod; @@ -232,7 +198,7 @@ static struct io_device *create_io_device(struct modem_io_t *io_t, iod->msd = msd; /* add iod to rb_tree */ - if (iod->format != IPC_RAW) + if (iod->format != IPC_PDP0 && iod->format != IPC_PDP1) insert_iod_with_format(msd, iod->format, iod); if (sipc4_is_not_reserved_channel(iod->id)) @@ -255,6 +221,7 @@ static int attach_devices(struct io_device *iod, enum modem_link tx_link) struct modem_shared *msd = iod->msd; struct link_device *ld; + mif_info("start!\n"); /* find link type for this io device */ list_for_each_entry(ld, &msd->link_dev_list, list) { if (IS_CONNECTED(iod, ld)) { @@ -266,12 +233,12 @@ static int attach_devices(struct io_device *iod, enum modem_link tx_link) */ if ((countbits(iod->link_types) <= 1) || (tx_link == ld->link_type)) { - mif_debug("set %s->%s\n", iod->name, ld->name); + mif_info("set %s->%s\n", iod->name, ld->name); set_current_link(iod, ld); if (iod->ipc_version == SIPC_VER_42) { - if (iod->format == IPC_FMT) { + if (iod->format == IPC_BYPASS) { int ch = iod->id & 0x03; ld->fmt_iods[ch] = iod; } @@ -289,32 +256,39 @@ static int attach_devices(struct io_device *iod, enum modem_link tx_link) } switch (iod->format) { - case IPC_FMT: + case IPC_BYPASS: #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&iod->wakelock, WAKE_LOCK_SUSPEND, iod->name); #else device_init_wakeup(iod->miscdev.this_device, true); #endif - iod->waketime = FMT_WAKE_TIME; + iod->waketime = 3 * HZ; break; - case IPC_RFS: + case IPC_PDP0: #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&iod->wakelock, WAKE_LOCK_SUSPEND, iod->name); -#else - device_init_wakeup(iod->miscdev.this_device, true); #endif - iod->waketime = RFS_WAKE_TIME; + iod->waketime = RAW_WAKE_TIME; + + break; + + case IPC_PDP1: +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_init(&iod->wakelock, WAKE_LOCK_SUSPEND, iod->name); +#endif + iod->waketime = RAW_WAKE_TIME; break; - case IPC_MULTI_RAW: + case IPC_RFS: #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&iod->wakelock, WAKE_LOCK_SUSPEND, iod->name); #else device_init_wakeup(iod->miscdev.this_device, true); #endif - iod->waketime = RAW_WAKE_TIME; + iod->waketime = RFS_WAKE_TIME; break; + case IPC_BOOT: #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&iod->wakelock, WAKE_LOCK_SUSPEND, iod->name); @@ -445,7 +419,7 @@ dt_parse_err: return ERR_PTR(err); } -static int modem_probe(struct platform_device *pdev) +static int __init modem_probe(struct platform_device *pdev) { int i; struct modem_data *pdata = pdev->dev.platform_data; @@ -463,7 +437,6 @@ static int modem_probe(struct platform_device *pdev) goto err_free_modemctl; } - pdata = modem_parse_dt(pdev, pdev->dev.of_node); if (IS_ERR(pdata)) { mif_err("Failed to parse device tree\n"); |