[PATCH net-next v4 02/10] net: wwan: tmi: Add control plane transaction layer
Yanchao Yang
yanchao.yang at mediatek.com
Fri Mar 17 01:09:34 PDT 2023
The control plane implements TX services that reside in the transaction layer.
The services receive the packets from the port layer and call the corresponding
DMA components to transmit data to the device. Meanwhile, TX services receive
and manage the port control commands from the port layer.
The control plane implements RX services that reside in the transaction layer.
The services receive the downlink packets from the modem and transfer the
packets to the corresponding port layer interfaces.
Signed-off-by: Yanchao Yang <yanchao.yang at mediatek.com>
Signed-off-by: Mingliang Xu <mingliang.xu at mediatek.com>
---
drivers/net/wwan/mediatek/Makefile | 4 +-
drivers/net/wwan/mediatek/mtk_ctrl_plane.c | 36 +++++++++++++
drivers/net/wwan/mediatek/mtk_ctrl_plane.h | 30 +++++++++++
drivers/net/wwan/mediatek/mtk_dev.c | 25 +++++++++
drivers/net/wwan/mediatek/mtk_dev.h | 3 ++
drivers/net/wwan/mediatek/pcie/mtk_pci.c | 62 ++++++++++++++++++++++
6 files changed, 159 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/wwan/mediatek/mtk_ctrl_plane.c
create mode 100644 drivers/net/wwan/mediatek/mtk_ctrl_plane.h
create mode 100644 drivers/net/wwan/mediatek/mtk_dev.c
diff --git a/drivers/net/wwan/mediatek/Makefile b/drivers/net/wwan/mediatek/Makefile
index b74192eee432..c93c81597821 100644
--- a/drivers/net/wwan/mediatek/Makefile
+++ b/drivers/net/wwan/mediatek/Makefile
@@ -3,6 +3,8 @@
MODULE_NAME := mtk_tmi
mtk_tmi-y = \
- pcie/mtk_pci.o
+ pcie/mtk_pci.o \
+ mtk_dev.o \
+ mtk_ctrl_plane.o
obj-$(CONFIG_MTK_TMI) += mtk_tmi.o
diff --git a/drivers/net/wwan/mediatek/mtk_ctrl_plane.c b/drivers/net/wwan/mediatek/mtk_ctrl_plane.c
new file mode 100644
index 000000000000..1dbfcf8587a1
--- /dev/null
+++ b/drivers/net/wwan/mediatek/mtk_ctrl_plane.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2022, MediaTek Inc.
+ */
+
+#include <linux/device.h>
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+
+#include "mtk_ctrl_plane.h"
+
+int mtk_ctrl_init(struct mtk_md_dev *mdev)
+{
+ struct mtk_ctrl_blk *ctrl_blk;
+
+ ctrl_blk = devm_kzalloc(mdev->dev, sizeof(*ctrl_blk), GFP_KERNEL);
+ if (!ctrl_blk)
+ return -ENOMEM;
+
+ ctrl_blk->mdev = mdev;
+ mdev->ctrl_blk = ctrl_blk;
+
+ return 0;
+}
+
+int mtk_ctrl_exit(struct mtk_md_dev *mdev)
+{
+ struct mtk_ctrl_blk *ctrl_blk = mdev->ctrl_blk;
+
+ devm_kfree(mdev->dev, ctrl_blk);
+
+ return 0;
+}
diff --git a/drivers/net/wwan/mediatek/mtk_ctrl_plane.h b/drivers/net/wwan/mediatek/mtk_ctrl_plane.h
new file mode 100644
index 000000000000..77af4248cb74
--- /dev/null
+++ b/drivers/net/wwan/mediatek/mtk_ctrl_plane.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear
+ *
+ * Copyright (c) 2022, MediaTek Inc.
+ */
+
+#ifndef __MTK_CTRL_PLANE_H__
+#define __MTK_CTRL_PLANE_H__
+
+#include <linux/kref.h>
+#include <linux/skbuff.h>
+
+#include "mtk_dev.h"
+
+#define VQ_MTU_3_5K (0xE00)
+#define VQ_MTU_63K (0xFC00)
+
+struct mtk_ctrl_trans {
+ struct mtk_ctrl_blk *ctrl_blk;
+ struct mtk_md_dev *mdev;
+};
+
+struct mtk_ctrl_blk {
+ struct mtk_md_dev *mdev;
+ struct mtk_ctrl_trans *trans;
+};
+
+int mtk_ctrl_init(struct mtk_md_dev *mdev);
+int mtk_ctrl_exit(struct mtk_md_dev *mdev);
+
+#endif /* __MTK_CTRL_PLANE_H__ */
diff --git a/drivers/net/wwan/mediatek/mtk_dev.c b/drivers/net/wwan/mediatek/mtk_dev.c
new file mode 100644
index 000000000000..f63c7e04df6a
--- /dev/null
+++ b/drivers/net/wwan/mediatek/mtk_dev.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2022, MediaTek Inc.
+ */
+
+#include "mtk_ctrl_plane.h"
+#include "mtk_dev.h"
+
+int mtk_dev_init(struct mtk_md_dev *mdev)
+{
+ int ret;
+
+ ret = mtk_ctrl_init(mdev);
+ if (ret)
+ goto err_ctrl_init;
+
+ return 0;
+err_ctrl_init:
+ return ret;
+}
+
+void mtk_dev_exit(struct mtk_md_dev *mdev)
+{
+ mtk_ctrl_exit(mdev);
+}
diff --git a/drivers/net/wwan/mediatek/mtk_dev.h b/drivers/net/wwan/mediatek/mtk_dev.h
index acda9ccf05f1..d48fc55ddef0 100644
--- a/drivers/net/wwan/mediatek/mtk_dev.h
+++ b/drivers/net/wwan/mediatek/mtk_dev.h
@@ -101,8 +101,11 @@ struct mtk_md_dev {
u32 hw_ver;
int msi_nvecs;
char dev_str[MTK_DEV_STR_LEN];
+ void *ctrl_blk;
};
+int mtk_dev_init(struct mtk_md_dev *mdev);
+void mtk_dev_exit(struct mtk_md_dev *mdev);
static inline u32 mtk_hw_read32(struct mtk_md_dev *mdev, u64 addr)
{
return mdev->hw_ops->read32(mdev, addr);
diff --git a/drivers/net/wwan/mediatek/pcie/mtk_pci.c b/drivers/net/wwan/mediatek/pcie/mtk_pci.c
index f8590d7319a8..b3de9634a62c 100644
--- a/drivers/net/wwan/mediatek/pcie/mtk_pci.c
+++ b/drivers/net/wwan/mediatek/pcie/mtk_pci.c
@@ -9,6 +9,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -16,6 +17,9 @@
#include "mtk_reg.h"
#define MTK_PCI_TRANSPARENT_ATR_SIZE (0x3F)
+#define MTK_PCI_LOCK_L1SS_STS_MASK (0x1F)
+#define MTK_PCI_LOCK_L1SS_POLL_STEP (10)
+#define MTK_PCI_LOCK_L1SS_POLL_TIMEOUT (10000)
static u32 mtk_pci_mac_read32(struct mtk_pci_priv *priv, u64 addr)
{
@@ -196,6 +200,41 @@ static void mtk_pci_ack_dev_state(struct mtk_md_dev *mdev, u32 state)
mtk_pci_mac_write32(mdev->hw_priv, REG_PCIE_DEBUG_DUMMY_7, state);
}
+static void mtk_pci_force_mac_active(struct mtk_md_dev *mdev, bool enable)
+{
+ struct mtk_pci_priv *priv = mdev->hw_priv;
+ u32 reg;
+
+ reg = mtk_pci_mac_read32(priv, REG_PCIE_MISC_CTRL);
+ if (enable)
+ reg |= MTK_FORCE_MAC_ACTIVE_BIT;
+ else
+ reg &= ~MTK_FORCE_MAC_ACTIVE_BIT;
+ mtk_pci_mac_write32(priv, REG_PCIE_MISC_CTRL, reg);
+}
+
+static u32 mtk_pci_get_ds_status(struct mtk_md_dev *mdev)
+{
+ u32 reg;
+
+ mtk_pci_force_mac_active(mdev, true);
+ reg = mtk_pci_mac_read32(mdev->hw_priv, REG_PCIE_RESOURCE_STATUS);
+ mtk_pci_force_mac_active(mdev, false);
+
+ return reg;
+}
+
+static void mtk_pci_set_l1ss(struct mtk_md_dev *mdev, u32 type, bool enable)
+{
+ struct mtk_pci_priv *priv = mdev->hw_priv;
+ u32 addr = REG_DIS_ASPM_LOWPWR_SET_0;
+
+ if (enable)
+ addr = REG_DIS_ASPM_LOWPWR_CLR_0;
+
+ mtk_pci_mac_write32(priv, addr, type);
+}
+
static int mtk_pci_get_irq_id(struct mtk_md_dev *mdev, enum mtk_irq_src irq_src)
{
struct mtk_pci_priv *priv = mdev->hw_priv;
@@ -736,6 +775,7 @@ static int mtk_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct mtk_pci_priv *priv;
struct mtk_md_dev *mdev;
int ret;
+ int val;
mdev = devm_kzalloc(dev, sizeof(*mdev), GFP_KERNEL);
if (!mdev) {
@@ -794,6 +834,25 @@ static int mtk_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto free_mhccif;
+ /* lock l1ss and check result */
+ mtk_pci_set_l1ss(mdev, L1SS_BIT_L1(L1SS_PM), false);
+ ret = read_poll_timeout(mtk_pci_get_ds_status, val,
+ (val & MTK_PCI_LOCK_L1SS_STS_MASK) == MTK_PCI_LOCK_L1SS_STS_MASK,
+ MTK_PCI_LOCK_L1SS_POLL_STEP,
+ MTK_PCI_LOCK_L1SS_POLL_TIMEOUT,
+ true,
+ mdev);
+ if (ret) {
+ dev_err(mdev->dev, "Failed to lock L1ss!\n");
+ goto free_irq;
+ }
+
+ ret = mtk_dev_init(mdev);
+ if (ret) {
+ dev_err(mdev->dev, "Failed to init dev.\n");
+ goto free_irq;
+ }
+
/* enable device to host interrupt. */
pci_set_master(pdev);
@@ -802,6 +861,8 @@ static int mtk_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev_info(mdev->dev, "Probe done hw_ver=0x%x\n", mdev->hw_ver);
return 0;
+free_irq:
+ mtk_pci_free_irq(mdev);
free_mhccif:
mtk_mhccif_exit(mdev);
free_bar:
@@ -825,6 +886,7 @@ static void mtk_pci_remove(struct pci_dev *pdev)
int ret;
mtk_pci_mask_irq(mdev, priv->mhccif_irq_id);
+ mtk_dev_exit(mdev);
ret = mtk_pci_fldr(mdev);
if (ret)
--
2.32.0
More information about the Linux-mediatek
mailing list