summaryrefslogtreecommitdiff
path: root/drivers/modem
diff options
context:
space:
mode:
authorChris Blair <chris.blair@stericsson.com>2011-11-04 11:03:27 +0000
committerPhilippe Langlais <philippe.langlais@linaro.org>2012-03-19 09:02:43 +0100
commit1b629ae7ce5ce25321698463982b8cb18e6be75e (patch)
treeaa21d77113ca5e6388479dd477c3794a468f8961 /drivers/modem
parent2bb287ee733f3943de1bca4b9729d44b1bc894d8 (diff)
modem: Add M6718 IPC SPI driver protocol framework
Adds the M6718 modem IPC SPI driver procotol framework and types. Placeholders remain where future parts of the protocol will be called. ST-Ericsson ID: 369397 ST-Ericsson FOSS-OUT ID: STETL-FOSS-OUT-12224 ST-Ericsson Linux next: NA Change-Id: Id4cd5a7fa730c06838c9dd5b1a1cc0045135fdd4 Signed-off-by: Chris Blair <chris.blair@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/36466 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'drivers/modem')
-rw-r--r--drivers/modem/m6718_spi/Makefile2
-rw-r--r--drivers/modem/m6718_spi/modem_driver.c26
-rw-r--r--drivers/modem/m6718_spi/modem_private.h103
-rw-r--r--drivers/modem/m6718_spi/modem_protocol.h22
-rw-r--r--drivers/modem/m6718_spi/modem_state.c2
-rw-r--r--drivers/modem/m6718_spi/modem_state.h36
-rw-r--r--drivers/modem/m6718_spi/modem_statemachine.h74
-rw-r--r--drivers/modem/m6718_spi/protocol.c287
8 files changed, 548 insertions, 4 deletions
diff --git a/drivers/modem/m6718_spi/Makefile b/drivers/modem/m6718_spi/Makefile
index 492995bc753..66bad09c0dd 100644
--- a/drivers/modem/m6718_spi/Makefile
+++ b/drivers/modem/m6718_spi/Makefile
@@ -5,7 +5,7 @@ ifeq ($(CONFIG_MODEM_M6718_SPI_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
-m6718_modem_spi-objs := modem_driver.o
+m6718_modem_spi-objs := modem_driver.o protocol.o
ifeq ($(CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_MODEM_STATE),y)
m6718_modem_spi-objs += modem_state.o
diff --git a/drivers/modem/m6718_spi/modem_driver.c b/drivers/modem/m6718_spi/modem_driver.c
index 7d0efa6e395..13d4a3e28b2 100644
--- a/drivers/modem/m6718_spi/modem_driver.c
+++ b/drivers/modem/m6718_spi/modem_driver.c
@@ -13,6 +13,7 @@
#include <linux/spi/spi.h>
#include <linux/modem/modem_client.h>
#include <linux/modem/m6718_spi/modem_driver.h>
+#include "modem_protocol.h"
static struct modem_spi_dev modem_driver_data = {
.dev = NULL,
@@ -53,6 +54,13 @@ static int spi_probe(struct spi_device *sdev)
spi_set_drvdata(sdev, &modem_driver_data);
+ if (modem_protocol_probe(sdev) != 0) {
+ dev_err(&sdev->dev,
+ "failed to initialise link protocol\n");
+ result = -ENODEV;
+ goto rollback;
+ }
+
/*
* Since we can have multiple spi links for the same modem, only
* initialise the modem data and char/net interfaces once.
@@ -65,13 +73,20 @@ static int spi_probe(struct spi_device *sdev)
dev_err(&sdev->dev,
"failed to retrieve modem description\n");
result = -ENODEV;
+ goto rollback_protocol_init;
}
}
return result;
+
+rollback_protocol_init:
+ modem_protocol_exit();
+rollback:
+ return result;
}
static int __exit spi_remove(struct spi_device *sdev)
{
+ modem_protocol_exit();
return 0;
}
@@ -86,8 +101,14 @@ static int __exit spi_remove(struct spi_device *sdev)
*/
static int spi_suspend(struct spi_device *sdev, pm_message_t mesg)
{
- dev_dbg(&sdev->dev, "suspend called\n");
- return 0;
+ bool busy;
+
+ busy = modem_protocol_is_busy(sdev);
+ dev_dbg(&sdev->dev, "suspend called, protocol busy:%d\n", busy);
+ if (!busy)
+ return 0;
+ else
+ return -EBUSY;
}
/**
@@ -118,6 +139,7 @@ static struct spi_driver spi_driver = {
static int __init m6718_spi_driver_init(void)
{
pr_info("M6718 modem driver initialising\n");
+ modem_protocol_init();
return spi_register_driver(&spi_driver);
}
module_init(m6718_spi_driver_init);
diff --git a/drivers/modem/m6718_spi/modem_private.h b/drivers/modem/m6718_spi/modem_private.h
new file mode 100644
index 00000000000..383699f1f3e
--- /dev/null
+++ b/drivers/modem/m6718_spi/modem_private.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Chris Blair <chris.blair@stericsson.com> for ST-Ericsson
+ * based on shrm_driver.h
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Modem IPC driver protocol interface header:
+ * private data
+ */
+#ifndef _MODEM_PRIVATE_H_
+#define _MODEM_PRIVATE_H_
+
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/atomic.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include "modem_protocol.h"
+#include "modem_statemachine.h"
+
+#define IPC_DRIVER_VERSION (0x03) /* APE protocol version */
+#define IPC_DRIVER_MODEM_MIN_VER (0x03) /* version required from modem */
+
+#define IPC_NBR_SUPPORTED_SPI_LINKS (2)
+#define IPC_LINK_COMMON (0)
+#define IPC_LINK_AUDIO (1)
+
+#define IPC_TX_QUEUE_MAX_SIZE (1024*1024)
+
+#define IPC_L1_HDR_SIZE (4)
+#define IPC_L2_HDR_SIZE (4)
+
+/* tx queue item (frame) */
+struct ipc_tx_queue {
+ struct list_head node;
+ int actual_len;
+ int len;
+ void *data;
+ int counter;
+};
+
+/* context structure for an spi link */
+struct ipc_link_context {
+ struct modem_m6718_spi_link_platform_data *link;
+ struct spi_device *sdev;
+ atomic_t gpio_configured;
+ atomic_t state_int;
+ spinlock_t sm_lock;
+ spinlock_t tx_q_update_lock;
+ atomic_t tx_q_count;
+ int tx_q_free;
+ struct list_head tx_q;
+ int tx_frame_counter;
+ const struct ipc_sm_state *state;
+ u32 cmd;
+ struct ipc_tx_queue *frame;
+ struct spi_message spi_message;
+ struct spi_transfer spi_transfer;
+ struct timer_list comms_timer;
+ struct timer_list slave_stable_timer;
+#ifdef CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_VERIFY_FRAMES
+ struct ipc_tx_queue *last_frame;
+#endif
+#ifdef CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_THROUGHPUT_MEASUREMENT
+ u32 tx_bytes;
+ u32 rx_bytes;
+ unsigned long idl_measured_at;
+ unsigned long idl_idle_enter;
+ unsigned long idl_idle_total;
+#endif
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfsfile;
+ u8 lastevent;
+ u8 lastignored;
+ enum ipc_sm_state_id lastignored_in;
+ bool lastignored_inthis;
+ int tx_q_min;
+ unsigned long statesince;
+#endif
+};
+
+/* context structure for the spi driver */
+struct ipc_l1_context {
+ bool init_done;
+ atomic_t boot_sync_done;
+ struct ipc_link_context device_context[IPC_NBR_SUPPORTED_SPI_LINKS];
+#ifdef CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_THROUGHPUT_MEASUREMENT
+ struct timer_list tp_timer;
+#endif
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfsdir;
+ struct dentry *debugfs_silentreset;
+ bool msr_disable;
+#endif
+};
+
+#endif /* _MODEM_PRIVATE_H_ */
diff --git a/drivers/modem/m6718_spi/modem_protocol.h b/drivers/modem/m6718_spi/modem_protocol.h
new file mode 100644
index 00000000000..69511945cb5
--- /dev/null
+++ b/drivers/modem/m6718_spi/modem_protocol.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Chris Blair <chris.blair@stericsson.com> for ST-Ericsson
+ * based on shrm_driver.h
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Modem IPC driver protocol interface header.
+ */
+#ifndef _MODEM_PROTOCOL_H_
+#define _MODEM_PROTOCOL_H_
+
+#include <linux/spi/spi.h>
+
+void modem_protocol_init(void);
+int modem_protocol_probe(struct spi_device *sdev);
+void modem_protocol_exit(void);
+bool modem_protocol_is_busy(struct spi_device *sdev);
+bool modem_protocol_channel_is_open(u8 channel);
+
+#endif /* _MODEM_PROTOCOL_H_ */
diff --git a/drivers/modem/m6718_spi/modem_state.c b/drivers/modem/m6718_spi/modem_state.c
index 266f75a7a71..47376934bcb 100644
--- a/drivers/modem/m6718_spi/modem_state.c
+++ b/drivers/modem/m6718_spi/modem_state.c
@@ -13,7 +13,6 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/wait.h>
-#include <linux/modem/m6718_spi/modem_state.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
@@ -30,6 +29,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
+#include "modem_state.h"
/*
* To enable this driver add a struct platform_device in the board
diff --git a/drivers/modem/m6718_spi/modem_state.h b/drivers/modem/m6718_spi/modem_state.h
new file mode 100644
index 00000000000..a2f1d9fbe3e
--- /dev/null
+++ b/drivers/modem/m6718_spi/modem_state.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Derek Morton <derek.morton@stericsson.com>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Power state driver for M6718 MODEM
+ */
+#ifndef MODEM_STATE_H
+#define MODEM_STATE_H
+
+enum modem_states {
+ MODEM_STATE_OFF,
+ MODEM_STATE_RESET,
+ MODEM_STATE_CRASH,
+ MODEM_STATE_ON,
+ /*
+ * Add new states before end marker and update modem_state_str[]
+ * in modem_state.c
+ */
+ MODEM_STATE_END_MARKER
+};
+
+void modem_state_power_on(void);
+void modem_state_power_off(void);
+void modem_state_force_reset(void);
+int modem_state_get_state(void);
+char *modem_state_to_str(int state);
+
+/* Callbacks will be running in tasklet context */
+int modem_state_register_callback(int (*callback) (unsigned long),
+ unsigned long data);
+int modem_state_remove_callback(int (*callback) (unsigned long));
+
+#endif
diff --git a/drivers/modem/m6718_spi/modem_statemachine.h b/drivers/modem/m6718_spi/modem_statemachine.h
new file mode 100644
index 00000000000..bc737dbb7e8
--- /dev/null
+++ b/drivers/modem/m6718_spi/modem_statemachine.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Chris Blair <chris.blair@stericsson.com> for ST-Ericsson
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Modem IPC driver protocol interface header:
+ * statemachine functionality.
+ */
+#ifndef _MODEM_STATEMACHINE_H_
+#define _MODEM_STATEMACHINE_H_
+
+#include <linux/kernel.h>
+
+/* valid states for the driver state machine */
+enum ipc_sm_state_id {
+ /* common link and shared states below */
+ IPC_SM_INIT,
+ IPC_SM_HALT,
+ IPC_SM_RESET,
+ IPC_SM_WAIT_SLAVE_STABLE,
+ IPC_SM_WAIT_HANDSHAKE_INACTIVE,
+ IPC_SM_SLW_TX_BOOTREQ,
+ IPC_SM_ACT_TX_BOOTREQ,
+ IPC_SM_SLW_RX_BOOTRESP,
+ IPC_SM_ACT_RX_BOOTRESP,
+ IPC_SM_IDL,
+ IPC_SM_SLW_TX_WR_CMD,
+ IPC_SM_ACT_TX_WR_CMD,
+ IPC_SM_SLW_TX_WR_DAT,
+ IPC_SM_ACT_TX_WR_DAT,
+ IPC_SM_SLW_TX_RD_CMD,
+ IPC_SM_ACT_TX_RD_CMD,
+ IPC_SM_SLW_RX_WR_CMD,
+ IPC_SM_ACT_RX_WR_CMD,
+ IPC_SM_ACT_RX_WR_DAT,
+ /* audio link states below */
+ IPC_SM_INIT_AUD,
+ IPC_SM_HALT_AUD,
+ IPC_SM_RESET_AUD,
+ IPC_SM_IDL_AUD,
+ IPC_SM_SLW_TX_WR_DAT_AUD,
+ IPC_SM_ACT_TX_WR_DAT_AUD,
+ IPC_SM_SLW_RX_WR_DAT_AUD,
+ IPC_SM_ACT_RX_WR_DAT_AUD,
+ IPC_SM_STATE_ID_NBR
+};
+
+/* state machine trigger causes events */
+#define IPC_SM_RUN_NONE (0x00)
+#define IPC_SM_RUN_SLAVE_IRQ (0x01)
+#define IPC_SM_RUN_TFR_COMPLETE (0x02)
+#define IPC_SM_RUN_TX_REQ (0x04)
+#define IPC_SM_RUN_INIT (0x08)
+#define IPC_SM_RUN_ABORT (0x10)
+#define IPC_SM_RUN_COMMS_TMO (0x20)
+#define IPC_SM_RUN_STABLE_TMO (0x40)
+#define IPC_SM_RUN_RESET (0x80)
+
+struct ipc_link_context; /* forward declaration */
+
+typedef u8 (*ipc_sm_enter_func)(u8 event, struct ipc_link_context *context);
+typedef const struct ipc_sm_state *(*ipc_sm_exit_func)(u8 event,
+ struct ipc_link_context *context);
+
+struct ipc_sm_state {
+ enum ipc_sm_state_id id;
+ ipc_sm_enter_func enter;
+ ipc_sm_exit_func exit;
+ u8 events;
+};
+
+#endif /* _MODEM_STATEMACHINE_H_ */
diff --git a/drivers/modem/m6718_spi/protocol.c b/drivers/modem/m6718_spi/protocol.c
new file mode 100644
index 00000000000..5f03167d024
--- /dev/null
+++ b/drivers/modem/m6718_spi/protocol.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010,2011
+ *
+ * Author: Chris Blair <chris.blair@stericsson.com> for ST-Ericsson
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * U9500 <-> M6718 IPC protocol implementation using SPI.
+ */
+#include <linux/modem/m6718_spi/modem_driver.h>
+#include "modem_protocol.h"
+#include "modem_private.h"
+
+#ifdef CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_MODEM_STATE
+#include <linux/workqueue.h>
+#include "modem_state.h"
+
+#define MODEM_STATE_REGISTER_TMO_MS (500)
+#endif
+
+#ifdef WORKAROUND_DUPLICATED_IRQ
+#include <linux/amba/pl022.h>
+#endif
+
+struct l2mux_channel {
+ u8 open:1;
+ u8 link:7;
+};
+
+/* valid open L2 mux channels */
+static const struct l2mux_channel channels[255] = {
+ [MODEM_M6718_SPI_CHN_ISI] = {
+ .open = true,
+ .link = IPC_LINK_COMMON
+ },
+ [MODEM_M6718_SPI_CHN_AUDIO] = {
+ .open = true,
+ .link = IPC_LINK_AUDIO
+ },
+ [MODEM_M6718_SPI_CHN_MASTER_LOOPBACK0] = {
+ .open = true,
+ .link = IPC_LINK_COMMON
+ },
+ [MODEM_M6718_SPI_CHN_SLAVE_LOOPBACK0] = {
+ .open = true,
+ .link = IPC_LINK_COMMON
+ },
+ [MODEM_M6718_SPI_CHN_MASTER_LOOPBACK1] = {
+ .open = true,
+ .link = IPC_LINK_AUDIO
+ },
+ [MODEM_M6718_SPI_CHN_SLAVE_LOOPBACK1] = {
+ .open = true,
+ .link = IPC_LINK_AUDIO
+ }
+};
+
+#ifdef CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_MODEM_STATE
+static void modem_state_reg_wq(struct work_struct *work);
+static DECLARE_DELAYED_WORK(modem_state_reg_work, modem_state_reg_wq);
+#endif
+
+/* the spi driver context */
+struct ipc_l1_context l1_context = {
+#ifdef CONFIG_DEBUG_FS
+ .msr_disable = false,
+#endif
+ .init_done = false
+};
+
+bool modem_protocol_channel_is_open(u8 channel)
+{
+ return channels[channel].open;
+}
+
+void modem_comms_timeout(unsigned long data)
+{
+ /* TODO: statemachine will be kicked here */
+}
+
+void slave_stable_timeout(unsigned long data)
+{
+ /* TODO: statemachine will be kicked here */
+}
+
+/**
+ * modem_protocol_init() - initialise the IPC protocol
+ *
+ * Initialises the IPC protocol in preparation for use. After this is called
+ * the protocol is ready to be probed for each link to be supported.
+ */
+void modem_protocol_init(void)
+{
+ pr_info("M6718 IPC protocol initialising version %02x\n",
+ IPC_DRIVER_VERSION);
+
+ atomic_set(&l1_context.boot_sync_done, 0);
+ l1_context.init_done = true;
+#ifdef CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_MODEM_STATE
+ schedule_delayed_work(&modem_state_reg_work, 0);
+#endif
+}
+
+/**
+ * modem_m6718_spi_send() - send a frame using the IPC protocol
+ * @modem_spi_dev: pointer to modem driver information structure
+ * @channel: L2 channel to send on
+ * @len: length of data to send
+ * @data: pointer to buffer containing data
+ *
+ * Check that the requested channel is supported and open, queue a frame
+ * containing the data on the appropriate link and ensure the state machine
+ * is running to start the transfer.
+ */
+int modem_m6718_spi_send(struct modem_spi_dev *modem_spi_dev, u8 channel,
+ u32 len, void *data)
+{
+ struct ipc_link_context *context;
+
+ if (!channels[channel].open) {
+ dev_err(modem_spi_dev->dev,
+ "error: invalid channel (%d), discarding frame\n",
+ channel);
+ return -EINVAL;
+ }
+
+ context = &l1_context.device_context[channels[channel].link];
+ if (context->state == NULL || context->state->id == IPC_SM_HALT) {
+ static unsigned long linkfail_warn_time;
+ if (printk_timed_ratelimit(&linkfail_warn_time, 60 * 1000))
+ dev_err(modem_spi_dev->dev,
+ "error: link %d for ch %d is not available, "
+ "discarding frames\n",
+ channels[channel].link, channel);
+ return -ENODEV;
+ }
+
+ /* TODO: statemachine will be kicked here */
+ return 0;
+}
+EXPORT_SYMBOL_GPL(modem_m6718_spi_send);
+
+/**
+ * modem_m6718_spi_is_boot_done() - check if boot handshake with modem is done
+ */
+bool modem_m6718_spi_is_boot_done(void)
+{
+ return atomic_read(&l1_context.boot_sync_done);
+}
+EXPORT_SYMBOL_GPL(modem_m6718_spi_is_boot_done);
+
+/**
+ * modem_protocol_is_busy() - check if the protocol is currently active
+ * @sdev: pointer to spi_device for link to check
+ *
+ * Checks each of the IPC links to see if they are inactive: this means they
+ * can be in either IDLE or INIT states. If any of the links are not idle then
+ * true is returned to indicate that the protocol is busy.
+ */
+bool modem_protocol_is_busy(struct spi_device *sdev)
+{
+ int i;
+
+ for (i = 0; i < IPC_NBR_SUPPORTED_SPI_LINKS; i++)
+ switch (l1_context.device_context[i].state->id) {
+ case IPC_SM_IDL:
+ case IPC_SM_IDL_AUD:
+ case IPC_SM_INIT:
+ case IPC_SM_INIT_AUD:
+ case IPC_SM_WAIT_SLAVE_STABLE:
+ /* not busy; continue checking */
+ break;
+ default:
+ dev_info(&sdev->dev, "link %d is busy\n", i);
+ return true;
+ }
+ return false;
+}
+
+#ifdef CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_MODEM_STATE
+static int modem_state_callback(unsigned long unused)
+{
+ int modem_state = modem_state_get_state();
+
+ pr_info("M6718 IPC protocol modemstate reports modem is %s\n",
+ modem_state_to_str(modem_state));
+
+ switch (modem_state) {
+ case MODEM_STATE_ON:
+ /* TODO: statemachine will be kicked here */
+ break;
+ case MODEM_STATE_OFF:
+ case MODEM_STATE_RESET:
+ case MODEM_STATE_CRASH:
+ /* TODO: statemachine will be kicked here */
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void modem_state_reg_wq(struct work_struct *work)
+{
+ if (modem_state_register_callback(modem_state_callback, 0) == -EAGAIN) {
+ pr_info("M6718 IPC protocol failed to register with "
+ "modemstate, will retry\n");
+ schedule_delayed_work(&modem_state_reg_work,
+ (MODEM_STATE_REGISTER_TMO_MS * HZ) / 1000);
+ } else {
+ pr_info("M6718 IPC protocol registered with modemstate\n");
+ }
+}
+#endif
+
+int modem_protocol_probe(struct spi_device *sdev)
+{
+ struct modem_m6718_spi_link_platform_data *link =
+ sdev->dev.platform_data;
+ struct ipc_link_context *context;
+ int link_id;
+
+ if (link == NULL) {
+ /* platform data missing in board config? */
+ dev_err(&sdev->dev, "error: no platform data for link!\n");
+ return -ENODEV;
+ }
+
+ link_id = link->id;
+ context = &l1_context.device_context[link_id];
+
+ if (link_id >= IPC_NBR_SUPPORTED_SPI_LINKS) {
+ dev_err(&sdev->dev,
+ "link %d error: too many links! (max %d)\n",
+ link->id, IPC_NBR_SUPPORTED_SPI_LINKS);
+ return -ENODEV;
+ }
+
+ dev_info(&sdev->dev,
+ "link %d: registering SPI link bus:%d cs:%d\n",
+ link->id, sdev->master->bus_num, sdev->chip_select);
+
+ /* update spi device with correct word size for our device */
+ sdev->bits_per_word = 16;
+ spi_setup(sdev);
+
+ /* init link context */
+ context->link = link;
+ context->sdev = sdev;
+ atomic_set(&context->gpio_configured, 0);
+ spin_lock_init(&context->sm_lock);
+ init_timer(&context->comms_timer);
+ context->comms_timer.function = modem_comms_timeout;
+ context->comms_timer.data = (unsigned long)context;
+ init_timer(&context->slave_stable_timer);
+ context->slave_stable_timer.function = slave_stable_timeout;
+ context->slave_stable_timer.data = (unsigned long)context;
+
+#ifdef CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_VERIFY_FRAMES
+ context->last_frame = NULL;
+#endif
+
+ /*
+ * For link0 (the handshake link) we force a state transition now so
+ * that it prepares for boot sync.
+ */
+ /* TODO: statemachine will be kicked here */
+
+ /*
+ * unlikely but possible: for links other than 0, check if handshake is
+ * already complete by the time this link is probed - if so we force a
+ * state transition since the one issued by the handshake exit actions
+ * will have been ignored.
+ */
+ if (link->id > 0 && atomic_read(&l1_context.boot_sync_done)) {
+ dev_dbg(&sdev->dev,
+ "link %d: boot sync is done, kicking state machine\n",
+ link->id);
+ /* TODO: statemachine will be kicked here */
+ }
+ return 0;
+}
+
+void modem_protocol_exit(void)
+{
+ pr_info("M6718 IPC protocol exit\n");
+}