summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Blair <chris.blair@stericsson.com>2011-11-07 14:34:38 +0000
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-06-05 10:40:12 +0200
commit5a88ec4d51e0ec1f14a9107c89a6d54539018099 (patch)
treef1aa83c3b09665166f55b7c63f9e1eafffe81f46
parentb48014c690648e9bc2c99342ed1cd3bb731e5005 (diff)
modem: Add M6718 modem SPI IPC driver framework
Adds support for the M6718 modem IPC SPI driver. This patch adds the spi driver under which the protocol will be added. ST-Ericsson ID: 369397 ST-Ericsson FOSS-OUT ID: STETL-FOSS-OUT-12224 ST-Ericsson Linux next: NA Change-Id: Ifa60efa9cb6a9d30b02b88b563624a293bc0930c Signed-off-by: Chris Blair <chris.blair@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/36433 Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
-rw-r--r--drivers/modem/Kconfig2
-rw-r--r--drivers/modem/Makefile1
-rw-r--r--drivers/modem/m6718_spi/Kconfig83
-rw-r--r--drivers/modem/m6718_spi/Makefile10
-rw-r--r--drivers/modem/m6718_spi/modem_driver.c134
-rw-r--r--include/linux/modem/m6718_spi/modem_driver.h135
6 files changed, 365 insertions, 0 deletions
diff --git a/drivers/modem/Kconfig b/drivers/modem/Kconfig
index 9ecbe00fd61..323ef88af18 100644
--- a/drivers/modem/Kconfig
+++ b/drivers/modem/Kconfig
@@ -29,3 +29,5 @@ config MODEM_M6718
Add support for the modem access driver for the M6718 modem.
If unsure, say N.
+
+source "drivers/modem/m6718_spi/Kconfig"
diff --git a/drivers/modem/Makefile b/drivers/modem/Makefile
index c0df71e65a1..a7c1df50074 100644
--- a/drivers/modem/Makefile
+++ b/drivers/modem/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_MODEM) := modem_access.o
obj-$(CONFIG_MODEM_U8500) += modem_u8500.o
obj-$(CONFIG_U8500_SHRM) += shrm/
obj-$(CONFIG_MODEM_M6718) += modem_m6718.o
+obj-$(CONFIG_MODEM_M6718_SPI) += m6718_spi/
diff --git a/drivers/modem/m6718_spi/Kconfig b/drivers/modem/m6718_spi/Kconfig
new file mode 100644
index 00000000000..f945d24a094
--- /dev/null
+++ b/drivers/modem/m6718_spi/Kconfig
@@ -0,0 +1,83 @@
+#
+# M6718 modem SPI IPC driver kernel configuration
+#
+config MODEM_M6718_SPI
+ tristate "M6718 modem IPC SPI driver"
+ depends on MODEM_M6718
+ default y
+ ---help---
+ If you say Y here, you will enable the M6718 modem IPC SPI driver.
+
+ If unsure, say Y.
+
+config MODEM_M6718_SPI_DEBUG
+ boolean "Modem driver debug"
+ depends on MODEM_M6718_SPI
+ default N
+ ---help---
+ If you say Y here, you will enable full debug trace from the M6718
+ modem driver. This should not be enabled by default.
+
+ If unsure, say N.
+
+config MODEM_M6718_SPI_ENABLE_FEATURE_MODEM_STATE
+ boolean "M6718 modem state driver integration"
+ depends on MODEM_M6718_SPI
+ default y
+ ---help---
+ Enables integration of the IPC driver with the modem state driver.
+ This allows the IPC driver to be notified of changes in modem state
+ (on, off, reset) and allows the IPC driver to cause modem state
+ changes if needed.
+
+ By default this should be enabled.
+
+config MODEM_M6718_SPI_ENABLE_FEATURE_FRAME_DUMP
+ boolean "IPC SPI L1 frame dump"
+ depends on MODEM_M6718_SPI
+ default n
+ ---help---
+ If you say Y here, you will enable dumping of the raw TX and RX frames
+ by the IPC driver L1.
+
+ If unsure, say N.
+
+config MODEM_M6718_SPI_ENABLE_FEATURE_LOOPBACK
+ boolean "Modem IPC loopback support"
+ depends on MODEM_M6718_SPI
+ default y
+ ---help---
+ If you say Y here, you will enable the IPC loopback channels/devices.
+
+ If unsure, say Y.
+
+
+config MODEM_M6718_SPI_ENABLE_FEATURE_VERIFY_FRAMES
+ boolean "Verify loopback frames"
+ depends on MODEM_M6718_SPI
+ default n
+ ---help---
+ This will enabling checking of loopback frames to verify that the data
+ received is identical to the data sent.
+
+ If unsure, say N.
+
+config MODEM_M6718_SPI_ENABLE_FEATURE_THROUGHPUT_MEASUREMENT
+ boolean "Modem IPC throughput measurement"
+ depends on MODEM_M6718_SPI
+ default n
+ ---help---
+ If you say Y here, you will enable the IPC link throughput
+ measurement and reporting.
+
+ If unsure, say N.
+
+config MODEM_M6718_SPI_SET_THROUGHPUT_FREQUENCY
+ int "Sample rate for throughput measurements (seconds)"
+ default "5"
+ depends on MODEM_M6718_SPI_ENABLE_FEATURE_THROUGHPUT_MEASUREMENT
+ help
+ The sample frequency for taking IPC SPI link throughput measurements.
+ Increasing the rate (reducing the time) will increase the accuracy of
+ the measurements, but will also increase the impact on link and system
+ performance.
diff --git a/drivers/modem/m6718_spi/Makefile b/drivers/modem/m6718_spi/Makefile
new file mode 100644
index 00000000000..96bf481e986
--- /dev/null
+++ b/drivers/modem/m6718_spi/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for M6718 SPI driver
+#
+ifeq ($(CONFIG_MODEM_M6718_SPI_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+m6718_modem_spi-objs := modem_driver.o
+
+obj-$(CONFIG_MODEM_M6718_SPI) += m6718_modem_spi.o
diff --git a/drivers/modem/m6718_spi/modem_driver.c b/drivers/modem/m6718_spi/modem_driver.c
new file mode 100644
index 00000000000..7d0efa6e395
--- /dev/null
+++ b/drivers/modem/m6718_spi/modem_driver.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Chris Blair <chris.blair@stericsson.com> for ST-Ericsson
+ * based on modem_shrm_driver.c
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * SPI driver implementing the M6718 inter-processor communication protocol.
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/modem/modem_client.h>
+#include <linux/modem/m6718_spi/modem_driver.h>
+
+static struct modem_spi_dev modem_driver_data = {
+ .dev = NULL,
+ .ndev = NULL,
+ .modem = NULL,
+ .isa_context = NULL,
+ .netdev_flag_up = 0
+};
+
+/**
+ * modem_m6718_spi_receive() - Receive a frame from L1 physical layer
+ * @sdev: pointer to spi device structure
+ * @channel: L2 mux channel id
+ * @len: frame data length
+ * @data: pointer to frame data
+ *
+ * This function is called from the driver L1 physical transport layer. It
+ * copied the frame data to the receive queue for the channel on which the data
+ * was received.
+ *
+ * Special handling is given to slave-loopback channels where the data is simply
+ * sent back to the modem on the same channel.
+ *
+ * Special handling is given to the ISI channel when PHONET is enabled - the
+ * phonet tasklet is scheduled in order to pump the received data through the
+ * net device interface.
+ */
+int modem_m6718_spi_receive(struct spi_device *sdev, u8 channel,
+ u32 len, void *data)
+{
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(modem_m6718_spi_receive);
+
+static int spi_probe(struct spi_device *sdev)
+{
+ int result = 0;
+
+ spi_set_drvdata(sdev, &modem_driver_data);
+
+ /*
+ * Since we can have multiple spi links for the same modem, only
+ * initialise the modem data and char/net interfaces once.
+ */
+ if (modem_driver_data.dev == NULL) {
+ modem_driver_data.dev = &sdev->dev;
+ modem_driver_data.modem =
+ modem_get(modem_driver_data.dev, "m6718");
+ if (modem_driver_data.modem == NULL) {
+ dev_err(&sdev->dev,
+ "failed to retrieve modem description\n");
+ result = -ENODEV;
+ }
+ }
+ return result;
+}
+
+static int __exit spi_remove(struct spi_device *sdev)
+{
+ return 0;
+}
+
+#ifdef CONFIG_PM
+/**
+ * spi_suspend() - This routine puts the IPC driver in to suspend state.
+ * @sdev: pointer to spi device structure.
+ * @mesg: pm operation
+ *
+ * This routine checks the current ongoing communication with modem
+ * and prevents suspend if modem communication is on-going.
+ */
+static int spi_suspend(struct spi_device *sdev, pm_message_t mesg)
+{
+ dev_dbg(&sdev->dev, "suspend called\n");
+ return 0;
+}
+
+/**
+ * spi_resume() - This routine resumes the IPC driver from suspend state.
+ * @sdev: pointer to spi device structure
+ */
+static int spi_resume(struct spi_device *sdev)
+{
+ dev_dbg(&sdev->dev, "resume called\n");
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct spi_driver spi_driver = {
+ .driver = {
+ .name = "spimodem",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE
+ },
+ .probe = spi_probe,
+ .remove = __exit_p(spi_remove),
+#ifdef CONFIG_PM
+ .suspend = spi_suspend,
+ .resume = spi_resume,
+#endif
+};
+
+static int __init m6718_spi_driver_init(void)
+{
+ pr_info("M6718 modem driver initialising\n");
+ return spi_register_driver(&spi_driver);
+}
+module_init(m6718_spi_driver_init);
+
+static void __exit m6718_spi_driver_exit(void)
+{
+ pr_debug("M6718 modem SPI IPC driver exit\n");
+ spi_unregister_driver(&spi_driver);
+}
+module_exit(m6718_spi_driver_exit);
+
+MODULE_AUTHOR("Chris Blair <chris.blair@stericsson.com>");
+MODULE_DESCRIPTION("M6718 modem IPC SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/modem/m6718_spi/modem_driver.h b/include/linux/modem/m6718_spi/modem_driver.h
new file mode 100644
index 00000000000..8c5209c228c
--- /dev/null
+++ b/include/linux/modem/m6718_spi/modem_driver.h
@@ -0,0 +1,135 @@
+/*
+ * 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 interface header.
+ */
+#ifndef _MODEM_DRIVER_H_
+#define _MODEM_DRIVER_H_
+
+#include <linux/device.h>
+#include <linux/modem/modem.h>
+#include <linux/cdev.h>
+#include <linux/spi/spi.h>
+
+
+/* driver L2 mux channels */
+#ifdef CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_LOOPBACK
+#define MODEM_M6718_SPI_MAX_CHANNELS (9)
+#else
+#define MODEM_M6718_SPI_MAX_CHANNELS (3)
+#endif
+
+#define MODEM_M6718_SPI_CHN_ISI (0)
+/*#define MODEM_M6718_SPI_CHN_RPC (1) not supported */
+#define MODEM_M6718_SPI_CHN_AUDIO (2)
+/*#define MODEM_M6718_SPI_CHN_SECURITY (3) not supported */
+/* (4) not supported */
+#ifdef CONFIG_MODEM_M6718_SPI_ENABLE_FEATURE_LOOPBACK
+#define MODEM_M6718_SPI_CHN_MASTER_LOOPBACK0 (5)
+#define MODEM_M6718_SPI_CHN_SLAVE_LOOPBACK0 (6)
+#define MODEM_M6718_SPI_CHN_MASTER_LOOPBACK1 (7)
+#define MODEM_M6718_SPI_CHN_SLAVE_LOOPBACK1 (8)
+#endif
+
+/**
+ * struct queue_element - information to add an element to queue
+ * @entry: list entry
+ * @offset: message offset
+ * @size: message size
+ * @no: total number of messages
+ */
+struct queue_element {
+ struct list_head entry;
+ u32 offset;
+ u32 size;
+ u32 no;
+};
+
+/**
+ * struct message_queue - ISI, RPC, AUDIO, SECURITY message queue information
+ * @channel: L2 mux channel served by this queue
+ * @fifo_base: pointer to the respective fifo base
+ * @size: size of the data to be read
+ * @free: free space in the queue
+ * @readptr: fifo read pointer
+ * @writeptr: fifo write pointer
+ * @no: total number of messages
+ * @update_lock: spinlock for protecting the queue read operation
+ * @q_rp: queue read pointer is valid
+ * @wq_readable: wait queue head
+ * @msg_list: message list
+ * @modem_spi_dev: pointer to modem device information structure
+ */
+struct message_queue {
+ u8 channel;
+ u8 *fifo_base;
+ u32 size;
+ u32 free;
+ u32 readptr;
+ u32 writeptr;
+ u32 no;
+ spinlock_t update_lock;
+ atomic_t q_rp;
+ wait_queue_head_t wq_readable;
+ struct list_head msg_list;
+ struct modem_spi_dev *modem_spi_dev;
+};
+
+/**
+ * struct isa_device_context - modem char interface device information
+ * @dl_queue: structre to store the queue related info
+ * @device_id: channel id (ISI, AUDIO, RPC, ...)
+ * @addr: device address
+ */
+struct isa_device_context {
+ struct message_queue dl_queue;
+ u8 device_id;
+ void *addr;
+};
+
+/**
+ * struct isa_driver_context - modem char interface driver information
+ * @is_open: flag to check the usage of queue
+ * @isadev: pointer to struct t_isadev_context
+ * @common_tx_lock: spinlock for protecting common channel
+ * @audio_tx_mutex: mutex for protecting audio channel
+ * @cdev: character device structre
+ * @modem_class: pointer to the class structure
+ */
+struct isa_driver_context {
+ atomic_t is_open[MODEM_M6718_SPI_MAX_CHANNELS];
+ struct isa_device_context *isadev;
+ spinlock_t common_tx_lock;
+ struct mutex audio_tx_mutex;
+ struct cdev cdev;
+ struct class *modem_class;
+};
+
+/**
+ * struct modem_spi_dev - modem device information
+ * @dev pointer to device
+ * @ndev pointer to net_device interface
+ * @modem pointer to registered modem structure
+ * @isa_context pointer to char device interface
+ * @netdev_flag_up: flag to indicate up/down of network device
+ * @msr_flag: flag to indicate modem-silent-reset is in progress
+ */
+struct modem_spi_dev {
+ struct device *dev;
+ struct net_device *ndev;
+ struct modem *modem;
+ struct isa_driver_context *isa_context;
+ int netdev_flag_up;
+ bool msr_flag;
+};
+
+/* function exported for L1 to call with received frames */
+int modem_m6718_spi_receive(struct spi_device *sdev, u8 channel,
+ u32 len, void *data);
+
+#endif /* _MODEM_DRIVER_H_ */