summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorYue Ma <yuem@codeaurora.org>2016-01-26 18:25:07 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:16:42 -0700
commit791a6a69a5b11a2dc8244d0bd7d2d37fabcb4ed3 (patch)
tree95dfc10983e6da97317e05760814f76db7bc327b /drivers
parentf590819cdec826e1f1b72b34534d2738f4a2fa22 (diff)
net: icnss: Add snapshot of icnss driver
This is a snapshot of the icnss driver and associated files as of msm-3.18 commit: e70ad0cd5efdd9dc91a77dcdac31d6132e1315c1 (Promotion of kernel.lnx. 3.18-151201.) Signed-off-by: Yue Ma <yuem@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/soc/qcom/Kconfig8
-rw-r--r--drivers/soc/qcom/Makefile1
-rw-r--r--drivers/soc/qcom/icnss.c946
-rw-r--r--drivers/soc/qcom/wlan_firmware_service_v01.c978
-rw-r--r--drivers/soc/qcom/wlan_firmware_service_v01.h274
5 files changed, 2207 insertions, 0 deletions
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 640ad813b88c..96c2a20dbbe5 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -343,6 +343,14 @@ config QCOM_MEMORY_DUMP_V2
of deadlocks or cpu hangs these dump regions are captured to
give a snapshot of the system at the time of the crash.
+config ICNSS
+ tristate "Platform driver for Q6 integrated connectivity"
+ ---help---
+ This module adds support for Q6 integrated WLAN connectivity
+ subsystem. This module is responsible for communicating WLAN on/off
+ control messages to FW over QMI channel. It is also responsible for
+ handling WLAN PD restart notifications.
+
config MSM_SECURE_BUFFER
bool "Helper functions for securing buffers through TZ"
help
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index ea2556d8861a..4f3fc0bc175e 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_QCOM_MEMORY_DUMP) += memory_dump.o
obj-$(CONFIG_QCOM_MEMORY_DUMP_V2) += memory_dump_v2.o
obj-$(CONFIG_QCOM_WATCHDOG_V2) += watchdog_v2.o
obj-$(CONFIG_TRACER_PKT) += tracer_pkt.o
+obj-$(CONFIG_ICNSS) += icnss.o wlan_firmware_service_v01.o
obj-$(CONFIG_SOC_BUS) += socinfo.o
obj-$(CONFIG_QCOM_BUS_SCALING) += msm_bus/
obj-$(CONFIG_MSM_SECURE_BUFFER) += secure_buffer.o
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
new file mode 100644
index 000000000000..cdcfa4e9fdd9
--- /dev/null
+++ b/drivers/soc/qcom/icnss.c
@@ -0,0 +1,946 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/export.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/qmi_encdec.h>
+#include <soc/qcom/memory_dump.h>
+#include <soc/qcom/icnss.h>
+#include <soc/qcom/msm_qmi_interface.h>
+
+#include "wlan_firmware_service_v01.h"
+
+enum icnss_qmi_event_type {
+ ICNSS_QMI_EVENT_SERVER_ARRIVE,
+ ICNSS_QMI_EVENT_SERVER_EXIT,
+ ICNSS_QMI_EVENT_FW_READY_IND,
+};
+
+struct icnss_qmi_event {
+ struct list_head list;
+ enum icnss_qmi_event_type type;
+ void *data;
+};
+
+#define ICNSS_PANIC 1
+#define WLFW_TIMEOUT_MS 3000
+#define WLFW_SERVICE_INS_ID_V01 0
+#define ICNSS_WLFW_QMI_CONNECTED BIT(0)
+#define ICNSS_FW_READY BIT(1)
+
+#define ICNSS_IS_WLFW_QMI_CONNECTED(_state) \
+ ((_state) & ICNSS_WLFW_QMI_CONNECTED)
+#define ICNSS_IS_FW_READY(_state) ((_state) & ICNSS_FW_READY)
+
+#ifdef ICNSS_PANIC
+#define ICNSS_ASSERT(_condition) do { \
+ if (!(_condition)) { \
+ pr_err("ICNSS ASSERT in %s Line %d\n", \
+ __func__, __LINE__); \
+ BUG_ON(1); \
+ } \
+ } while (0)
+#else
+#define ICNSS_ASSERT(_condition) do { \
+ if (!(_condition)) { \
+ pr_err("ICNSS ASSERT in %s Line %d\n", \
+ __func__, __LINE__); \
+ WARN_ON(1); \
+ } \
+ } while (0)
+#endif
+
+struct ce_irq_list {
+ int irq;
+ irqreturn_t (*handler)(int, void *);
+};
+
+static struct {
+ struct platform_device *pdev;
+ struct icnss_driver_ops *ops;
+ struct ce_irq_list ce_irq_list[ICNSS_MAX_IRQ_REGISTRATIONS];
+ u32 ce_irqs[ICNSS_MAX_IRQ_REGISTRATIONS];
+ phys_addr_t mem_base_pa;
+ void __iomem *mem_base_va;
+ struct qmi_handle *wlfw_clnt;
+ struct list_head qmi_event_list;
+ spinlock_t qmi_event_lock;
+ struct work_struct qmi_event_work;
+ struct work_struct qmi_recv_msg_work;
+ struct workqueue_struct *qmi_event_wq;
+ uint32_t state;
+ u32 board_id;
+ u32 num_peers;
+ u32 mac_version;
+ char fw_version[QMI_WLFW_MAX_STR_LEN_V01 + 1];
+} *penv;
+
+static int icnss_qmi_event_post(enum icnss_qmi_event_type type, void *data)
+{
+ struct icnss_qmi_event *event = NULL;
+ unsigned long flags;
+ int gfp = GFP_KERNEL;
+
+ if (in_interrupt() || irqs_disabled())
+ gfp = GFP_ATOMIC;
+
+ event = kzalloc(sizeof(*event), gfp);
+ if (event == NULL)
+ return -ENOMEM;
+
+ event->type = type;
+ event->data = data;
+ spin_lock_irqsave(&penv->qmi_event_lock, flags);
+ list_add_tail(&event->list, &penv->qmi_event_list);
+ spin_unlock_irqrestore(&penv->qmi_event_lock, flags);
+
+ queue_work(penv->qmi_event_wq, &penv->qmi_event_work);
+
+ return 0;
+}
+
+static int wlfw_ind_register_send_sync_msg(void)
+{
+ int ret;
+ struct wlfw_ind_register_req_msg_v01 req;
+ struct wlfw_ind_register_resp_msg_v01 resp;
+ struct msg_desc req_desc, resp_desc;
+
+ if (!penv || !penv->wlfw_clnt) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ memset(&req, 0, sizeof(req));
+ memset(&resp, 0, sizeof(resp));
+
+ req.fw_ready_enable_valid = 1;
+ req.fw_ready_enable = 1;
+
+ req_desc.max_msg_len = WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN;
+ req_desc.msg_id = QMI_WLFW_IND_REGISTER_REQ_V01;
+ req_desc.ei_array = wlfw_ind_register_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = WLFW_IND_REGISTER_RESP_MSG_V01_MAX_MSG_LEN;
+ resp_desc.msg_id = QMI_WLFW_IND_REGISTER_RESP_V01;
+ resp_desc.ei_array = wlfw_ind_register_resp_msg_v01_ei;
+
+ ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
+ &resp_desc, &resp, sizeof(resp),
+ WLFW_TIMEOUT_MS);
+ if (ret < 0) {
+ pr_err("%s: send req failed %d\n", __func__, ret);
+ goto out;
+ }
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("%s: QMI request failed %d %d\n",
+ __func__, resp.resp.result, resp.resp.error);
+ ret = resp.resp.result;
+ goto out;
+ }
+out:
+ return ret;
+}
+
+static int wlfw_cap_send_sync_msg(void)
+{
+ int ret;
+ struct wlfw_cap_req_msg_v01 req;
+ struct wlfw_cap_resp_msg_v01 resp;
+ struct msg_desc req_desc, resp_desc;
+
+ if (!penv || !penv->wlfw_clnt) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ memset(&resp, 0, sizeof(resp));
+
+ req_desc.max_msg_len = WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN;
+ req_desc.msg_id = QMI_WLFW_CAP_REQ_V01;
+ req_desc.ei_array = wlfw_cap_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN;
+ resp_desc.msg_id = QMI_WLFW_CAP_RESP_V01;
+ resp_desc.ei_array = wlfw_cap_resp_msg_v01_ei;
+
+ ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
+ &resp_desc, &resp, sizeof(resp),
+ WLFW_TIMEOUT_MS);
+ if (ret < 0) {
+ pr_err("%s: send req failed %d\n", __func__, ret);
+ goto out;
+ }
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("%s: QMI request failed %d %d\n",
+ __func__, resp.resp.result, resp.resp.error);
+ ret = resp.resp.result;
+ goto out;
+ }
+
+ /* store cap locally */
+ if (resp.board_id_valid)
+ penv->board_id = resp.board_id;
+ if (resp.num_peers_valid)
+ penv->num_peers = resp.num_peers;
+ if (resp.mac_version_valid)
+ penv->mac_version = resp.mac_version;
+ if (resp.fw_version_valid)
+ strlcpy(penv->fw_version, resp.fw_version,
+ QMI_WLFW_MAX_STR_LEN_V01 + 1);
+
+ pr_debug("%s: board_id:0x%0x num_peers: %d mac_version: 0x%0x fw_version: %s",
+ __func__, penv->board_id, penv->num_peers,
+ penv->mac_version, penv->fw_version);
+out:
+ return ret;
+}
+
+static int wlfw_wlan_mode_send_sync_msg(enum wlfw_driver_mode_enum_v01 mode)
+{
+ int ret;
+ struct wlfw_wlan_mode_req_msg_v01 req;
+ struct wlfw_wlan_mode_resp_msg_v01 resp;
+ struct msg_desc req_desc, resp_desc;
+
+ if (!penv || !penv->wlfw_clnt) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ memset(&req, 0, sizeof(req));
+ memset(&resp, 0, sizeof(resp));
+
+ req.mode = mode;
+
+ req_desc.max_msg_len = WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN;
+ req_desc.msg_id = QMI_WLFW_WLAN_MODE_REQ_V01;
+ req_desc.ei_array = wlfw_wlan_mode_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = WLFW_WLAN_MODE_RESP_MSG_V01_MAX_MSG_LEN;
+ resp_desc.msg_id = QMI_WLFW_WLAN_MODE_RESP_V01;
+ resp_desc.ei_array = wlfw_wlan_mode_resp_msg_v01_ei;
+
+ ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
+ &resp_desc, &resp, sizeof(resp),
+ WLFW_TIMEOUT_MS);
+ if (ret < 0) {
+ pr_err("%s: send req failed %d\n", __func__, ret);
+ goto out;
+ }
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("%s: QMI request failed %d %d\n",
+ __func__, resp.resp.result, resp.resp.error);
+ ret = resp.resp.result;
+ goto out;
+ }
+out:
+ return ret;
+}
+
+static int wlfw_wlan_cfg_send_sync_msg(struct wlfw_wlan_cfg_req_msg_v01 *data)
+{
+ int ret;
+ struct wlfw_wlan_cfg_req_msg_v01 req;
+ struct wlfw_wlan_cfg_resp_msg_v01 resp;
+ struct msg_desc req_desc, resp_desc;
+
+ if (!penv || !penv->wlfw_clnt) {
+ return -ENODEV;
+ goto out;
+ }
+
+ memset(&req, 0, sizeof(req));
+ memset(&resp, 0, sizeof(resp));
+
+ memcpy(&req, data, sizeof(req));
+
+ req_desc.max_msg_len = WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN;
+ req_desc.msg_id = QMI_WLFW_WLAN_CFG_REQ_V01;
+ req_desc.ei_array = wlfw_wlan_cfg_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = WLFW_WLAN_CFG_RESP_MSG_V01_MAX_MSG_LEN;
+ resp_desc.msg_id = QMI_WLFW_WLAN_CFG_RESP_V01;
+ resp_desc.ei_array = wlfw_wlan_cfg_resp_msg_v01_ei;
+
+ ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
+ &resp_desc, &resp, sizeof(resp),
+ WLFW_TIMEOUT_MS);
+ if (ret < 0) {
+ pr_err("%s: send req failed %d\n", __func__, ret);
+ goto out;
+ }
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("%s: QMI request failed %d %d\n",
+ __func__, resp.resp.result, resp.resp.error);
+ ret = resp.resp.result;
+ goto out;
+ }
+out:
+ return ret;
+}
+
+static void icnss_qmi_wlfw_clnt_notify_work(struct work_struct *work)
+{
+ int ret;
+
+ if (!penv || !penv->wlfw_clnt)
+ return;
+
+ do {
+ pr_debug("%s: Received Event\n", __func__);
+ } while ((ret = qmi_recv_msg(penv->wlfw_clnt)) == 0);
+
+ if (ret != -ENOMSG)
+ pr_err("%s: Error receiving message\n", __func__);
+}
+
+static void icnss_qmi_wlfw_clnt_notify(struct qmi_handle *handle,
+ enum qmi_event_type event, void *notify_priv)
+{
+ if (!penv || !penv->wlfw_clnt)
+ return;
+
+ switch (event) {
+ case QMI_RECV_MSG:
+ schedule_work(&penv->qmi_recv_msg_work);
+ break;
+ default:
+ pr_debug("%s: Received Event: %d\n", __func__, event);
+ break;
+ }
+}
+
+static void icnss_qmi_wlfw_clnt_ind(struct qmi_handle *handle,
+ unsigned int msg_id, void *msg,
+ unsigned int msg_len, void *ind_cb_priv)
+{
+ if (!penv)
+ return;
+
+ pr_debug("%s: Received Ind 0x%x\n", __func__, msg_id);
+
+ switch (msg_id) {
+ case QMI_WLFW_FW_READY_IND_V01:
+ icnss_qmi_event_post(ICNSS_QMI_EVENT_FW_READY_IND, NULL);
+ break;
+ default:
+ pr_err("%s: Invalid msg_id 0x%x\n", __func__, msg_id);
+ break;
+ }
+}
+
+static int icnss_qmi_event_server_arrive(void *data)
+{
+ int ret = 0;
+
+ if (!penv)
+ return -ENODEV;
+
+ penv->wlfw_clnt = qmi_handle_create(icnss_qmi_wlfw_clnt_notify, penv);
+ if (!penv->wlfw_clnt) {
+ pr_err("%s: QMI client handle alloc failed\n", __func__);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = qmi_connect_to_service(penv->wlfw_clnt,
+ WLFW_SERVICE_ID_V01,
+ WLFW_SERVICE_VERS_V01,
+ WLFW_SERVICE_INS_ID_V01);
+ if (ret < 0) {
+ pr_err("%s: Server not found : %d\n", __func__, ret);
+ goto fail;
+ }
+
+ ret = qmi_register_ind_cb(penv->wlfw_clnt,
+ icnss_qmi_wlfw_clnt_ind, penv);
+ if (ret < 0) {
+ pr_err("Failed to register indication callback: %d\n",
+ ret);
+ goto fail;
+ }
+
+ penv->state |= ICNSS_WLFW_QMI_CONNECTED;
+
+ pr_info("%s: QMI Server Connected\n", __func__);
+
+ ret = wlfw_ind_register_send_sync_msg();
+ if (ret < 0) {
+ pr_err("Failed to send indication message: %d\n",
+ ret);
+ goto out;
+ }
+
+ ret = wlfw_cap_send_sync_msg();
+ if (ret < 0) {
+ pr_err("Failed to get capability: %d\n",
+ ret);
+ goto out;
+ }
+ return ret;
+fail:
+ qmi_handle_destroy(penv->wlfw_clnt);
+ penv->wlfw_clnt = NULL;
+out:
+ ICNSS_ASSERT(0);
+ return ret;
+}
+
+static int icnss_qmi_event_server_exit(void *data)
+{
+ if (!penv || !penv->wlfw_clnt)
+ return -ENODEV;
+
+ pr_info("%s: QMI Service Disconnected\n", __func__);
+
+ qmi_handle_destroy(penv->wlfw_clnt);
+ penv->state = 0;
+ penv->wlfw_clnt = NULL;
+
+ return 0;
+}
+
+static int icnss_qmi_event_fw_ready_ind(void *data)
+{
+ int ret = 0;
+
+ if (!penv)
+ return -ENODEV;
+
+ penv->state |= ICNSS_FW_READY;
+
+ if (!penv->pdev) {
+ pr_err("%s: Device is not ready\n", __func__);
+ ret = -ENODEV;
+ goto out;
+ }
+ if (!penv->ops || !penv->ops->probe) {
+ pr_err("%s: WLAN driver is not registed yet\n", __func__);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ ret = penv->ops->probe(&penv->pdev->dev);
+ if (ret < 0)
+ pr_err("%s: Driver probe failed: %d\n", __func__, ret);
+out:
+ return ret;
+}
+
+static int icnss_qmi_wlfw_clnt_svc_event_notify(struct notifier_block *this,
+ unsigned long code,
+ void *_cmd)
+{
+ int ret = 0;
+
+ if (!penv)
+ return -ENODEV;
+
+ pr_debug("Event Notify: code: %ld", code);
+
+ switch (code) {
+ case QMI_SERVER_ARRIVE:
+ ret = icnss_qmi_event_post(ICNSS_QMI_EVENT_SERVER_ARRIVE, NULL);
+ break;
+
+ case QMI_SERVER_EXIT:
+ ret = icnss_qmi_event_post(ICNSS_QMI_EVENT_SERVER_EXIT, NULL);
+ break;
+ default:
+ pr_debug("Invalid code: %ld", code);
+ break;
+ }
+ return ret;
+}
+
+static void icnss_qmi_wlfw_event_work(struct work_struct *work)
+{
+ struct icnss_qmi_event *event;
+ unsigned long flags;
+
+ spin_lock_irqsave(&penv->qmi_event_lock, flags);
+
+ while (!list_empty(&penv->qmi_event_list)) {
+ event = list_first_entry(&penv->qmi_event_list,
+ struct icnss_qmi_event, list);
+ list_del(&event->list);
+ spin_unlock_irqrestore(&penv->qmi_event_lock, flags);
+
+ switch (event->type) {
+ case ICNSS_QMI_EVENT_SERVER_ARRIVE:
+ icnss_qmi_event_server_arrive(event->data);
+ break;
+ case ICNSS_QMI_EVENT_SERVER_EXIT:
+ icnss_qmi_event_server_exit(event->data);
+ break;
+ case ICNSS_QMI_EVENT_FW_READY_IND:
+ icnss_qmi_event_fw_ready_ind(event->data);
+ break;
+ default:
+ pr_debug("Invalid Event type: %d", event->type);
+ break;
+ }
+ kfree(event);
+ spin_lock_irqsave(&penv->qmi_event_lock, flags);
+ }
+ spin_unlock_irqrestore(&penv->qmi_event_lock, flags);
+}
+
+static struct notifier_block wlfw_clnt_nb = {
+ .notifier_call = icnss_qmi_wlfw_clnt_svc_event_notify,
+};
+
+int icnss_register_driver(struct icnss_driver_ops *ops)
+{
+ struct platform_device *pdev;
+ int ret = 0;
+
+ if (!penv || !penv->pdev) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ pdev = penv->pdev;
+ if (!pdev) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (penv->ops) {
+ pr_err("icnss: driver already registered\n");
+ ret = -EEXIST;
+ goto out;
+ }
+ penv->ops = ops;
+
+ /* check for all conditions before invoking probe */
+ if (ICNSS_IS_FW_READY(penv->state) && penv->ops->probe)
+ ret = penv->ops->probe(&pdev->dev);
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL(icnss_register_driver);
+
+int icnss_unregister_driver(struct icnss_driver_ops *ops)
+{
+ int ret = 0;
+ struct platform_device *pdev;
+
+ if (!penv || !penv->pdev) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ pdev = penv->pdev;
+ if (!pdev) {
+ ret = -ENODEV;
+ goto out;
+ }
+ if (!penv->ops) {
+ pr_err("icnss: driver not registered\n");
+ ret = -ENOENT;
+ goto out;
+ }
+ if (penv->ops->remove)
+ penv->ops->remove(&pdev->dev);
+
+ penv->ops = NULL;
+out:
+ return ret;
+}
+EXPORT_SYMBOL(icnss_unregister_driver);
+
+int icnss_register_ce_irq(unsigned int ce_id,
+ irqreturn_t (*handler)(int, void *),
+ unsigned long flags, const char *name)
+{
+ int ret = 0;
+ unsigned int irq;
+ struct ce_irq_list *irq_entry;
+
+ if (!penv || !penv->pdev) {
+ ret = -ENODEV;
+ goto out;
+ }
+ if (ce_id >= ICNSS_MAX_IRQ_REGISTRATIONS) {
+ pr_err("icnss: Invalid CE ID %d\n", ce_id);
+ ret = -EINVAL;
+ goto out;
+ }
+ irq = penv->ce_irqs[ce_id];
+ irq_entry = &penv->ce_irq_list[ce_id];
+
+ if (irq_entry->handler || irq_entry->irq) {
+ pr_err("icnss: handler already registered %d\n", irq);
+ ret = -EEXIST;
+ goto out;
+ }
+
+ ret = request_irq(irq, handler, IRQF_SHARED, name, &penv->pdev->dev);
+ if (ret) {
+ pr_err("icnss: IRQ not registered %d\n", irq);
+ ret = -EINVAL;
+ goto out;
+ }
+ irq_entry->irq = irq;
+ irq_entry->handler = handler;
+ pr_debug("icnss: IRQ registered %d\n", irq);
+out:
+ return ret;
+
+}
+EXPORT_SYMBOL(icnss_register_ce_irq);
+
+int icnss_unregister_ce_irq(unsigned int ce_id)
+{
+ int ret = 0;
+ unsigned int irq;
+ struct ce_irq_list *irq_entry;
+
+ if (!penv || !penv->pdev) {
+ ret = -ENODEV;
+ goto out;
+ }
+ irq = penv->ce_irqs[ce_id];
+ irq_entry = &penv->ce_irq_list[ce_id];
+ if (!irq_entry->handler || !irq_entry->irq) {
+ pr_err("icnss: handler not registered %d\n", irq);
+ ret = -EEXIST;
+ goto out;
+ }
+ free_irq(irq, &penv->pdev->dev);
+ irq_entry->irq = 0;
+ irq_entry->handler = NULL;
+out:
+ return ret;
+}
+EXPORT_SYMBOL(icnss_unregister_ce_irq);
+
+int icnss_ce_request_irq(unsigned int ce_id,
+ irqreturn_t (*handler)(int, void *),
+ unsigned long flags, const char *name, void *ctx)
+{
+ int ret = 0;
+ unsigned int irq;
+ struct ce_irq_list *irq_entry;
+
+ if (!penv || !penv->pdev) {
+ ret = -ENODEV;
+ goto out;
+ }
+ if (ce_id >= ICNSS_MAX_IRQ_REGISTRATIONS) {
+ pr_err("icnss: Invalid CE ID %d\n", ce_id);
+ ret = -EINVAL;
+ goto out;
+ }
+ irq = penv->ce_irqs[ce_id];
+ irq_entry = &penv->ce_irq_list[ce_id];
+
+ if (irq_entry->handler || irq_entry->irq) {
+ pr_err("icnss: handler already registered %d\n", irq);
+ ret = -EEXIST;
+ goto out;
+ }
+
+ ret = request_irq(irq, handler, flags, name, ctx);
+ if (ret) {
+ pr_err("icnss: IRQ not registered %d\n", irq);
+ ret = -EINVAL;
+ goto out;
+ }
+ irq_entry->irq = irq;
+ irq_entry->handler = handler;
+ pr_debug("icnss: IRQ registered %d\n", irq);
+out:
+ return ret;
+}
+EXPORT_SYMBOL(icnss_ce_request_irq);
+
+int icnss_ce_free_irq(unsigned int ce_id, void *ctx)
+{
+ int ret = 0;
+ unsigned int irq;
+ struct ce_irq_list *irq_entry;
+
+ if (!penv || !penv->pdev) {
+ ret = -ENODEV;
+ goto out;
+ }
+ irq = penv->ce_irqs[ce_id];
+ irq_entry = &penv->ce_irq_list[ce_id];
+ if (!irq_entry->handler || !irq_entry->irq) {
+ pr_err("icnss: handler not registered %d\n", irq);
+ ret = -EEXIST;
+ goto out;
+ }
+ free_irq(irq, ctx);
+ irq_entry->irq = 0;
+ irq_entry->handler = NULL;
+out:
+ return ret;
+}
+EXPORT_SYMBOL(icnss_ce_free_irq);
+
+void icnss_enable_irq(unsigned int ce_id)
+{
+ unsigned int irq;
+
+ if (!penv || !penv->pdev) {
+ pr_err("icnss: platform driver not initialized\n");
+ return;
+ }
+ irq = penv->ce_irqs[ce_id];
+ enable_irq(irq);
+}
+EXPORT_SYMBOL(icnss_enable_irq);
+
+void icnss_disable_irq(unsigned int ce_id)
+{
+ unsigned int irq;
+
+ if (!penv || !penv->pdev) {
+ pr_err("icnss: platform driver not initialized\n");
+ return;
+ }
+ irq = penv->ce_irqs[ce_id];
+ disable_irq(irq);
+}
+EXPORT_SYMBOL(icnss_disable_irq);
+
+int icnss_get_soc_info(struct icnss_soc_info *info)
+{
+ if (!penv) {
+ pr_err("icnss: platform driver not initialized\n");
+ return -EINVAL;
+ }
+
+ info->v_addr = penv->mem_base_va;
+ info->p_addr = penv->mem_base_pa;
+
+ return 0;
+}
+EXPORT_SYMBOL(icnss_get_soc_info);
+
+int icnss_wlan_enable(struct icnss_wlan_enable_cfg *config,
+ enum icnss_driver_mode mode,
+ const char *host_version)
+{
+ struct wlfw_wlan_cfg_req_msg_v01 req;
+ u32 i;
+ int ret;
+
+ memset(&req, 0, sizeof(req));
+
+ if (mode == ICNSS_WALTEST)
+ goto skip;
+ else if (!config || !host_version) {
+ pr_err("%s: Invalid cfg pointer\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ req.host_version_valid = 1;
+ strlcpy(req.host_version, host_version,
+ QMI_WLFW_MAX_STR_LEN_V01 + 1);
+
+ req.tgt_cfg_valid = 1;
+ if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01)
+ req.tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
+ else
+ req.tgt_cfg_len = config->num_ce_tgt_cfg;
+ for (i = 0; i < req.tgt_cfg_len; i++) {
+ req.tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num;
+ req.tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir;
+ req.tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries;
+ req.tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max;
+ req.tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags;
+ }
+
+ req.svc_cfg_valid = 1;
+ if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01)
+ req.svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01;
+ else
+ req.svc_cfg_len = config->num_ce_svc_pipe_cfg;
+ for (i = 0; i < req.svc_cfg_len; i++) {
+ req.svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id;
+ req.svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
+ req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
+ }
+
+ req.shadow_reg_valid = 1;
+ if (config->num_shadow_reg_cfg >
+ QMI_WLFW_MAX_NUM_SHADOW_REG_V01)
+ req.shadow_reg_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V01;
+ else
+ req.shadow_reg_len = config->num_shadow_reg_cfg;
+
+ memcpy(req.shadow_reg, config->shadow_reg_cfg,
+ sizeof(struct wlfw_shadow_reg_cfg_s_v01) * req.shadow_reg_len);
+
+ ret = wlfw_wlan_cfg_send_sync_msg(&req);
+ if (ret) {
+ pr_err("%s: Failed to send cfg, ret = %d\n", __func__, ret);
+ goto out;
+ }
+skip:
+ ret = wlfw_wlan_mode_send_sync_msg(mode);
+ if (ret)
+ pr_err("%s: Failed to send mode, ret = %d\n", __func__, ret);
+out:
+ return ret;
+}
+EXPORT_SYMBOL(icnss_wlan_enable);
+
+int icnss_wlan_disable(enum icnss_driver_mode mode)
+{
+ return wlfw_wlan_mode_send_sync_msg(QMI_WLFW_OFF_V01);
+}
+EXPORT_SYMBOL(icnss_wlan_disable);
+
+int icnss_get_ce_id(int irq)
+{
+ int i;
+
+ for (i = 0; i < ICNSS_MAX_IRQ_REGISTRATIONS; i++) {
+ if (penv->ce_irqs[i] == irq)
+ return i;
+ }
+ pr_err("icnss: No matching CE id for irq %d\n", irq);
+ return -EINVAL;
+}
+EXPORT_SYMBOL(icnss_get_ce_id);
+
+static int icnss_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct resource *res;
+ int i;
+
+ if (penv)
+ return -EEXIST;
+
+ penv = devm_kzalloc(&pdev->dev, sizeof(*penv), GFP_KERNEL);
+ if (!penv)
+ return -ENOMEM;
+
+ penv->pdev = pdev;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "membase");
+ if (!res) {
+ pr_err("icnss: Memory base not found\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ penv->mem_base_pa = res->start;
+ penv->mem_base_va = ioremap(penv->mem_base_pa, resource_size(res));
+ if (!penv->mem_base_va) {
+ pr_err("icnss: ioremap failed\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < ICNSS_MAX_IRQ_REGISTRATIONS; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!res) {
+ pr_err("icnss: Fail to get IRQ-%d\n", i);
+ ret = -ENODEV;
+ goto out;
+ } else {
+ penv->ce_irqs[i] = res->start;
+ }
+ }
+
+ penv->qmi_event_wq = alloc_workqueue("icnss_qmi_event", 0, 0);
+ if (!penv->qmi_event_wq) {
+ pr_err("%s: workqueue creation failed\n", __func__);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ INIT_WORK(&penv->qmi_event_work, icnss_qmi_wlfw_event_work);
+ INIT_WORK(&penv->qmi_recv_msg_work, icnss_qmi_wlfw_clnt_notify_work);
+ INIT_LIST_HEAD(&penv->qmi_event_list);
+
+ ret = qmi_svc_event_notifier_register(WLFW_SERVICE_ID_V01,
+ WLFW_SERVICE_VERS_V01,
+ WLFW_SERVICE_INS_ID_V01,
+ &wlfw_clnt_nb);
+ if (ret < 0) {
+ pr_err("%s: notifier register failed\n", __func__);
+ destroy_workqueue(penv->qmi_event_wq);
+ goto out;
+ }
+
+ pr_debug("icnss: Platform driver probed successfully\n");
+out:
+ return ret;
+}
+
+static int icnss_remove(struct platform_device *pdev)
+{
+ qmi_svc_event_notifier_unregister(WLFW_SERVICE_ID_V01,
+ WLFW_SERVICE_VERS_V01,
+ WLFW_SERVICE_INS_ID_V01,
+ &wlfw_clnt_nb);
+ if (penv->qmi_event_wq)
+ destroy_workqueue(penv->qmi_event_wq);
+
+ return 0;
+}
+
+
+static const struct of_device_id icnss_dt_match[] = {
+ {.compatible = "qcom,icnss"},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, icnss_dt_match);
+
+static struct platform_driver icnss_driver = {
+ .probe = icnss_probe,
+ .remove = icnss_remove,
+ .driver = {
+ .name = "icnss",
+ .owner = THIS_MODULE,
+ .of_match_table = icnss_dt_match,
+ },
+};
+
+static int __init icnss_initialize(void)
+{
+ return platform_driver_register(&icnss_driver);
+}
+
+static void __exit icnss_exit(void)
+{
+ platform_driver_unregister(&icnss_driver);
+}
+
+
+module_init(icnss_initialize);
+module_exit(icnss_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION(DEVICE "iCNSS CORE platform driver");
diff --git a/drivers/soc/qcom/wlan_firmware_service_v01.c b/drivers/soc/qcom/wlan_firmware_service_v01.c
new file mode 100644
index 000000000000..b514f3f7c6cd
--- /dev/null
+++ b/drivers/soc/qcom/wlan_firmware_service_v01.c
@@ -0,0 +1,978 @@
+ /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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/qmi_encdec.h>
+
+#include <soc/qcom/msm_qmi_interface.h>
+
+#include "wlan_firmware_service_v01.h"
+
+static struct elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01,
+ pipe_num),
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum wlfw_pipedir_enum_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01,
+ pipe_dir),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01,
+ nentries),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01,
+ nbytes_max),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01,
+ flags),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static struct elem_info wlfw_ce_svc_pipe_cfg_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01,
+ service_id),
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum wlfw_pipedir_enum_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01,
+ pipe_dir),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01,
+ pipe_num),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static struct elem_info wlfw_shadow_reg_cfg_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint16_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_shadow_reg_cfg_s_v01,
+ id),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint16_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_shadow_reg_cfg_s_v01,
+ offset),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_ind_register_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ fw_ready_enable_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ fw_ready_enable),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ initiate_cal_download_enable_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ initiate_cal_download_enable),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ initiate_cal_update_enable_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ initiate_cal_update_enable),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_ind_register_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_ind_register_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_fw_ready_ind_msg_v01_ei[] = {
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_wlan_mode_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum wlfw_driver_mode_enum_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01,
+ mode),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_wlan_mode_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_wlan_mode_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ host_version_valid),
+ },
+ {
+ .data_type = QMI_STRING,
+ .elem_len = QMI_WLFW_MAX_STR_LEN_V01 + 1,
+ .elem_size = sizeof(char),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ host_version),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ tgt_cfg_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ tgt_cfg_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = QMI_WLFW_MAX_NUM_CE_V01,
+ .elem_size = sizeof(struct wlfw_ce_tgt_pipe_cfg_s_v01),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ tgt_cfg),
+ .ei_array = wlfw_ce_tgt_pipe_cfg_s_v01_ei,
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ svc_cfg_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ svc_cfg_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = QMI_WLFW_MAX_NUM_SVC_V01,
+ .elem_size = sizeof(struct wlfw_ce_svc_pipe_cfg_s_v01),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ svc_cfg),
+ .ei_array = wlfw_ce_svc_pipe_cfg_s_v01_ei,
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ shadow_reg_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ shadow_reg_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V01,
+ .elem_size = sizeof(struct wlfw_shadow_reg_cfg_s_v01),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ shadow_reg),
+ .ei_array = wlfw_shadow_reg_cfg_s_v01_ei,
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_wlan_cfg_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_wlan_cfg_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_cap_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_cap_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ board_id_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ board_id),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ num_peers_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ num_peers),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ mac_version_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ mac_version),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ fw_version_valid),
+ },
+ {
+ .data_type = QMI_STRING,
+ .elem_len = QMI_WLFW_MAX_STR_LEN_V01 + 1,
+ .elem_size = sizeof(char),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ fw_version),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_bdf_download_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ valid),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ file_id_valid),
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ file_id),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ total_size_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ total_size),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ seg_id_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ seg_id),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ data_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint16_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ data_len),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01,
+ .elem_size = sizeof(uint8_t),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ data),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x14,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ end_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x14,
+ .offset = offsetof(struct wlfw_bdf_download_req_msg_v01,
+ end),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_bdf_download_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_bdf_download_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_cal_report_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct wlfw_cal_report_req_msg_v01,
+ meta_data_len),
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = QMI_WLFW_MAX_NUM_CAL_V01,
+ .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct wlfw_cal_report_req_msg_v01,
+ meta_data),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_cal_report_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_cal_report_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = {
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct wlfw_initiate_cal_download_ind_msg_v01,
+ cal_id),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_cal_download_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ valid),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ file_id_valid),
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ file_id),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ total_size_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ total_size),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ seg_id_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ seg_id),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ data_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint16_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ data_len),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01,
+ .elem_size = sizeof(uint8_t),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ data),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x14,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ end_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x14,
+ .offset = offsetof(struct wlfw_cal_download_req_msg_v01,
+ end),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_cal_download_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_cal_download_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[] = {
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct wlfw_initiate_cal_update_ind_msg_v01,
+ cal_id),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_initiate_cal_update_ind_msg_v01,
+ total_size),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_cal_update_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct wlfw_cal_update_req_msg_v01,
+ cal_id),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_cal_update_req_msg_v01,
+ seg_id),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_cal_update_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ file_id_valid),
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ file_id),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ total_size_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ total_size),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ seg_id_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ seg_id),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ data_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint16_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ data_len),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01,
+ .elem_size = sizeof(uint8_t),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ data),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x14,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ end_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x14,
+ .offset = offsetof(struct wlfw_cal_update_resp_msg_v01,
+ end),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
diff --git a/drivers/soc/qcom/wlan_firmware_service_v01.h b/drivers/soc/qcom/wlan_firmware_service_v01.h
new file mode 100644
index 000000000000..62b7183e2141
--- /dev/null
+++ b/drivers/soc/qcom/wlan_firmware_service_v01.h
@@ -0,0 +1,274 @@
+ /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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 WLAN_FIRMWARE_SERVICE_V01_H
+#define WLAN_FIRMWARE_SERVICE_V01_H
+
+#define WLFW_SERVICE_ID_V01 0x45
+#define WLFW_SERVICE_VERS_V01 0x01
+
+#define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026
+#define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026
+#define QMI_WLFW_CAP_RESP_V01 0x0024
+#define QMI_WLFW_BDF_DOWNLOAD_REQ_V01 0x0025
+#define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027
+#define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022
+#define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029
+#define QMI_WLFW_BDF_DOWNLOAD_RESP_V01 0x0025
+#define QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01 0x002A
+#define QMI_WLFW_FW_READY_IND_V01 0x0021
+#define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028
+#define QMI_WLFW_CAP_REQ_V01 0x0024
+#define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027
+#define QMI_WLFW_WLAN_MODE_REQ_V01 0x0022
+#define QMI_WLFW_CAL_UPDATE_REQ_V01 0x0029
+#define QMI_WLFW_IND_REGISTER_REQ_V01 0x0020
+#define QMI_WLFW_WLAN_CFG_RESP_V01 0x0023
+#define QMI_WLFW_WLAN_CFG_REQ_V01 0x0023
+#define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020
+
+#define QMI_WLFW_MAX_NUM_CAL_V01 5
+#define QMI_WLFW_MAX_DATA_SIZE_V01 6144
+#define QMI_WLFW_MAX_NUM_CE_V01 12
+#define QMI_WLFW_MAX_STR_LEN_V01 16
+#define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24
+#define QMI_WLFW_MAX_NUM_SVC_V01 24
+
+enum wlfw_driver_mode_enum_v01 {
+ WLFW_DRIVER_MODE_ENUM_MIN_VAL_V01 = INT_MIN,
+ QMI_WLFW_MISSION_V01 = 0,
+ QMI_WLFW_FTM_V01 = 1,
+ QMI_WLFW_EPPING_V01 = 2,
+ QMI_WLFW_WALTEST_V01 = 3,
+ QMI_WLFW_OFF_V01 = 4,
+ WLFW_DRIVER_MODE_ENUM_MAX_VAL_V01 = INT_MAX,
+};
+
+enum wlfw_cal_temp_id_enum_v01 {
+ WLFW_CAL_TEMP_ID_ENUM_MIN_VAL_V01 = INT_MIN,
+ QMI_WLFW_CAL_TEMP_IDX_0_V01 = 0,
+ QMI_WLFW_CAL_TEMP_IDX_1_V01 = 1,
+ QMI_WLFW_CAL_TEMP_IDX_2_V01 = 2,
+ QMI_WLFW_CAL_TEMP_IDX_3_V01 = 3,
+ QMI_WLFW_CAL_TEMP_IDX_4_V01 = 4,
+ WLFW_CAL_TEMP_ID_ENUM_MAX_VAL_V01 = INT_MAX,
+};
+
+enum wlfw_pipedir_enum_v01 {
+ WLFW_PIPEDIR_ENUM_MIN_VAL_V01 = INT_MIN,
+ QMI_WLFW_PIPEDIR_NONE_V01 = 0,
+ QMI_WLFW_PIPEDIR_IN_V01 = 1,
+ QMI_WLFW_PIPEDIR_OUT_V01 = 2,
+ QMI_WLFW_PIPEDIR_INOUT_V01 = 3,
+ WLFW_PIPEDIR_ENUM_MAX_VAL_V01 = INT_MAX,
+};
+
+#define QMI_WLFW_CE_ATTR_FLAGS_V01 ((uint32_t)0x00)
+#define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((uint32_t)0x01)
+#define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((uint32_t)0x02)
+#define QMI_WLFW_CE_ATTR_SWIZZLE_DESCRIPTORS_V01 ((uint32_t)0x04)
+#define QMI_WLFW_CE_ATTR_DISABLE_INTR_V01 ((uint32_t)0x08)
+#define QMI_WLFW_CE_ATTR_ENABLE_POLL_V01 ((uint32_t)0x10)
+
+struct wlfw_ce_tgt_pipe_cfg_s_v01 {
+ uint32_t pipe_num;
+ enum wlfw_pipedir_enum_v01 pipe_dir;
+ uint32_t nentries;
+ uint32_t nbytes_max;
+ uint32_t flags;
+};
+
+struct wlfw_ce_svc_pipe_cfg_s_v01 {
+ uint32_t service_id;
+ enum wlfw_pipedir_enum_v01 pipe_dir;
+ uint32_t pipe_num;
+};
+
+struct wlfw_shadow_reg_cfg_s_v01 {
+ uint16_t id;
+ uint16_t offset;
+};
+
+struct wlfw_ind_register_req_msg_v01 {
+ uint8_t fw_ready_enable_valid;
+ uint8_t fw_ready_enable;
+ uint8_t initiate_cal_download_enable_valid;
+ uint8_t initiate_cal_download_enable;
+ uint8_t initiate_cal_update_enable_valid;
+ uint8_t initiate_cal_update_enable;
+};
+#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 12
+extern struct elem_info wlfw_ind_register_req_msg_v01_ei[];
+
+struct wlfw_ind_register_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+#define WLFW_IND_REGISTER_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct elem_info wlfw_ind_register_resp_msg_v01_ei[];
+
+struct wlfw_fw_ready_ind_msg_v01 {
+ char placeholder;
+};
+#define WLFW_FW_READY_IND_MSG_V01_MAX_MSG_LEN 0
+extern struct elem_info wlfw_fw_ready_ind_msg_v01_ei[];
+
+struct wlfw_wlan_mode_req_msg_v01 {
+ enum wlfw_driver_mode_enum_v01 mode;
+};
+#define WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN 7
+extern struct elem_info wlfw_wlan_mode_req_msg_v01_ei[];
+
+struct wlfw_wlan_mode_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+#define WLFW_WLAN_MODE_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct elem_info wlfw_wlan_mode_resp_msg_v01_ei[];
+
+struct wlfw_wlan_cfg_req_msg_v01 {
+ uint8_t host_version_valid;
+ char host_version[QMI_WLFW_MAX_STR_LEN_V01 + 1];
+ uint8_t tgt_cfg_valid;
+ uint32_t tgt_cfg_len;
+ struct wlfw_ce_tgt_pipe_cfg_s_v01 tgt_cfg[QMI_WLFW_MAX_NUM_CE_V01];
+ uint8_t svc_cfg_valid;
+ uint32_t svc_cfg_len;
+ struct wlfw_ce_svc_pipe_cfg_s_v01 svc_cfg[QMI_WLFW_MAX_NUM_SVC_V01];
+ uint8_t shadow_reg_valid;
+ uint32_t shadow_reg_len;
+ struct wlfw_shadow_reg_cfg_s_v01 shadow_reg[QMI_WLFW_MAX_NUM_SHADOW_REG_V01];
+};
+#define WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN 655
+extern struct elem_info wlfw_wlan_cfg_req_msg_v01_ei[];
+
+struct wlfw_wlan_cfg_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+#define WLFW_WLAN_CFG_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct elem_info wlfw_wlan_cfg_resp_msg_v01_ei[];
+
+struct wlfw_cap_req_msg_v01 {
+ char placeholder;
+};
+#define WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN 0
+extern struct elem_info wlfw_cap_req_msg_v01_ei[];
+
+struct wlfw_cap_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+ uint8_t board_id_valid;
+ uint32_t board_id;
+ uint8_t num_peers_valid;
+ uint32_t num_peers;
+ uint8_t mac_version_valid;
+ uint32_t mac_version;
+ uint8_t fw_version_valid;
+ char fw_version[QMI_WLFW_MAX_STR_LEN_V01 + 1];
+};
+#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 47
+extern struct elem_info wlfw_cap_resp_msg_v01_ei[];
+
+struct wlfw_bdf_download_req_msg_v01 {
+ uint8_t valid;
+ uint8_t file_id_valid;
+ enum wlfw_cal_temp_id_enum_v01 file_id;
+ uint8_t total_size_valid;
+ uint32_t total_size;
+ uint8_t seg_id_valid;
+ uint32_t seg_id;
+ uint8_t data_valid;
+ uint32_t data_len;
+ uint8_t data[QMI_WLFW_MAX_DATA_SIZE_V01];
+ uint8_t end_valid;
+ uint8_t end;
+};
+#define WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6178
+extern struct elem_info wlfw_bdf_download_req_msg_v01_ei[];
+
+struct wlfw_bdf_download_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+#define WLFW_BDF_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct elem_info wlfw_bdf_download_resp_msg_v01_ei[];
+
+struct wlfw_cal_report_req_msg_v01 {
+ uint32_t meta_data_len;
+ enum wlfw_cal_temp_id_enum_v01 meta_data[QMI_WLFW_MAX_NUM_CAL_V01];
+};
+#define WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN 24
+extern struct elem_info wlfw_cal_report_req_msg_v01_ei[];
+
+struct wlfw_cal_report_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+#define WLFW_CAL_REPORT_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct elem_info wlfw_cal_report_resp_msg_v01_ei[];
+
+struct wlfw_initiate_cal_download_ind_msg_v01 {
+ enum wlfw_cal_temp_id_enum_v01 cal_id;
+};
+#define WLFW_INITIATE_CAL_DOWNLOAD_IND_MSG_V01_MAX_MSG_LEN 7
+extern struct elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[];
+
+struct wlfw_cal_download_req_msg_v01 {
+ uint8_t valid;
+ uint8_t file_id_valid;
+ enum wlfw_cal_temp_id_enum_v01 file_id;
+ uint8_t total_size_valid;
+ uint32_t total_size;
+ uint8_t seg_id_valid;
+ uint32_t seg_id;
+ uint8_t data_valid;
+ uint32_t data_len;
+ uint8_t data[QMI_WLFW_MAX_DATA_SIZE_V01];
+ uint8_t end_valid;
+ uint8_t end;
+};
+#define WLFW_CAL_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6178
+extern struct elem_info wlfw_cal_download_req_msg_v01_ei[];
+
+struct wlfw_cal_download_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+#define WLFW_CAL_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct elem_info wlfw_cal_download_resp_msg_v01_ei[];
+
+struct wlfw_initiate_cal_update_ind_msg_v01 {
+ enum wlfw_cal_temp_id_enum_v01 cal_id;
+ uint32_t total_size;
+};
+#define WLFW_INITIATE_CAL_UPDATE_IND_MSG_V01_MAX_MSG_LEN 14
+extern struct elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[];
+
+struct wlfw_cal_update_req_msg_v01 {
+ enum wlfw_cal_temp_id_enum_v01 cal_id;
+ uint32_t seg_id;
+};
+#define WLFW_CAL_UPDATE_REQ_MSG_V01_MAX_MSG_LEN 14
+extern struct elem_info wlfw_cal_update_req_msg_v01_ei[];
+
+struct wlfw_cal_update_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+ uint8_t file_id_valid;
+ enum wlfw_cal_temp_id_enum_v01 file_id;
+ uint8_t total_size_valid;
+ uint32_t total_size;
+ uint8_t seg_id_valid;
+ uint32_t seg_id;
+ uint8_t data_valid;
+ uint32_t data_len;
+ uint8_t data[QMI_WLFW_MAX_DATA_SIZE_V01];
+ uint8_t end_valid;
+ uint8_t end;
+};
+#define WLFW_CAL_UPDATE_RESP_MSG_V01_MAX_MSG_LEN 6181
+extern struct elem_info wlfw_cal_update_resp_msg_v01_ei[];
+
+#endif