forked from luck/tmp_suning_uos_patched
soc: qcom: smd: Transition client drivers from smd to rpmsg
By moving these client drivers to use RPMSG instead of the direct SMD API we can reuse them ontop of the newly added GLINK wire-protocol support found in the 820 and 835 Qualcomm platforms. As the new (RPMSG-based) and old SMD implementations are mutually exclusive we have to change all client drivers in one commit, to make sure we have a working system before and after this transition. Acked-by: Andy Gross <andy.gross@linaro.org> Acked-by: Kalle Valo <kvalo@codeaurora.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
def499c929
commit
5052de8def
|
@ -344,7 +344,7 @@ config BT_WILINK
|
||||||
|
|
||||||
config BT_QCOMSMD
|
config BT_QCOMSMD
|
||||||
tristate "Qualcomm SMD based HCI support"
|
tristate "Qualcomm SMD based HCI support"
|
||||||
depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n)
|
depends on RPMSG || (COMPILE_TEST && RPMSG=n)
|
||||||
depends on QCOM_WCNSS_CTRL || (COMPILE_TEST && QCOM_WCNSS_CTRL=n)
|
depends on QCOM_WCNSS_CTRL || (COMPILE_TEST && QCOM_WCNSS_CTRL=n)
|
||||||
select BT_QCA
|
select BT_QCA
|
||||||
help
|
help
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/soc/qcom/smd.h>
|
#include <linux/rpmsg.h>
|
||||||
#include <linux/soc/qcom/wcnss_ctrl.h>
|
#include <linux/soc/qcom/wcnss_ctrl.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@
|
||||||
struct btqcomsmd {
|
struct btqcomsmd {
|
||||||
struct hci_dev *hdev;
|
struct hci_dev *hdev;
|
||||||
|
|
||||||
struct qcom_smd_channel *acl_channel;
|
struct rpmsg_endpoint *acl_channel;
|
||||||
struct qcom_smd_channel *cmd_channel;
|
struct rpmsg_endpoint *cmd_channel;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
|
static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
|
||||||
|
@ -48,19 +48,19 @@ static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
|
||||||
return hci_recv_frame(hdev, skb);
|
return hci_recv_frame(hdev, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btqcomsmd_acl_callback(struct qcom_smd_channel *channel,
|
static int btqcomsmd_acl_callback(struct rpmsg_device *rpdev, void *data,
|
||||||
const void *data, size_t count)
|
int count, void *priv, u32 addr)
|
||||||
{
|
{
|
||||||
struct btqcomsmd *btq = qcom_smd_get_drvdata(channel);
|
struct btqcomsmd *btq = priv;
|
||||||
|
|
||||||
btq->hdev->stat.byte_rx += count;
|
btq->hdev->stat.byte_rx += count;
|
||||||
return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count);
|
return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btqcomsmd_cmd_callback(struct qcom_smd_channel *channel,
|
static int btqcomsmd_cmd_callback(struct rpmsg_device *rpdev, void *data,
|
||||||
const void *data, size_t count)
|
int count, void *priv, u32 addr)
|
||||||
{
|
{
|
||||||
struct btqcomsmd *btq = qcom_smd_get_drvdata(channel);
|
struct btqcomsmd *btq = priv;
|
||||||
|
|
||||||
return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
|
return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
|
||||||
}
|
}
|
||||||
|
@ -72,12 +72,12 @@ static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
|
||||||
|
|
||||||
switch (hci_skb_pkt_type(skb)) {
|
switch (hci_skb_pkt_type(skb)) {
|
||||||
case HCI_ACLDATA_PKT:
|
case HCI_ACLDATA_PKT:
|
||||||
ret = qcom_smd_send(btq->acl_channel, skb->data, skb->len);
|
ret = rpmsg_send(btq->acl_channel, skb->data, skb->len);
|
||||||
hdev->stat.acl_tx++;
|
hdev->stat.acl_tx++;
|
||||||
hdev->stat.byte_tx += skb->len;
|
hdev->stat.byte_tx += skb->len;
|
||||||
break;
|
break;
|
||||||
case HCI_COMMAND_PKT:
|
case HCI_COMMAND_PKT:
|
||||||
ret = qcom_smd_send(btq->cmd_channel, skb->data, skb->len);
|
ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len);
|
||||||
hdev->stat.cmd_tx++;
|
hdev->stat.cmd_tx++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -114,18 +114,15 @@ static int btqcomsmd_probe(struct platform_device *pdev)
|
||||||
wcnss = dev_get_drvdata(pdev->dev.parent);
|
wcnss = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
|
||||||
btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL",
|
btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL",
|
||||||
btqcomsmd_acl_callback);
|
btqcomsmd_acl_callback, btq);
|
||||||
if (IS_ERR(btq->acl_channel))
|
if (IS_ERR(btq->acl_channel))
|
||||||
return PTR_ERR(btq->acl_channel);
|
return PTR_ERR(btq->acl_channel);
|
||||||
|
|
||||||
btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD",
|
btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD",
|
||||||
btqcomsmd_cmd_callback);
|
btqcomsmd_cmd_callback, btq);
|
||||||
if (IS_ERR(btq->cmd_channel))
|
if (IS_ERR(btq->cmd_channel))
|
||||||
return PTR_ERR(btq->cmd_channel);
|
return PTR_ERR(btq->cmd_channel);
|
||||||
|
|
||||||
qcom_smd_set_drvdata(btq->acl_channel, btq);
|
|
||||||
qcom_smd_set_drvdata(btq->cmd_channel, btq);
|
|
||||||
|
|
||||||
hdev = hci_alloc_dev();
|
hdev = hci_alloc_dev();
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -158,6 +155,9 @@ static int btqcomsmd_remove(struct platform_device *pdev)
|
||||||
hci_unregister_dev(btq->hdev);
|
hci_unregister_dev(btq->hdev);
|
||||||
hci_free_dev(btq->hdev);
|
hci_free_dev(btq->hdev);
|
||||||
|
|
||||||
|
rpmsg_destroy_ept(btq->cmd_channel);
|
||||||
|
rpmsg_destroy_ept(btq->acl_channel);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ config WCN36XX
|
||||||
tristate "Qualcomm Atheros WCN3660/3680 support"
|
tristate "Qualcomm Atheros WCN3660/3680 support"
|
||||||
depends on MAC80211 && HAS_DMA
|
depends on MAC80211 && HAS_DMA
|
||||||
depends on QCOM_WCNSS_CTRL || QCOM_WCNSS_CTRL=n
|
depends on QCOM_WCNSS_CTRL || QCOM_WCNSS_CTRL=n
|
||||||
depends on QCOM_SMD || QCOM_SMD=n
|
depends on RPMSG || RPMSG=n
|
||||||
---help---
|
---help---
|
||||||
This module adds support for wireless adapters based on
|
This module adds support for wireless adapters based on
|
||||||
Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets.
|
Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets.
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/soc/qcom/smd.h>
|
#include <linux/rpmsg.h>
|
||||||
#include <linux/soc/qcom/smem_state.h>
|
#include <linux/soc/qcom/smem_state.h>
|
||||||
#include <linux/soc/qcom/wcnss_ctrl.h>
|
#include <linux/soc/qcom/wcnss_ctrl.h>
|
||||||
#include "wcn36xx.h"
|
#include "wcn36xx.h"
|
||||||
|
@ -1218,15 +1218,13 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker);
|
INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker);
|
||||||
|
|
||||||
wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process);
|
wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw);
|
||||||
if (IS_ERR(wcn->smd_channel)) {
|
if (IS_ERR(wcn->smd_channel)) {
|
||||||
wcn36xx_err("failed to open WLAN_CTRL channel\n");
|
wcn36xx_err("failed to open WLAN_CTRL channel\n");
|
||||||
ret = PTR_ERR(wcn->smd_channel);
|
ret = PTR_ERR(wcn->smd_channel);
|
||||||
goto out_wq;
|
goto out_wq;
|
||||||
}
|
}
|
||||||
|
|
||||||
qcom_smd_set_drvdata(wcn->smd_channel, hw);
|
|
||||||
|
|
||||||
addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret);
|
addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret);
|
||||||
if (addr && ret != ETH_ALEN) {
|
if (addr && ret != ETH_ALEN) {
|
||||||
wcn36xx_err("invalid local-mac-address\n");
|
wcn36xx_err("invalid local-mac-address\n");
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/soc/qcom/smd.h>
|
#include <linux/rpmsg.h>
|
||||||
#include "smd.h"
|
#include "smd.h"
|
||||||
|
|
||||||
struct wcn36xx_cfg_val {
|
struct wcn36xx_cfg_val {
|
||||||
|
@ -254,7 +254,7 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
|
||||||
|
|
||||||
init_completion(&wcn->hal_rsp_compl);
|
init_completion(&wcn->hal_rsp_compl);
|
||||||
start = jiffies;
|
start = jiffies;
|
||||||
ret = qcom_smd_send(wcn->smd_channel, wcn->hal_buf, len);
|
ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wcn36xx_err("HAL TX failed\n");
|
wcn36xx_err("HAL TX failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -2205,11 +2205,11 @@ int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wcn36xx_smd_rsp_process(struct qcom_smd_channel *channel,
|
int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
|
||||||
const void *buf, size_t len)
|
void *buf, int len, void *priv, u32 addr)
|
||||||
{
|
{
|
||||||
const struct wcn36xx_hal_msg_header *msg_header = buf;
|
const struct wcn36xx_hal_msg_header *msg_header = buf;
|
||||||
struct ieee80211_hw *hw = qcom_smd_get_drvdata(channel);
|
struct ieee80211_hw *hw = priv;
|
||||||
struct wcn36xx *wcn = hw->priv;
|
struct wcn36xx *wcn = hw->priv;
|
||||||
struct wcn36xx_hal_ind_msg *msg_ind;
|
struct wcn36xx_hal_ind_msg *msg_ind;
|
||||||
wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
|
wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
|
||||||
|
|
|
@ -51,7 +51,7 @@ struct wcn36xx_hal_ind_msg {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wcn36xx;
|
struct wcn36xx;
|
||||||
struct qcom_smd_channel;
|
struct rpmsg_device;
|
||||||
|
|
||||||
int wcn36xx_smd_open(struct wcn36xx *wcn);
|
int wcn36xx_smd_open(struct wcn36xx *wcn);
|
||||||
void wcn36xx_smd_close(struct wcn36xx *wcn);
|
void wcn36xx_smd_close(struct wcn36xx *wcn);
|
||||||
|
@ -129,8 +129,8 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index);
|
||||||
|
|
||||||
int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
|
int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
|
||||||
|
|
||||||
int wcn36xx_smd_rsp_process(struct qcom_smd_channel *channel,
|
int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
|
||||||
const void *buf, size_t len);
|
void *buf, int len, void *priv, u32 addr);
|
||||||
|
|
||||||
int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
|
int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
|
|
|
@ -195,7 +195,7 @@ struct wcn36xx {
|
||||||
void __iomem *ccu_base;
|
void __iomem *ccu_base;
|
||||||
void __iomem *dxe_base;
|
void __iomem *dxe_base;
|
||||||
|
|
||||||
struct qcom_smd_channel *smd_channel;
|
struct rpmsg_endpoint *smd_channel;
|
||||||
|
|
||||||
struct qcom_smem_state *tx_enable_state;
|
struct qcom_smem_state *tx_enable_state;
|
||||||
unsigned tx_enable_state_bit;
|
unsigned tx_enable_state_bit;
|
||||||
|
|
|
@ -43,7 +43,8 @@ config QCOM_SMD
|
||||||
|
|
||||||
config QCOM_SMD_RPM
|
config QCOM_SMD_RPM
|
||||||
tristate "Qualcomm Resource Power Manager (RPM) over SMD"
|
tristate "Qualcomm Resource Power Manager (RPM) over SMD"
|
||||||
depends on QCOM_SMD && OF
|
depends on ARCH_QCOM
|
||||||
|
depends on RPMSG && OF
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
Resource Power Manager system found in the Qualcomm 8974 based
|
Resource Power Manager system found in the Qualcomm 8974 based
|
||||||
|
@ -76,7 +77,8 @@ config QCOM_SMSM
|
||||||
|
|
||||||
config QCOM_WCNSS_CTRL
|
config QCOM_WCNSS_CTRL
|
||||||
tristate "Qualcomm WCNSS control driver"
|
tristate "Qualcomm WCNSS control driver"
|
||||||
depends on QCOM_SMD
|
depends on ARCH_QCOM
|
||||||
|
depends on RPMSG
|
||||||
help
|
help
|
||||||
Client driver for the WCNSS_CTRL SMD channel, used to download nv
|
Client driver for the WCNSS_CTRL SMD channel, used to download nv
|
||||||
firmware to a newly booted WCNSS chip.
|
firmware to a newly booted WCNSS chip.
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include <linux/soc/qcom/smd.h>
|
#include <linux/rpmsg.h>
|
||||||
#include <linux/soc/qcom/smd-rpm.h>
|
#include <linux/soc/qcom/smd-rpm.h>
|
||||||
|
|
||||||
#define RPM_REQUEST_TIMEOUT (5 * HZ)
|
#define RPM_REQUEST_TIMEOUT (5 * HZ)
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
* @ack_status: result of the rpm request
|
* @ack_status: result of the rpm request
|
||||||
*/
|
*/
|
||||||
struct qcom_smd_rpm {
|
struct qcom_smd_rpm {
|
||||||
struct qcom_smd_channel *rpm_channel;
|
struct rpmsg_endpoint *rpm_channel;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
struct completion ack;
|
struct completion ack;
|
||||||
|
@ -133,7 +133,7 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
|
||||||
pkt->req.data_len = cpu_to_le32(count);
|
pkt->req.data_len = cpu_to_le32(count);
|
||||||
memcpy(pkt->payload, buf, count);
|
memcpy(pkt->payload, buf, count);
|
||||||
|
|
||||||
ret = qcom_smd_send(rpm->rpm_channel, pkt, size);
|
ret = rpmsg_send(rpm->rpm_channel, pkt, size);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -150,14 +150,16 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(qcom_rpm_smd_write);
|
EXPORT_SYMBOL(qcom_rpm_smd_write);
|
||||||
|
|
||||||
static int qcom_smd_rpm_callback(struct qcom_smd_channel *channel,
|
static int qcom_smd_rpm_callback(struct rpmsg_device *rpdev,
|
||||||
const void *data,
|
void *data,
|
||||||
size_t count)
|
int count,
|
||||||
|
void *priv,
|
||||||
|
u32 addr)
|
||||||
{
|
{
|
||||||
const struct qcom_rpm_header *hdr = data;
|
const struct qcom_rpm_header *hdr = data;
|
||||||
size_t hdr_length = le32_to_cpu(hdr->length);
|
size_t hdr_length = le32_to_cpu(hdr->length);
|
||||||
const struct qcom_rpm_message *msg;
|
const struct qcom_rpm_message *msg;
|
||||||
struct qcom_smd_rpm *rpm = qcom_smd_get_drvdata(channel);
|
struct qcom_smd_rpm *rpm = dev_get_drvdata(&rpdev->dev);
|
||||||
const u8 *buf = data + sizeof(struct qcom_rpm_header);
|
const u8 *buf = data + sizeof(struct qcom_rpm_header);
|
||||||
const u8 *end = buf + hdr_length;
|
const u8 *end = buf + hdr_length;
|
||||||
char msgbuf[32];
|
char msgbuf[32];
|
||||||
|
@ -196,29 +198,27 @@ static int qcom_smd_rpm_callback(struct qcom_smd_channel *channel,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qcom_smd_rpm_probe(struct qcom_smd_device *sdev)
|
static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev)
|
||||||
{
|
{
|
||||||
struct qcom_smd_rpm *rpm;
|
struct qcom_smd_rpm *rpm;
|
||||||
|
|
||||||
rpm = devm_kzalloc(&sdev->dev, sizeof(*rpm), GFP_KERNEL);
|
rpm = devm_kzalloc(&rpdev->dev, sizeof(*rpm), GFP_KERNEL);
|
||||||
if (!rpm)
|
if (!rpm)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
mutex_init(&rpm->lock);
|
mutex_init(&rpm->lock);
|
||||||
init_completion(&rpm->ack);
|
init_completion(&rpm->ack);
|
||||||
|
|
||||||
rpm->dev = &sdev->dev;
|
rpm->dev = &rpdev->dev;
|
||||||
rpm->rpm_channel = sdev->channel;
|
rpm->rpm_channel = rpdev->ept;
|
||||||
qcom_smd_set_drvdata(sdev->channel, rpm);
|
dev_set_drvdata(&rpdev->dev, rpm);
|
||||||
|
|
||||||
dev_set_drvdata(&sdev->dev, rpm);
|
return of_platform_populate(rpdev->dev.of_node, NULL, NULL, &rpdev->dev);
|
||||||
|
|
||||||
return of_platform_populate(sdev->dev.of_node, NULL, NULL, &sdev->dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qcom_smd_rpm_remove(struct qcom_smd_device *sdev)
|
static void qcom_smd_rpm_remove(struct rpmsg_device *rpdev)
|
||||||
{
|
{
|
||||||
of_platform_depopulate(&sdev->dev);
|
of_platform_depopulate(&rpdev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id qcom_smd_rpm_of_match[] = {
|
static const struct of_device_id qcom_smd_rpm_of_match[] = {
|
||||||
|
@ -229,26 +229,25 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match);
|
MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match);
|
||||||
|
|
||||||
static struct qcom_smd_driver qcom_smd_rpm_driver = {
|
static struct rpmsg_driver qcom_smd_rpm_driver = {
|
||||||
.probe = qcom_smd_rpm_probe,
|
.probe = qcom_smd_rpm_probe,
|
||||||
.remove = qcom_smd_rpm_remove,
|
.remove = qcom_smd_rpm_remove,
|
||||||
.callback = qcom_smd_rpm_callback,
|
.callback = qcom_smd_rpm_callback,
|
||||||
.driver = {
|
.drv = {
|
||||||
.name = "qcom_smd_rpm",
|
.name = "qcom_smd_rpm",
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.of_match_table = qcom_smd_rpm_of_match,
|
.of_match_table = qcom_smd_rpm_of_match,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init qcom_smd_rpm_init(void)
|
static int __init qcom_smd_rpm_init(void)
|
||||||
{
|
{
|
||||||
return qcom_smd_driver_register(&qcom_smd_rpm_driver);
|
return register_rpmsg_driver(&qcom_smd_rpm_driver);
|
||||||
}
|
}
|
||||||
arch_initcall(qcom_smd_rpm_init);
|
arch_initcall(qcom_smd_rpm_init);
|
||||||
|
|
||||||
static void __exit qcom_smd_rpm_exit(void)
|
static void __exit qcom_smd_rpm_exit(void)
|
||||||
{
|
{
|
||||||
qcom_smd_driver_unregister(&qcom_smd_rpm_driver);
|
unregister_rpmsg_driver(&qcom_smd_rpm_driver);
|
||||||
}
|
}
|
||||||
module_exit(qcom_smd_rpm_exit);
|
module_exit(qcom_smd_rpm_exit);
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/soc/qcom/smd.h>
|
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/rpmsg.h>
|
||||||
#include <linux/soc/qcom/wcnss_ctrl.h>
|
#include <linux/soc/qcom/wcnss_ctrl.h>
|
||||||
|
|
||||||
#define WCNSS_REQUEST_TIMEOUT (5 * HZ)
|
#define WCNSS_REQUEST_TIMEOUT (5 * HZ)
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
*/
|
*/
|
||||||
struct wcnss_ctrl {
|
struct wcnss_ctrl {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct qcom_smd_channel *channel;
|
struct rpmsg_endpoint *channel;
|
||||||
|
|
||||||
struct completion ack;
|
struct completion ack;
|
||||||
struct completion cbc;
|
struct completion cbc;
|
||||||
|
@ -122,11 +122,13 @@ struct wcnss_download_nv_resp {
|
||||||
*
|
*
|
||||||
* Handles any incoming packets from the remote WCNSS_CTRL service.
|
* Handles any incoming packets from the remote WCNSS_CTRL service.
|
||||||
*/
|
*/
|
||||||
static int wcnss_ctrl_smd_callback(struct qcom_smd_channel *channel,
|
static int wcnss_ctrl_smd_callback(struct rpmsg_device *rpdev,
|
||||||
const void *data,
|
void *data,
|
||||||
size_t count)
|
int count,
|
||||||
|
void *priv,
|
||||||
|
u32 addr)
|
||||||
{
|
{
|
||||||
struct wcnss_ctrl *wcnss = qcom_smd_get_drvdata(channel);
|
struct wcnss_ctrl *wcnss = dev_get_drvdata(&rpdev->dev);
|
||||||
const struct wcnss_download_nv_resp *nvresp;
|
const struct wcnss_download_nv_resp *nvresp;
|
||||||
const struct wcnss_version_resp *version;
|
const struct wcnss_version_resp *version;
|
||||||
const struct wcnss_msg_hdr *hdr = data;
|
const struct wcnss_msg_hdr *hdr = data;
|
||||||
|
@ -180,7 +182,7 @@ static int wcnss_request_version(struct wcnss_ctrl *wcnss)
|
||||||
|
|
||||||
msg.type = WCNSS_VERSION_REQ;
|
msg.type = WCNSS_VERSION_REQ;
|
||||||
msg.len = sizeof(msg);
|
msg.len = sizeof(msg);
|
||||||
ret = qcom_smd_send(wcnss->channel, &msg, sizeof(msg));
|
ret = rpmsg_send(wcnss->channel, &msg, sizeof(msg));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -238,7 +240,7 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
|
||||||
|
|
||||||
memcpy(req->fragment, data, req->frag_size);
|
memcpy(req->fragment, data, req->frag_size);
|
||||||
|
|
||||||
ret = qcom_smd_send(wcnss->channel, req, req->hdr.len);
|
ret = rpmsg_send(wcnss->channel, req, req->hdr.len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(wcnss->dev, "failed to send smd packet\n");
|
dev_err(wcnss->dev, "failed to send smd packet\n");
|
||||||
goto release_fw;
|
goto release_fw;
|
||||||
|
@ -274,11 +276,16 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
|
||||||
* @name: SMD channel name
|
* @name: SMD channel name
|
||||||
* @cb: callback to handle incoming data on the channel
|
* @cb: callback to handle incoming data on the channel
|
||||||
*/
|
*/
|
||||||
struct qcom_smd_channel *qcom_wcnss_open_channel(void *wcnss, const char *name, qcom_smd_cb_t cb)
|
struct rpmsg_endpoint *qcom_wcnss_open_channel(void *wcnss, const char *name, rpmsg_rx_cb_t cb, void *priv)
|
||||||
{
|
{
|
||||||
|
struct rpmsg_channel_info chinfo;
|
||||||
struct wcnss_ctrl *_wcnss = wcnss;
|
struct wcnss_ctrl *_wcnss = wcnss;
|
||||||
|
|
||||||
return qcom_smd_open_channel(_wcnss->channel, name, cb);
|
strncpy(chinfo.name, name, sizeof(chinfo.name));
|
||||||
|
chinfo.src = RPMSG_ADDR_ANY;
|
||||||
|
chinfo.dst = RPMSG_ADDR_ANY;
|
||||||
|
|
||||||
|
return rpmsg_create_ept(_wcnss->channel->rpdev, cb, priv, chinfo);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(qcom_wcnss_open_channel);
|
EXPORT_SYMBOL(qcom_wcnss_open_channel);
|
||||||
|
|
||||||
|
@ -306,35 +313,34 @@ static void wcnss_async_probe(struct work_struct *work)
|
||||||
of_platform_populate(wcnss->dev->of_node, NULL, NULL, wcnss->dev);
|
of_platform_populate(wcnss->dev->of_node, NULL, NULL, wcnss->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wcnss_ctrl_probe(struct qcom_smd_device *sdev)
|
static int wcnss_ctrl_probe(struct rpmsg_device *rpdev)
|
||||||
{
|
{
|
||||||
struct wcnss_ctrl *wcnss;
|
struct wcnss_ctrl *wcnss;
|
||||||
|
|
||||||
wcnss = devm_kzalloc(&sdev->dev, sizeof(*wcnss), GFP_KERNEL);
|
wcnss = devm_kzalloc(&rpdev->dev, sizeof(*wcnss), GFP_KERNEL);
|
||||||
if (!wcnss)
|
if (!wcnss)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
wcnss->dev = &sdev->dev;
|
wcnss->dev = &rpdev->dev;
|
||||||
wcnss->channel = sdev->channel;
|
wcnss->channel = rpdev->ept;
|
||||||
|
|
||||||
init_completion(&wcnss->ack);
|
init_completion(&wcnss->ack);
|
||||||
init_completion(&wcnss->cbc);
|
init_completion(&wcnss->cbc);
|
||||||
INIT_WORK(&wcnss->probe_work, wcnss_async_probe);
|
INIT_WORK(&wcnss->probe_work, wcnss_async_probe);
|
||||||
|
|
||||||
qcom_smd_set_drvdata(sdev->channel, wcnss);
|
dev_set_drvdata(&rpdev->dev, wcnss);
|
||||||
dev_set_drvdata(&sdev->dev, wcnss);
|
|
||||||
|
|
||||||
schedule_work(&wcnss->probe_work);
|
schedule_work(&wcnss->probe_work);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wcnss_ctrl_remove(struct qcom_smd_device *sdev)
|
static void wcnss_ctrl_remove(struct rpmsg_device *rpdev)
|
||||||
{
|
{
|
||||||
struct wcnss_ctrl *wcnss = qcom_smd_get_drvdata(sdev->channel);
|
struct wcnss_ctrl *wcnss = dev_get_drvdata(&rpdev->dev);
|
||||||
|
|
||||||
cancel_work_sync(&wcnss->probe_work);
|
cancel_work_sync(&wcnss->probe_work);
|
||||||
of_platform_depopulate(&sdev->dev);
|
of_platform_depopulate(&rpdev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id wcnss_ctrl_of_match[] = {
|
static const struct of_device_id wcnss_ctrl_of_match[] = {
|
||||||
|
@ -342,18 +348,18 @@ static const struct of_device_id wcnss_ctrl_of_match[] = {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct qcom_smd_driver wcnss_ctrl_driver = {
|
static struct rpmsg_driver wcnss_ctrl_driver = {
|
||||||
.probe = wcnss_ctrl_probe,
|
.probe = wcnss_ctrl_probe,
|
||||||
.remove = wcnss_ctrl_remove,
|
.remove = wcnss_ctrl_remove,
|
||||||
.callback = wcnss_ctrl_smd_callback,
|
.callback = wcnss_ctrl_smd_callback,
|
||||||
.driver = {
|
.drv = {
|
||||||
.name = "qcom_wcnss_ctrl",
|
.name = "qcom_wcnss_ctrl",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.of_match_table = wcnss_ctrl_of_match,
|
.of_match_table = wcnss_ctrl_of_match,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module_qcom_smd_driver(wcnss_ctrl_driver);
|
module_rpmsg_driver(wcnss_ctrl_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Qualcomm WCNSS control driver");
|
MODULE_DESCRIPTION("Qualcomm WCNSS control driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
#ifndef __WCNSS_CTRL_H__
|
#ifndef __WCNSS_CTRL_H__
|
||||||
#define __WCNSS_CTRL_H__
|
#define __WCNSS_CTRL_H__
|
||||||
|
|
||||||
#include <linux/soc/qcom/smd.h>
|
#include <linux/rpmsg.h>
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_QCOM_WCNSS_CTRL)
|
#if IS_ENABLED(CONFIG_QCOM_WCNSS_CTRL)
|
||||||
|
|
||||||
struct qcom_smd_channel *qcom_wcnss_open_channel(void *wcnss, const char *name, qcom_smd_cb_t cb);
|
struct rpmsg_endpoint *qcom_wcnss_open_channel(void *wcnss, const char *name,
|
||||||
|
rpmsg_rx_cb_t cb, void *priv);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline struct qcom_smd_channel*
|
static struct rpmsg_endpoint *qcom_wcnss_open_channel(void *wcnss,
|
||||||
qcom_wcnss_open_channel(void *wcnss, const char *name, qcom_smd_cb_t cb)
|
const char *name,
|
||||||
|
rpmsg_rx_cb_t cb,
|
||||||
|
void *priv)
|
||||||
{
|
{
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
return ERR_PTR(-ENXIO);
|
return ERR_PTR(-ENXIO);
|
||||||
|
|
|
@ -16,7 +16,7 @@ if QRTR
|
||||||
|
|
||||||
config QRTR_SMD
|
config QRTR_SMD
|
||||||
tristate "SMD IPC Router channels"
|
tristate "SMD IPC Router channels"
|
||||||
depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n)
|
depends on RPMSG || (COMPILE_TEST && RPMSG=n)
|
||||||
---help---
|
---help---
|
||||||
Say Y here to support SMD based ipcrouter channels. SMD is the
|
Say Y here to support SMD based ipcrouter channels. SMD is the
|
||||||
most common transport for IPC Router.
|
most common transport for IPC Router.
|
||||||
|
|
|
@ -14,21 +14,21 @@
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/soc/qcom/smd.h>
|
#include <linux/rpmsg.h>
|
||||||
|
|
||||||
#include "qrtr.h"
|
#include "qrtr.h"
|
||||||
|
|
||||||
struct qrtr_smd_dev {
|
struct qrtr_smd_dev {
|
||||||
struct qrtr_endpoint ep;
|
struct qrtr_endpoint ep;
|
||||||
struct qcom_smd_channel *channel;
|
struct rpmsg_endpoint *channel;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* from smd to qrtr */
|
/* from smd to qrtr */
|
||||||
static int qcom_smd_qrtr_callback(struct qcom_smd_channel *channel,
|
static int qcom_smd_qrtr_callback(struct rpmsg_device *rpdev,
|
||||||
const void *data, size_t len)
|
void *data, int len, void *priv, u32 addr)
|
||||||
{
|
{
|
||||||
struct qrtr_smd_dev *qdev = qcom_smd_get_drvdata(channel);
|
struct qrtr_smd_dev *qdev = dev_get_drvdata(&rpdev->dev);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!qdev)
|
if (!qdev)
|
||||||
|
@ -54,7 +54,7 @@ static int qcom_smd_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rc = qcom_smd_send(qdev->channel, skb->data, skb->len);
|
rc = rpmsg_send(qdev->channel, skb->data, skb->len);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -64,57 +64,55 @@ static int qcom_smd_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qcom_smd_qrtr_probe(struct qcom_smd_device *sdev)
|
static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev)
|
||||||
{
|
{
|
||||||
struct qrtr_smd_dev *qdev;
|
struct qrtr_smd_dev *qdev;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
qdev = devm_kzalloc(&sdev->dev, sizeof(*qdev), GFP_KERNEL);
|
qdev = devm_kzalloc(&rpdev->dev, sizeof(*qdev), GFP_KERNEL);
|
||||||
if (!qdev)
|
if (!qdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
qdev->channel = sdev->channel;
|
qdev->channel = rpdev->ept;
|
||||||
qdev->dev = &sdev->dev;
|
qdev->dev = &rpdev->dev;
|
||||||
qdev->ep.xmit = qcom_smd_qrtr_send;
|
qdev->ep.xmit = qcom_smd_qrtr_send;
|
||||||
|
|
||||||
rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
|
rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
qcom_smd_set_drvdata(sdev->channel, qdev);
|
dev_set_drvdata(&rpdev->dev, qdev);
|
||||||
dev_set_drvdata(&sdev->dev, qdev);
|
|
||||||
|
|
||||||
dev_dbg(&sdev->dev, "Qualcomm SMD QRTR driver probed\n");
|
dev_dbg(&rpdev->dev, "Qualcomm SMD QRTR driver probed\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qcom_smd_qrtr_remove(struct qcom_smd_device *sdev)
|
static void qcom_smd_qrtr_remove(struct rpmsg_device *rpdev)
|
||||||
{
|
{
|
||||||
struct qrtr_smd_dev *qdev = dev_get_drvdata(&sdev->dev);
|
struct qrtr_smd_dev *qdev = dev_get_drvdata(&rpdev->dev);
|
||||||
|
|
||||||
qrtr_endpoint_unregister(&qdev->ep);
|
qrtr_endpoint_unregister(&qdev->ep);
|
||||||
|
|
||||||
dev_set_drvdata(&sdev->dev, NULL);
|
dev_set_drvdata(&rpdev->dev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct qcom_smd_id qcom_smd_qrtr_smd_match[] = {
|
static const struct rpmsg_device_id qcom_smd_qrtr_smd_match[] = {
|
||||||
{ "IPCRTR" },
|
{ "IPCRTR" },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct qcom_smd_driver qcom_smd_qrtr_driver = {
|
static struct rpmsg_driver qcom_smd_qrtr_driver = {
|
||||||
.probe = qcom_smd_qrtr_probe,
|
.probe = qcom_smd_qrtr_probe,
|
||||||
.remove = qcom_smd_qrtr_remove,
|
.remove = qcom_smd_qrtr_remove,
|
||||||
.callback = qcom_smd_qrtr_callback,
|
.callback = qcom_smd_qrtr_callback,
|
||||||
.smd_match_table = qcom_smd_qrtr_smd_match,
|
.id_table = qcom_smd_qrtr_smd_match,
|
||||||
.driver = {
|
.drv = {
|
||||||
.name = "qcom_smd_qrtr",
|
.name = "qcom_smd_qrtr",
|
||||||
.owner = THIS_MODULE,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module_qcom_smd_driver(qcom_smd_qrtr_driver);
|
module_rpmsg_driver(qcom_smd_qrtr_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Qualcomm IPC-Router SMD interface driver");
|
MODULE_DESCRIPTION("Qualcomm IPC-Router SMD interface driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user