|
@@ -21,6 +21,10 @@
|
|
#include <linux/platform_device.h>
|
|
#include <linux/platform_device.h>
|
|
#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/soc/qcom/smd.h>
|
|
|
|
+#include <linux/soc/qcom/smem_state.h>
|
|
|
|
+#include <linux/soc/qcom/wcnss_ctrl.h>
|
|
#include "wcn36xx.h"
|
|
#include "wcn36xx.h"
|
|
|
|
|
|
unsigned int wcn36xx_dbg_mask;
|
|
unsigned int wcn36xx_dbg_mask;
|
|
@@ -1058,8 +1062,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
/* Set TX IRQ */
|
|
/* Set TX IRQ */
|
|
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
|
|
|
|
- "wcnss_wlantx_irq");
|
|
|
|
|
|
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
|
|
if (!res) {
|
|
if (!res) {
|
|
wcn36xx_err("failed to get tx_irq\n");
|
|
wcn36xx_err("failed to get tx_irq\n");
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
@@ -1067,14 +1070,29 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
|
|
wcn->tx_irq = res->start;
|
|
wcn->tx_irq = res->start;
|
|
|
|
|
|
/* Set RX IRQ */
|
|
/* Set RX IRQ */
|
|
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
|
|
|
|
- "wcnss_wlanrx_irq");
|
|
|
|
|
|
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
|
|
if (!res) {
|
|
if (!res) {
|
|
wcn36xx_err("failed to get rx_irq\n");
|
|
wcn36xx_err("failed to get rx_irq\n");
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
}
|
|
}
|
|
wcn->rx_irq = res->start;
|
|
wcn->rx_irq = res->start;
|
|
|
|
|
|
|
|
+ /* Acquire SMSM tx enable handle */
|
|
|
|
+ wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev,
|
|
|
|
+ "tx-enable", &wcn->tx_enable_state_bit);
|
|
|
|
+ if (IS_ERR(wcn->tx_enable_state)) {
|
|
|
|
+ wcn36xx_err("failed to get tx-enable state\n");
|
|
|
|
+ return PTR_ERR(wcn->tx_enable_state);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Acquire SMSM tx rings empty handle */
|
|
|
|
+ wcn->tx_rings_empty_state = qcom_smem_state_get(&pdev->dev,
|
|
|
|
+ "tx-rings-empty", &wcn->tx_rings_empty_state_bit);
|
|
|
|
+ if (IS_ERR(wcn->tx_rings_empty_state)) {
|
|
|
|
+ wcn36xx_err("failed to get tx-rings-empty state\n");
|
|
|
|
+ return PTR_ERR(wcn->tx_rings_empty_state);
|
|
|
|
+ }
|
|
|
|
+
|
|
mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
|
|
mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
|
|
if (!mmio_node) {
|
|
if (!mmio_node) {
|
|
wcn36xx_err("failed to acquire qcom,mmio reference\n");
|
|
wcn36xx_err("failed to acquire qcom,mmio reference\n");
|
|
@@ -1115,11 +1133,14 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
|
{
|
|
{
|
|
struct ieee80211_hw *hw;
|
|
struct ieee80211_hw *hw;
|
|
struct wcn36xx *wcn;
|
|
struct wcn36xx *wcn;
|
|
|
|
+ void *wcnss;
|
|
int ret;
|
|
int ret;
|
|
- u8 addr[ETH_ALEN];
|
|
|
|
|
|
+ const u8 *addr;
|
|
|
|
|
|
wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
|
|
wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
|
|
|
|
|
|
|
|
+ wcnss = dev_get_drvdata(pdev->dev.parent);
|
|
|
|
+
|
|
hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
|
|
hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
|
|
if (!hw) {
|
|
if (!hw) {
|
|
wcn36xx_err("failed to alloc hw\n");
|
|
wcn36xx_err("failed to alloc hw\n");
|
|
@@ -1130,11 +1151,23 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
|
wcn = hw->priv;
|
|
wcn = hw->priv;
|
|
wcn->hw = hw;
|
|
wcn->hw = hw;
|
|
wcn->dev = &pdev->dev;
|
|
wcn->dev = &pdev->dev;
|
|
- wcn->ctrl_ops = pdev->dev.platform_data;
|
|
|
|
-
|
|
|
|
mutex_init(&wcn->hal_mutex);
|
|
mutex_init(&wcn->hal_mutex);
|
|
|
|
|
|
- if (!wcn->ctrl_ops->get_hw_mac(addr)) {
|
|
|
|
|
|
+ wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process);
|
|
|
|
+ if (IS_ERR(wcn->smd_channel)) {
|
|
|
|
+ wcn36xx_err("failed to open WLAN_CTRL channel\n");
|
|
|
|
+ ret = PTR_ERR(wcn->smd_channel);
|
|
|
|
+ goto out_wq;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ qcom_smd_set_drvdata(wcn->smd_channel, hw);
|
|
|
|
+
|
|
|
|
+ addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret);
|
|
|
|
+ if (addr && ret != ETH_ALEN) {
|
|
|
|
+ wcn36xx_err("invalid local-mac-address\n");
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ goto out_wq;
|
|
|
|
+ } else if (addr) {
|
|
wcn36xx_info("mac address: %pM\n", addr);
|
|
wcn36xx_info("mac address: %pM\n", addr);
|
|
SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
|
|
SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
|
|
}
|
|
}
|
|
@@ -1158,6 +1191,7 @@ out_wq:
|
|
out_err:
|
|
out_err:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
+
|
|
static int wcn36xx_remove(struct platform_device *pdev)
|
|
static int wcn36xx_remove(struct platform_device *pdev)
|
|
{
|
|
{
|
|
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
|
|
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
|
|
@@ -1168,42 +1202,33 @@ static int wcn36xx_remove(struct platform_device *pdev)
|
|
mutex_destroy(&wcn->hal_mutex);
|
|
mutex_destroy(&wcn->hal_mutex);
|
|
|
|
|
|
ieee80211_unregister_hw(hw);
|
|
ieee80211_unregister_hw(hw);
|
|
|
|
+
|
|
|
|
+ qcom_smem_state_put(wcn->tx_enable_state);
|
|
|
|
+ qcom_smem_state_put(wcn->tx_rings_empty_state);
|
|
|
|
+
|
|
iounmap(wcn->dxe_base);
|
|
iounmap(wcn->dxe_base);
|
|
iounmap(wcn->ccu_base);
|
|
iounmap(wcn->ccu_base);
|
|
ieee80211_free_hw(hw);
|
|
ieee80211_free_hw(hw);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
-static const struct platform_device_id wcn36xx_platform_id_table[] = {
|
|
|
|
- {
|
|
|
|
- .name = "wcn36xx",
|
|
|
|
- .driver_data = 0
|
|
|
|
- },
|
|
|
|
|
|
+
|
|
|
|
+static const struct of_device_id wcn36xx_of_match[] = {
|
|
|
|
+ { .compatible = "qcom,wcnss-wlan" },
|
|
{}
|
|
{}
|
|
};
|
|
};
|
|
-MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table);
|
|
|
|
|
|
+MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
|
|
|
|
|
|
static struct platform_driver wcn36xx_driver = {
|
|
static struct platform_driver wcn36xx_driver = {
|
|
.probe = wcn36xx_probe,
|
|
.probe = wcn36xx_probe,
|
|
.remove = wcn36xx_remove,
|
|
.remove = wcn36xx_remove,
|
|
.driver = {
|
|
.driver = {
|
|
.name = "wcn36xx",
|
|
.name = "wcn36xx",
|
|
|
|
+ .of_match_table = wcn36xx_of_match,
|
|
},
|
|
},
|
|
- .id_table = wcn36xx_platform_id_table,
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-static int __init wcn36xx_init(void)
|
|
|
|
-{
|
|
|
|
- platform_driver_register(&wcn36xx_driver);
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-module_init(wcn36xx_init);
|
|
|
|
-
|
|
|
|
-static void __exit wcn36xx_exit(void)
|
|
|
|
-{
|
|
|
|
- platform_driver_unregister(&wcn36xx_driver);
|
|
|
|
-}
|
|
|
|
-module_exit(wcn36xx_exit);
|
|
|
|
|
|
+module_platform_driver(wcn36xx_driver);
|
|
|
|
|
|
MODULE_LICENSE("Dual BSD/GPL");
|
|
MODULE_LICENSE("Dual BSD/GPL");
|
|
MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
|
|
MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
|