net: wwan: t7xx: Add debug ports
authorJinjian Song <jinjian.song@fibocom.com>
Mon, 4 Nov 2024 09:44:35 +0000 (17:44 +0800)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 7 Nov 2024 12:33:45 +0000 (13:33 +0100)
Add support for userspace to enable/disable the debug ports(ADB,MIPC).
 - ADB port: /dev/wwan0adb0
 - MIPC port: /dev/wwan0mipc0

Application can use ADB (Android Debug Bridge) port to implement
functions (shell, pull, push ...) by ADB protocol commands.
E.g., ADB commands:
 - A_OPEN: OPEN(local-id, 0, "destination")
 - A_WRTE: WRITE(local-id, remote-id, "data")
 - A_OKEY: READY(local-id, remote-id, "")
 - A_CLSE: CLOSE(local-id, remote-id, "")

Link: https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/main/README.md
Application can use MIPC (Modem Information Process Center) port
to debug antenna tuner or noise profiling through this MTK modem
diagnostic interface.

By default, debug ports are not exposed, so using the command
to enable or disable debug ports.

Enable debug ports:
 - enable: 'echo 1 > /sys/bus/pci/devices/${bdf}/t7xx_debug_ports

Disable debug ports:
 - disable: 'echo 0 > /sys/bus/pci/devices/${bdf}/t7xx_debug_ports

Signed-off-by: Jinjian Song <jinjian.song@fibocom.com>
Reviewed-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Documentation/networking/device_drivers/wwan/t7xx.rst
drivers/net/wwan/t7xx/t7xx_modem_ops.c
drivers/net/wwan/t7xx/t7xx_pci.c
drivers/net/wwan/t7xx/t7xx_pci.h
drivers/net/wwan/t7xx/t7xx_port.h
drivers/net/wwan/t7xx/t7xx_port_proxy.c
drivers/net/wwan/t7xx/t7xx_port_proxy.h
drivers/net/wwan/t7xx/t7xx_port_wwan.c

index f346f5f85f154e6c63d39c340ece51ece758b1d7..4cf777c341cd6c9a01b7e8571b114b99dbd686c0 100644 (file)
@@ -67,6 +67,28 @@ Write from userspace to set the device mode.
 ::
   $ echo fastboot_switching > /sys/bus/pci/devices/${bdf}/t7xx_mode
 
+t7xx_debug_ports
+----------------
+The sysfs interface provides userspace with access to enable/disable the debug
+ports, this interface supports read and write operations.
+
+Debug port status:
+
+- ``1`` represents enable debug ports
+- ``0`` represents disable debug ports
+
+Currently supported debug ports (ADB/MIPC).
+
+Read from userspace to get the current debug ports status.
+
+::
+  $ cat /sys/bus/pci/devices/${bdf}/t7xx_debug_ports
+
+Write from userspace to set the debug ports status.
+
+::
+  $ echo 1 > /sys/bus/pci/devices/${bdf}/t7xx_debug_ports
+
 Management application development
 ==================================
 The driver and userspace interfaces are described below. The MBIM protocol is
@@ -139,6 +161,25 @@ Please note that driver needs to be reloaded to export /dev/wwan0fastboot0
 port, because device needs a cold reset after enter ``fastboot_switching``
 mode.
 
+ADB port userspace ABI
+----------------------
+
+/dev/wwan0adb0 character device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The driver exposes a ADB protocol interface by implementing ADB WWAN Port.
+The userspace end of the ADB channel pipe is a /dev/wwan0adb0 character device.
+Application shall use this interface for ADB protocol communication.
+
+MIPC port userspace ABI
+-----------------------
+
+/dev/wwan0mipc0 character device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The driver exposes a diagnostic interface by implementing MIPC (Modem
+Information Process Center) WWAN Port. The userspace end of the MIPC channel
+pipe is a /dev/wwan0mipc0 character device.
+Application shall use this interface for MTK modem diagnostic communication.
+
 The MediaTek's T700 modem supports the 3GPP TS 27.007 [4] specification.
 
 References
