#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
-#include <linux/regulator/rpm-smd-regulator.h>
#include <linux/workqueue.h>
#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/clk.h>
-#include <soc/qcom/smd.h>
-#include <soc/qcom/smsm.h>
+#include <linux/remoteproc.h>
+#include <linux/soc/qcom/smd.h>
#include "wcn36xx.h"
#include "wcnss_core.h"
-#include <soc/qcom/subsystem_restart.h>
-#include <soc/qcom/subsystem_notif.h>
-
#define MAC_ADDR_0 "wlan/macaddr0"
-static void *pil;
-
-struct wcn36xx_msm {
- struct wcn36xx_platform_ctrl_ops ctrl_ops;
- struct platform_device *core;
- void *drv_priv;
- void (*rsp_cb)(void *drv_priv, void *buf, size_t len);
- /* SMD related */
- struct workqueue_struct *wq;
- struct work_struct smd_work;
- struct completion smd_compl;
- smd_channel_t *smd_ch;
- struct pinctrl *pinctrl;
- enum wcn36xx_chip_type chip_type;
-};
-
-static struct wcn36xx_msm wmsm;
-
static int wcn36xx_msm_smsm_change_state(u32 clear_mask, u32 set_mask)
{
- return smsm_change_state(SMSM_APPS_STATE, clear_mask, set_mask);
+ return 0;
}
-static int wcn36xx_msm_get_hw_mac(u8 *addr)
+static int wcn36xx_msm_get_hw_mac(struct wcn36xx *wcn, u8 *addr)
{
const struct firmware *addr_file = NULL;
int status;
u8 tmp[18];
static const u8 qcom_oui[3] = {0x00, 0x0A, 0xF5};
static const char *files = {MAC_ADDR_0};
+ struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data;
- status = request_firmware(&addr_file, files, &wmsm.core->dev);
+ status = request_firmware(&addr_file, files, &pdata->core->dev);
if (status < 0) {
/* Assign a random mac with Qualcomm oui */
- dev_err(&wmsm.core->dev, "Failed (%d) to read macaddress file %s, using a random address instead", status,
- files);
+ dev_err(&pdata->core->dev, "Failed (%d) to read macaddress"
+ "file %s, using a random address instead", status, files);
memcpy(addr, qcom_oui, 3);
get_random_bytes(addr + 3, 3);
} else {
return 0;
}
-static int wcn36xx_msm_smd_send_and_wait(char *buf, size_t len)
+static int wcn36xx_msm_smd_send_and_wait(struct wcn36xx *wcn, char *buf, size_t len)
{
- int avail;
int ret = 0;
+ struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data;
- avail = smd_write_avail(wmsm.smd_ch);
-
- if (avail >= len) {
- avail = smd_write(wmsm.smd_ch, buf, len);
- if (avail != len) {
- dev_err(&wmsm.core->dev,
- "Cannot write to SMD channel\n");
- ret = -EAGAIN;
- goto out;
- }
- } else {
- dev_err(&wmsm.core->dev,
- "SMD channel can accept only %d bytes\n", avail);
- ret = -ENOMEM;
- goto out;
+ mutex_lock(&pdata->wlan_ctrl_lock);
+ ret = qcom_smd_send(pdata->wlan_ctrl_channel, buf, len);
+ if (ret) {
+ dev_err(wcn->dev, "wlan ctrl channel tx failed\n");
}
+ mutex_unlock(&pdata->wlan_ctrl_lock);
-out:
return ret;
}
-static void wcn36xx_msm_smd_notify(void *data, unsigned event)
+static int wcn36xx_msm_smd_open(struct wcn36xx *wcn, void *rsp_cb)
{
- struct wcn36xx_msm *wmsm_priv = (struct wcn36xx_msm *)data;
-
- switch (event) {
- case SMD_EVENT_OPEN:
- complete(&wmsm_priv->smd_compl);
- break;
- case SMD_EVENT_DATA:
- queue_work(wmsm_priv->wq, &wmsm_priv->smd_work);
- break;
- case SMD_EVENT_CLOSE:
- break;
- case SMD_EVENT_STATUS:
- break;
- case SMD_EVENT_REOPEN_READY:
- break;
- default:
- dev_err(&wmsm_priv->core->dev,
- "%s: SMD_EVENT (%d) not supported\n", __func__, event);
- break;
- }
+ struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data;
+
+ pdata->cb = rsp_cb;
+ return 0;
}
-static void wcn36xx_msm_smd_work(struct work_struct *work)
+static void wcn36xx_msm_smd_close(struct wcn36xx *wcn)
{
- int avail;
- int msg_len;
- void *msg;
- int ret;
- struct wcn36xx_msm *wmsm_priv =
- container_of(work, struct wcn36xx_msm, smd_work);
-
- while (1) {
- msg_len = smd_cur_packet_size(wmsm_priv->smd_ch);
- if (0 == msg_len) {
- return;
- }
- avail = smd_read_avail(wmsm_priv->smd_ch);
- if (avail < msg_len) {
- return;
- }
- msg = kmalloc(msg_len, GFP_KERNEL);
- if (NULL == msg) {
- return;
- }
+ return;
+}
- ret = smd_read(wmsm_priv->smd_ch, msg, msg_len);
- if (ret != msg_len) {
- return;
- }
- wmsm_priv->rsp_cb(wmsm_priv->drv_priv, msg, msg_len);
- kfree(msg);
- }
+static int wcn36xx_msm_get_chip_type(struct wcn36xx *wcn)
+{
+ struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data;
+ return pdata->chip_type;
}
-int wcn36xx_msm_smd_open(void *drv_priv, void *rsp_cb)
+static struct wcn36xx_platform_data wcn36xx_data = {
+ .ctrl_ops = {
+ .open = wcn36xx_msm_smd_open,
+ .close = wcn36xx_msm_smd_close,
+ .tx = wcn36xx_msm_smd_send_and_wait,
+ .get_hw_mac = wcn36xx_msm_get_hw_mac,
+ .smsm_change_state = wcn36xx_msm_smsm_change_state,
+ .get_chip_type = wcn36xx_msm_get_chip_type,
+ },
+};
+
+static int qcom_smd_wlan_ctrl_probe(struct qcom_smd_device *sdev)
{
- int ret, left;
- wmsm.drv_priv = drv_priv;
- wmsm.rsp_cb = rsp_cb;
- INIT_WORK(&wmsm.smd_work, wcn36xx_msm_smd_work);
- init_completion(&wmsm.smd_compl);
-
- wmsm.wq = create_workqueue("wcn36xx_msm_smd_wq");
- if (!wmsm.wq) {
- dev_err(&wmsm.core->dev, "failed to allocate wq");
- ret = -ENOMEM;
- return ret;
- }
+ pr_info("%s: enter\n", __func__);
+ mutex_init(&wcn36xx_data.wlan_ctrl_lock);
+ init_completion(&wcn36xx_data.wlan_ctrl_ack);
- ret = smd_named_open_on_edge("WLAN_CTRL", SMD_APPS_WCNSS,
- &wmsm.smd_ch, &wmsm, wcn36xx_msm_smd_notify);
- if (ret) {
- dev_err(&wmsm.core->dev,
- "smd_named_open_on_edge failed: %d\n", ret);
- return ret;
- }
+ wcn36xx_data.sdev = sdev;
- left = wait_for_completion_interruptible_timeout(&wmsm.smd_compl,
- msecs_to_jiffies(HAL_MSG_TIMEOUT));
- if (left <= 0) {
- dev_err(&wmsm.core->dev,
- "timeout waiting for smd open: %d\n", ret);
- return left;
- }
+ dev_set_drvdata(&sdev->dev, &wcn36xx_data);
+ wcn36xx_data.wlan_ctrl_channel = sdev->channel;
- /* Not to receive INT until the whole buf from SMD is read */
- smd_disable_read_intr(wmsm.smd_ch);
+ of_platform_populate(sdev->dev.of_node, NULL, NULL, &sdev->dev);
- return 0;
+ return 0;
}
-void wcn36xx_msm_smd_close(void)
+static void qcom_smd_wlan_ctrl_remove(struct qcom_smd_device *sdev)
{
- smd_close(wmsm.smd_ch);
- flush_workqueue(wmsm.wq);
- destroy_workqueue(wmsm.wq);
+ of_platform_depopulate(&sdev->dev);
}
-int wcn36xx_msm_shutdown(const struct subsys_desc *desc, bool force_stop)
-{
- return 0;
-}
-int wcn36xx_msm_powerup(const struct subsys_desc *desc)
+static int qcom_smd_wlan_ctrl_callback(struct qcom_smd_device *qsdev,
+ const void *data,
+ size_t count)
{
+ struct wcn36xx_platform_data *pdata = dev_get_drvdata(&qsdev->dev);
+ void *buf = kzalloc(count, GFP_ATOMIC);
+ if (!buf) {
+ dev_err(&pdata->core->dev, "can't allocate buffer\n");
+ return -ENOMEM;
+ }
+
+ memcpy_fromio(buf, data, count);
+ pdata->cb(pdata->wcn, buf, count);
+ kfree(buf);
+
return 0;
}
+static const struct of_device_id qcom_smd_wlan_ctrl_of_match[] = {
+ { .compatible = "qcom,wlan-ctrl" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, qcom_smd_wlan_ctrl_of_match);
+
+static struct qcom_smd_driver qcom_smd_wlan_ctrl_driver = {
+ .probe = qcom_smd_wlan_ctrl_probe,
+ .remove = qcom_smd_wlan_ctrl_remove,
+ .callback = qcom_smd_wlan_ctrl_callback,
+ .driver = {
+ .name = "qcom_smd_wlan_ctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = qcom_smd_wlan_ctrl_of_match,
+ },
+};
+
static const struct of_device_id wcn36xx_msm_match_table[] = {
{ .compatible = "qcom,wcn3660", .data = (void *)WCN36XX_CHIP_3660 },
{ .compatible = "qcom,wcn3680", .data = (void *)WCN36XX_CHIP_3680 },
{ .compatible = "qcom,wcn3620", .data = (void *)WCN36XX_CHIP_3620 },
{ }
};
-
-static int wcn36xx_msm_get_chip_type(void)
-{
- return wmsm.chip_type;
-}
-
-static struct wcn36xx_msm wmsm = {
- .ctrl_ops = {
- .open = wcn36xx_msm_smd_open,
- .close = wcn36xx_msm_smd_close,
- .tx = wcn36xx_msm_smd_send_and_wait,
- .get_hw_mac = wcn36xx_msm_get_hw_mac,
- .smsm_change_state = wcn36xx_msm_smsm_change_state,
- .get_chip_type = wcn36xx_msm_get_chip_type,
- },
-};
+MODULE_DEVICE_TABLE(of, wcn36xx_msm_match_table);
static int wcn36xx_msm_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
struct resource *r;
struct resource res[3];
- struct pinctrl_state *ps;
static const char const *rnames[] = {
"wcnss_mmio", "wcnss_wlantx_irq", "wcnss_wlanrx_irq" };
static const int rtype[] = {
IORESOURCE_MEM, IORESOURCE_IRQ, IORESOURCE_IRQ };
+ struct device_node *dn;
int n;
- of_id = of_match_node(wcn36xx_msm_match_table, pdev->dev.of_node);
- if (!of_id)
- return -EINVAL;
-
- wmsm.chip_type = (enum wcn36xx_chip_type)of_id->data;
-
- wmsm.pinctrl = devm_pinctrl_get(&pdev->dev);
- if (IS_ERR_OR_NULL(wmsm.pinctrl))
- return PTR_ERR(wmsm.pinctrl);
+ wcnss_core_prepare(pdev);
- ps = pinctrl_lookup_state(wmsm.pinctrl, "wcnss_default");
- if (IS_ERR_OR_NULL(ps))
- return PTR_ERR(ps);
+ dn = of_parse_phandle(pdev->dev.of_node, "rproc", 0);
+ if (!dn) {
+ dev_err(&pdev->dev, "No rproc specified in DT\n");
+ } else {
+ struct rproc *rproc= rproc_get_by_phandle(dn->phandle);
+ if (rproc)
+ rproc_boot(rproc);
+ else {
+ dev_err(&pdev->dev, "No rproc registered\n");
+ }
+ }
- ret = pinctrl_select_state(wmsm.pinctrl, ps);
- if (ret)
- return ret;
+ qcom_smd_driver_register(&qcom_smd_wlan_ctrl_driver);
+ wcnss_core_init();
- wcnss_core_prepare(pdev);
+ of_id = of_match_node(wcn36xx_msm_match_table, pdev->dev.of_node);
+ if (!of_id)
+ return -EINVAL;
- if (IS_ERR_OR_NULL(pil))
- pil = subsystem_get("wcnss");
- if (IS_ERR_OR_NULL(pil))
- return PTR_ERR(pil);
+ wcn36xx_data.chip_type = (enum wcn36xx_chip_type)of_id->data;
- wmsm.core = platform_device_alloc("wcn36xx", -1);
+ wcn36xx_data.core = platform_device_alloc("wcn36xx", -1);
for (n = 0; n < ARRAY_SIZE(rnames); n++) {
r = platform_get_resource_byname(pdev, rtype[n], rnames[n]);
if (!r) {
- dev_err(&wmsm.core->dev,
+ dev_err(&wcn36xx_data.core->dev,
"Missing resource %s'\n", rnames[n]);
ret = -ENOMEM;
return ret;
res[n] = *r;
}
- platform_device_add_resources(wmsm.core, res, n);
+ platform_device_add_resources(wcn36xx_data.core, res, n);
+ wcn36xx_data.core->dev.platform_data = &wcn36xx_data;
- ret = platform_device_add_data(wmsm.core, &wmsm.ctrl_ops,
- sizeof(wmsm.ctrl_ops));
- if (ret) {
- dev_err(&wmsm.core->dev, "Can't add platform data\n");
- ret = -ENOMEM;
- return ret;
- }
-
- platform_device_add(wmsm.core);
- wcnss_core_init();
+ platform_device_add(wcn36xx_data.core);
dev_info(&pdev->dev, "%s initialized\n", __func__);
static int wcn36xx_msm_remove(struct platform_device *pdev)
{
- struct pinctrl_state *ps;
-
- wcnss_core_deinit();
- platform_device_del(wmsm.core);
- platform_device_put(wmsm.core);
-
- if (wmsm.pinctrl) {
- ps = pinctrl_lookup_state(wmsm.pinctrl, "wcnss_sleep");
- if (IS_ERR_OR_NULL(ps))
- return PTR_ERR(ps);
-
- pinctrl_select_state(wmsm.pinctrl, ps);
- }
-
+ platform_device_del(wcn36xx_data.core);
+ platform_device_put(wcn36xx_data.core);
return 0;
}
-MODULE_DEVICE_TABLE(of, wcn36xx_msm_match_table);
-
static struct platform_driver wcn36xx_msm_driver = {
.probe = wcn36xx_msm_probe,
.remove = wcn36xx_msm_remove,
static void __exit wcn36xx_msm_exit(void)
{
platform_driver_unregister(&wcn36xx_msm_driver);
- if (pil)
- subsystem_put(pil);
}
module_exit(wcn36xx_msm_exit);
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
-#include <linux/regulator/rpm-smd-regulator.h>
#include <linux/workqueue.h>
#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/clk.h>
-#include <soc/qcom/smd.h>
-#include <soc/qcom/smsm.h>
+#include <linux/soc/qcom/smd.h>
#include "wcn36xx.h"
#include "wcnss_core.h"
+#define WCNSS_CTRL_TIMEOUT (msecs_to_jiffies(500))
+
static int wcnss_core_config(struct platform_device *pdev, void __iomem *base)
{
int ret = 0;
- u32 value, iris_read = INVALID_IRIS_REG;
+ u32 value, iris_read_v = INVALID_IRIS_REG;
int clk_48m = 0;
value = readl_relaxed(base + SPARE_OFFSET);
return ret;
}
-static struct wcn36xx_ctrl_nv_data ctrl_nv_data;
-static void wcn36xx_download_notify(void *data, unsigned int event)
-{
- struct wcn36xx_ctrl_nv_data *ctrl_nv_data = data;
-
- switch (event) {
- case SMD_EVENT_OPEN:
- complete(&ctrl_nv_data->smd_open_compl);
- schedule_work(&ctrl_nv_data->download_work);
- break;
- case SMD_EVENT_DATA:
- schedule_work(&ctrl_nv_data->rx_work);
- break;
- case SMD_EVENT_CLOSE:
- case SMD_EVENT_STATUS:
- case SMD_EVENT_REOPEN_READY:
- break;
- default:
- pr_err("%s: SMD_EVENT (%d) not supported\n",
- __func__, event);
- break;
- }
-}
-
-static unsigned char wcnss_fw_status(struct wcn36xx_ctrl_nv_data *data)
-{
- int len = 0;
- int rc = 0;
-
- unsigned char fw_status = 0xFF;
-
- len = smd_read_avail(data->smd_ch);
- if (len < 1) {
- pr_err("%s: invalid firmware status", __func__);
- return fw_status;
- }
-
- rc = smd_read(data->smd_ch, &fw_status, 1);
- if (rc < 0) {
- pr_err("%s: incomplete data read from smd\n", __func__);
- return fw_status;
- }
- return fw_status;
-}
-
-static void wcn36xx_nv_rx_work(struct work_struct *worker)
-{
- struct wcn36xx_ctrl_nv_data *data =
- container_of(worker, struct wcn36xx_ctrl_nv_data, rx_work);
- int len = 0, ret = 0;
- unsigned char buf[sizeof(struct wcnss_version)];
- struct smd_msg_hdr *phdr;
-
- len = smd_read_avail(data->smd_ch);
- if (len > 4096) {
- pr_err("%s: frame larger than allowed size\n", __func__);
- smd_read(data->smd_ch, NULL, len);
- return;
- }
-
- if (len < sizeof(struct smd_msg_hdr))
- return;
-
- ret = smd_read(data->smd_ch, buf, sizeof(struct smd_msg_hdr));
- if (ret < sizeof(struct smd_msg_hdr)) {
- pr_err("%s: incomplete header from smd\n", __func__);
- return;
- }
-
- phdr = (struct smd_msg_hdr *)buf;
+struct wcnss_platform_data {
+ struct qcom_smd_channel *channel;
+ struct completion ack;
+ struct mutex lock;
- switch (phdr->msg_type) {
- case WCNSS_NV_DOWNLOAD_RSP:
- pr_info("fw_status: %d\n", wcnss_fw_status(data));
- break;
- }
- return;
-}
+ struct work_struct rx_work;
+ struct work_struct download_work;
-static int wcn36xx_nv_smd_tx(struct wcn36xx_ctrl_nv_data *nv_data, void *buf, int len)
-{
- int ret = 0;
-
- ret = smd_write_avail(nv_data->smd_ch);
- if (ret < len) {
- pr_err("wcnss: no space available. %d needed. Just %d avail\n",
- len, ret);
- return -ENOSPC;
- }
- ret = smd_write(nv_data->smd_ch, buf, len);
- if (ret < len) {
- pr_err("wcnss: failed to write Command %d", len);
- ret = -ENODEV;
- }
- return ret;
-}
+ struct qcom_smd_device *sdev;
+};
+static struct completion fw_ready_compl;
#define NV_FILE_NAME "wlan/prima/WCNSS_qcom_wlan_nv.bin"
static void wcn36xx_nv_download_work(struct work_struct *worker)
{
- int ret = 0, i, retry = 3;
+ int ret = 0, i;
const struct firmware *nv = NULL;
- struct wcn36xx_ctrl_nv_data *data =
- container_of(worker, struct wcn36xx_ctrl_nv_data, download_work);
- struct device *dev = &data->pdev->dev;
+ struct wcnss_platform_data *wcnss_data =
+ container_of(worker, struct wcnss_platform_data, download_work);
+ struct device *dev = &wcnss_data->sdev->dev;
+
struct nvbin_dnld_req_msg *msg;
const void *nv_blob_start;
char *pkt = NULL;
memcpy(pkt + sizeof(struct nvbin_dnld_req_msg),
nv_blob_start + i * NV_FRAGMENT_SIZE, pkt_len);
- ret = wcn36xx_nv_smd_tx(data, pkt, msg->hdr.msg_len);
-
- while ((ret == -ENOSPC) && (retry++ <= 3)) {
- dev_err(dev, "smd_tx failed, %d times retry\n", retry);
- msleep(100);
- ret = wcn36xx_nv_smd_tx(data, pkt, msg->hdr.msg_len);
- }
-
- if (ret < 0) {
+ ret = qcom_smd_send(wcnss_data->channel, pkt, msg->hdr.msg_len);
+ if (ret) {
dev_err(dev, "nv download failed\n");
goto out;
}
+
i++;
nv_blob_size -= NV_FRAGMENT_SIZE;
msleep(100);
return;
}
-static int wcnss_ctrl_remove(struct platform_device *pdev)
+static int qcom_smd_wcnss_ctrl_callback(struct qcom_smd_device *qsdev,
+ const void *data,
+ size_t count)
{
- smd_close(ctrl_nv_data.smd_ch);
+ struct wcnss_platform_data *wcnss_data = dev_get_drvdata(&qsdev->dev);
+ struct smd_msg_hdr phdr;
+ const unsigned char *tmp = data;
+ memcpy_fromio(&phdr, data, sizeof(struct smd_msg_hdr));
+
+ switch (phdr.msg_type) {
+ /* CBC COMPLETE means firmware ready for go */
+ case WCNSS_CBC_COMPLETE_IND:
+ complete(&fw_ready_compl);
+ pr_info("wcnss: received WCNSS_CBC_COMPLETE_IND from FW\n");
+ break;
+
+ case WCNSS_NV_DOWNLOAD_RSP:
+ pr_info("fw_status: %d\n", tmp[sizeof(struct smd_msg_hdr)]);
+ break;
+ }
+
+ complete(&wcnss_data->ack);
return 0;
}
-static int wcnss_ctrl_probe(struct platform_device *pdev)
+static int qcom_smd_wcnss_ctrl_probe(struct qcom_smd_device *sdev)
{
- int ret = 0;
+ struct wcnss_platform_data *wcnss_data;
- INIT_WORK(&ctrl_nv_data.rx_work, wcn36xx_nv_rx_work);
- INIT_WORK(&ctrl_nv_data.download_work, wcn36xx_nv_download_work);
- init_completion(&ctrl_nv_data.smd_open_compl);
- ctrl_nv_data.pdev = pdev;
+ wcnss_data = devm_kzalloc(&sdev->dev, sizeof(*wcnss_data), GFP_KERNEL);
+ if (!wcnss_data)
+ return -ENOMEM;
- ret = smd_named_open_on_edge("WCNSS_CTRL", SMD_APPS_WCNSS,
- &ctrl_nv_data.smd_ch, &ctrl_nv_data, wcn36xx_download_notify);
- if (ret) {
- dev_err(&pdev->dev, "wcnss_ctrl open failed\n");
- return ret;
- }
- smd_disable_read_intr(ctrl_nv_data.smd_ch);
- return ret;
+ mutex_init(&wcnss_data->lock);
+ init_completion(&wcnss_data->ack);
+
+ wcnss_data->sdev = sdev;
+
+ dev_set_drvdata(&sdev->dev, wcnss_data);
+ wcnss_data->channel = sdev->channel;
+
+ INIT_WORK(&wcnss_data->download_work, wcn36xx_nv_download_work);
+
+ of_platform_populate(sdev->dev.of_node, NULL, NULL, &sdev->dev);
+
+ /* We are ready for download here */
+ schedule_work(&wcnss_data->download_work);
+ return 0;
+}
+
+static void qcom_smd_wcnss_ctrl_remove(struct qcom_smd_device *sdev)
+{
+ of_platform_depopulate(&sdev->dev);
}
-/* platform device for WCNSS_CTRL SMD channel */
-static struct platform_driver wcnss_ctrl_driver = {
- .driver = {
- .name = "WCNSS_CTRL",
- .owner = THIS_MODULE,
+static const struct of_device_id qcom_smd_wcnss_ctrl_of_match[] = {
+ { .compatible = "qcom,wcnss-ctrl" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, qcom_smd_wcnss_ctrl_of_match);
+
+static struct qcom_smd_driver qcom_smd_wcnss_ctrl_driver = {
+ .probe = qcom_smd_wcnss_ctrl_probe,
+ .remove = qcom_smd_wcnss_ctrl_remove,
+ .callback = qcom_smd_wcnss_ctrl_callback,
+ .driver = {
+ .name = "qcom_smd_wcnss_ctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = qcom_smd_wcnss_ctrl_of_match,
},
- .probe = wcnss_ctrl_probe,
- .remove = wcnss_ctrl_remove,
};
void wcnss_core_init(void)
{
- platform_driver_register(&wcnss_ctrl_driver);
+ int ret = 0;
+
+ init_completion(&fw_ready_compl);
+ qcom_smd_driver_register(&qcom_smd_wcnss_ctrl_driver);
+
+ ret = wait_for_completion_interruptible_timeout(
+ &fw_ready_compl, msecs_to_jiffies(FW_READY_TIMEOUT));
+ if (ret <= 0) {
+ pr_err("timeout waiting for wcnss firmware ready indicator\n");
+ return;
+ }
+
+ return;
}
void wcnss_core_deinit(void)
{
- platform_driver_unregister(&wcnss_ctrl_driver);
+ qcom_smd_driver_unregister(&qcom_smd_wcnss_ctrl_driver);
}
-