@@ -164,3 +205,9 @@ speak the Mobile Interface Broadband Model (MBIM) protocol"*
 [5] *fastboot "a mechanism for communicating with bootloaders"*
 
 - https://android.googlesource.com/platform/system/core/+/refs/heads/main/fastboot/README.md
+
+[6] *ADB (Android Debug Bridge) "a mechanism to keep track of Android devices
+and emulators instances connected to or running on a given host developer
+machine with ADB protocol"*
+
+- https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/main/README.md
index 79f17100f70b1c690be0302aa9b3a9ee230a26c7..7968e208dd37c1cc1931ed722b2772d23acfe031 100644 (file)
@@ -198,6 +198,7 @@ int t7xx_reset_device(struct t7xx_pci_dev *t7xx_dev, enum reset_type type)
        pci_save_state(t7xx_dev->pdev);
        t7xx_pci_reprobe_early(t7xx_dev);
        t7xx_mode_update(t7xx_dev, T7XX_RESET);
+       WRITE_ONCE(t7xx_dev->debug_ports_show, false);
 
        if (type == FLDR) {
                ret = t7xx_acpi_reset(t7xx_dev, "_RST");
index e556e5bd49abcfcebbd2e701fb5b15e47f3db6ba..7b8c17b029c7a5a2503cd703f6b1be33e253153d 100644 (file)
@@ -41,6 +41,7 @@
 #include "t7xx_pcie_mac.h"
 #include "t7xx_reg.h"
 #include "t7xx_state_monitor.h"
+#include "t7xx_port_proxy.h"
 
 #define T7XX_PCI_IREG_BASE             0
 #define T7XX_PCI_EREG_BASE             2
@@ -120,13 +121,58 @@ static ssize_t t7xx_mode_show(struct device *dev,
 
 static DEVICE_ATTR_RW(t7xx_mode);
 
-static struct attribute *t7xx_mode_attr[] = {
+static ssize_t t7xx_debug_ports_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct t7xx_pci_dev *t7xx_dev;
+       struct pci_dev *pdev;
+       bool show;
+       int ret;
+
+       pdev = to_pci_dev(dev);
+       t7xx_dev = pci_get_drvdata(pdev);
+       if (!t7xx_dev)
+               return -ENODEV;
+
+       ret = kstrtobool(buf, &show);
+       if (ret < 0)
+               return ret;
+
+       t7xx_proxy_debug_ports_show(t7xx_dev, show);
+       WRITE_ONCE(t7xx_dev->debug_ports_show, show);
+
+       return count;
+};
+
+static ssize_t t7xx_debug_ports_show(struct device *dev,
+                                    struct device_attribute *attr,
+                                    char *buf)
+{
+       struct t7xx_pci_dev *t7xx_dev;
+       struct pci_dev *pdev;
+       bool show;
+
+       pdev = to_pci_dev(dev);
+       t7xx_dev = pci_get_drvdata(pdev);
+       if (!t7xx_dev)
+               return -ENODEV;
+
+       show = READ_ONCE(t7xx_dev->debug_ports_show);
+
+       return sysfs_emit(buf, "%d\n", show);
+}
+
+static DEVICE_ATTR_RW(t7xx_debug_ports);
+
+static struct attribute *t7xx_attr[] = {
        &dev_attr_t7xx_mode.attr,
+       &dev_attr_t7xx_debug_ports.attr,
        NULL
 };
 
-static const struct attribute_group t7xx_mode_attribute_group = {
-       .attrs = t7xx_mode_attr,
+static const struct attribute_group t7xx_attribute_group = {
+       .attrs = t7xx_attr,
 };
 
 void t7xx_mode_update(struct t7xx_pci_dev *t7xx_dev, enum t7xx_mode mode)
@@ -839,7 +885,7 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        t7xx_pcie_mac_interrupts_dis(t7xx_dev);
 
        ret = sysfs_create_group(&t7xx_dev->pdev->dev.kobj,
-                                &t7xx_mode_attribute_group);
+                                &t7xx_attribute_group);
        if (ret)
                goto err_md_exit;
 
@@ -855,7 +901,7 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 err_remove_group:
        sysfs_remove_group(&t7xx_dev->pdev->dev.kobj,
-                          &t7xx_mode_attribute_group);
+                          &t7xx_attribute_group);
 
 err_md_exit:
        t7xx_md_exit(t7xx_dev);
@@ -870,7 +916,7 @@ static void t7xx_pci_remove(struct pci_dev *pdev)
        t7xx_dev = pci_get_drvdata(pdev);
 
        sysfs_remove_group(&t7xx_dev->pdev->dev.kobj,
-                          &t7xx_mode_attribute_group);
+                          &t7xx_attribute_group);
        t7xx_md_exit(t7xx_dev);
 
        for (i = 0; i < EXT_INT_NUM; i++) {
index cd8ea17c26441ce40e573e3e9f5b5e80f8eca417..b25d867e72d29c539a58a01a85f4f2c2ce44afb8 100644 (file)
@@ -94,6 +94,7 @@ struct t7xx_pci_dev {
        struct dentry           *debugfs_dir;
 #endif
        u32                     mode;
+       bool                    debug_ports_show;
 };
 
 enum t7xx_pm_id {
index f74d3bab810d849b236e58e1fd3f47a357396d60..9f5d6d288c97e9757bf019170a3fa3f02493c78b 100644 (file)
@@ -42,6 +42,8 @@ enum port_ch {
        /* to AP */
        PORT_CH_AP_CONTROL_RX = 0x1000,
        PORT_CH_AP_CONTROL_TX = 0x1001,
+       PORT_CH_AP_ADB_RX = 0x100a,
+       PORT_CH_AP_ADB_TX = 0x100b,
 
        /* to MD */
        PORT_CH_CONTROL_RX = 0x2000,
@@ -100,6 +102,7 @@ struct t7xx_port_conf {
        struct port_ops         *ops;
        char                    *name;
        enum wwan_port_type     port_type;
+       bool                    debug;
 };
 
 struct t7xx_port {
index 35743e7de0c306c7fdf7be463e2cf3a19fa9187c..4fc131f9632f870caa797498011e402b09327307 100644 (file)
@@ -38,7 +38,8 @@
 #include "t7xx_state_monitor.h"
 
 #define Q_IDX_CTRL                     0
-#define Q_IDX_MBIM                     2
+#define Q_IDX_MBIM_MIPC                2
+#define Q_IDX_ADB                      3
 #define Q_IDX_AT_CMD                   5
 
 #define INVALID_SEQ_NUM                        GENMASK(15, 0)
@@ -66,8 +67,8 @@ static const struct t7xx_port_conf t7xx_port_conf[] = {
        }, {
                .tx_ch = PORT_CH_MBIM_TX,
                .rx_ch = PORT_CH_MBIM_RX,
-               .txq_index = Q_IDX_MBIM,
-               .rxq_index = Q_IDX_MBIM,
+               .txq_index = Q_IDX_MBIM_MIPC,
+               .rxq_index = Q_IDX_MBIM_MIPC,
                .path_id = CLDMA_ID_MD,
                .ops = &wwan_sub_port_ops,
                .name = "MBIM",
@@ -100,7 +101,27 @@ static const struct t7xx_port_conf t7xx_port_conf[] = {
                .path_id = CLDMA_ID_AP,
                .ops = &ctl_port_ops,
                .name = "t7xx_ap_ctrl",
-       },
+       }, {
+               .tx_ch = PORT_CH_AP_ADB_TX,
+               .rx_ch = PORT_CH_AP_ADB_RX,
+               .txq_index = Q_IDX_ADB,
+               .rxq_index = Q_IDX_ADB,
+               .path_id = CLDMA_ID_AP,
+               .ops = &wwan_sub_port_ops,
+               .name = "adb",
+               .port_type = WWAN_PORT_ADB,
+               .debug = true,
+       }, {
+               .tx_ch = PORT_CH_MIPC_TX,
+               .rx_ch = PORT_CH_MIPC_RX,
+               .txq_index = Q_IDX_MBIM_MIPC,
+               .rxq_index = Q_IDX_MBIM_MIPC,
+               .path_id = CLDMA_ID_MD,
+               .ops = &wwan_sub_port_ops,
+               .name = "mipc",
+               .port_type = WWAN_PORT_MIPC,
+               .debug = true,
+       }
 };
 
 static const struct t7xx_port_conf t7xx_early_port_conf[] = {
@@ -505,13 +526,33 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)
                spin_lock_init(&port->port_update_lock);
                port->chan_enable = false;
 
-               if (port_conf->ops && port_conf->ops->init)
+               if (!port_conf->debug &&
+                   port_conf->ops &&
+                   port_conf->ops->init)
                        port_conf->ops->init(port);
        }
 
        t7xx_proxy_setup_ch_mapping(port_prox);
 }
 
+void t7xx_proxy_debug_ports_show(struct t7xx_pci_dev *t7xx_dev, bool show)
+{
+       struct port_proxy *port_prox = t7xx_dev->md->port_prox;
+       struct t7xx_port *port;
+       int i;
+
+       for_each_proxy_port(i, port, port_prox) {
+               const struct t7xx_port_conf *port_conf = port->port_conf;
+
+               if (port_conf->debug && port_conf->ops) {
+                       if (show && port_conf->ops->init)
+                               port_conf->ops->init(port);
+                       else if (!show && port_conf->ops->uninit)
+                               port_conf->ops->uninit(port);
+               }
+       }
+}
+
 void t7xx_port_proxy_set_cfg(struct t7xx_modem *md, enum port_cfg_id cfg_id)
 {
        struct port_proxy *port_prox = md->port_prox;
index 7f5706811445baaa7c0213c3a225c95342644233..f0918b36e899bd4bc2cb1b971b929589c8b1aed6 100644 (file)
@@ -98,6 +98,7 @@ extern struct port_ops ctl_port_ops;
 extern struct port_ops t7xx_trace_port_ops;
 #endif
 
+void t7xx_proxy_debug_ports_show(struct t7xx_pci_dev *t7xx_dev, bool show);
 void t7xx_port_proxy_reset(struct port_proxy *port_prox);
 void t7xx_port_proxy_uninit(struct port_proxy *port_prox);
 int t7xx_port_proxy_init(struct t7xx_modem *md);
index 4b23ba693f3f1d8095bf784babb6d8a56fd6b204..7fc569565ff99a4b7ab8fc26ca819d043eb8339f 100644 (file)
@@ -169,7 +169,9 @@ static int t7xx_port_wwan_init(struct t7xx_port *port)
 {
        const struct t7xx_port_conf *port_conf = port->port_conf;
 
-       if (port_conf->port_type == WWAN_PORT_FASTBOOT)
+       if (port_conf->port_type == WWAN_PORT_FASTBOOT ||
+           port_conf->port_type == WWAN_PORT_ADB ||
+           port_conf->port_type == WWAN_PORT_MIPC)
                t7xx_port_wwan_create(port);
 
        port->rx_length_th = RX_QUEUE_MAXLEN;
@@ -224,7 +226,9 @@ static void t7xx_port_wwan_md_state_notify(struct t7xx_port *port, unsigned int
 {
        const struct t7xx_port_conf *port_conf = port->port_conf;
 
-       if (port_conf->port_type == WWAN_PORT_FASTBOOT)
+       if (port_conf->port_type == WWAN_PORT_FASTBOOT ||
+           port_conf->port_type == WWAN_PORT_ADB ||
+           port_conf->port_type == WWAN_PORT_MIPC)
                return;
 
        if (state != MD_STATE_READY)