[][MT79xx add USBIF compliance toolkit]
[Description]
Add USBIF compliance toolkit for MT79xx
hqa
usb3hqa
RG_USB20_INTR_EN
RG_UsB20_VRT_VREF_SEL
RG_USB20_TERM_VREF_SEL
RG_USB20_HSTX_SRCTRL
RG_USB20_DISCTH
RG_CHGDT_EN
reg
fixed Port1 show USB20, it shows USB30
[Release-log]
N/A
Change-Id: Iad411fd7ba992a25fc9a72e62cf6e5b421bf10c4
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5694096
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/unusual-declaration.h b/target/linux/mediatek/files-5.4/drivers/usb/host/unusual-declaration.h
index f517e20..70db398 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/unusual-declaration.h
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/unusual-declaration.h
@@ -13,6 +13,7 @@
DEVICE_ATTR_DECLARED(RG_USB20_HSTX_SRCTRL);
DEVICE_ATTR_DECLARED(RG_USB20_DISCTH);
DEVICE_ATTR_DECLARED(RG_CHGDT_EN);
+ DEVICE_ATTR_DECLARED(reg);
#define HQA_INFORMACTION_COLLECTS() do {\
ECHO_HQA(USB20_PHY_USBPHYACR0, RG_USB20_INTR_EN, 1); \
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/unusual-statement.h b/target/linux/mediatek/files-5.4/drivers/usb/host/unusual-statement.h
index b929342..e898a26 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/unusual-statement.h
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/unusual-statement.h
@@ -13,4 +13,5 @@
UNUSUAL_DEVICE_ATTR(RG_USB20_HSTX_SRCTRL),
UNUSUAL_DEVICE_ATTR(RG_USB20_DISCTH),
UNUSUAL_DEVICE_ATTR(RG_CHGDT_EN),
+UNUSUAL_DEVICE_ATTR(reg),
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-chgdt-en.c b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-chgdt-en.c
index 13626c1..575680e 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-chgdt-en.c
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-chgdt-en.c
@@ -21,6 +21,7 @@
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
struct usb_hcd *hcd = mtk->hcd;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct device_node *node = dev->of_node;
ssize_t cnt = 0;
void __iomem *addr;
u32 val;
@@ -64,8 +65,8 @@
cnt += sprintf(buf + cnt,
"USB20 Port%i: 0x%08X\n", i, val);
- ret = query_phy_addr(dev->of_node,
- &index, &io, &length);
+ ret = query_phy_addr(node,
+ &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES) {
if (ret == -EPERM)
cnt += sprintf(buf + cnt,
@@ -139,7 +140,7 @@
hqa_info(mtk, " params: %i %i %s\n",
port, index, str);
- ret = query_phy_addr(node, &index, &io, &length);
+ ret = query_phy_addr(node, &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES)
goto error;
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-discth.c b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-discth.c
index 66a024a..83a94bd 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-discth.c
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-discth.c
@@ -21,6 +21,7 @@
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
struct usb_hcd *hcd = mtk->hcd;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct device_node *node = dev->of_node;
ssize_t cnt = 0;
void __iomem *addr;
u32 val;
@@ -66,8 +67,8 @@
cnt += sprintf(buf + cnt,
"USB20 Port%i: 0x%08X\n", i, val);
- ret = query_phy_addr(dev->of_node,
- &index, &io, &length);
+ ret = query_phy_addr(node,
+ &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES) {
if (ret == -EPERM)
cnt += sprintf(buf + cnt,
@@ -141,7 +142,7 @@
hqa_info(mtk, " params: %i %i %s\n",
port, index, str);
- ret = query_phy_addr(node, &index, &io, &length);
+ ret = query_phy_addr(node, &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES)
goto error;
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-hstx-srctrl.c b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-hstx-srctrl.c
index a7791cf..a387798 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-hstx-srctrl.c
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-hstx-srctrl.c
@@ -21,6 +21,7 @@
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
struct usb_hcd *hcd = mtk->hcd;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct device_node *node = dev->of_node;
ssize_t cnt = 0;
void __iomem *addr;
u32 val;
@@ -66,8 +67,8 @@
cnt += sprintf(buf + cnt,
"USB20 Port%i: 0x%08X\n", i, val);
- ret = query_phy_addr(dev->of_node,
- &index, &io, &length);
+ ret = query_phy_addr(node,
+ &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES) {
if (ret == -EPERM)
cnt += sprintf(buf + cnt,
@@ -141,7 +142,7 @@
hqa_info(mtk, " params: %i %i %s\n",
port, index, str);
- ret = query_phy_addr(node, &index, &io, &length);
+ ret = query_phy_addr(node, &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES)
goto error;
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-intr-en.c b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-intr-en.c
index acdaf8b..3922c73 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-intr-en.c
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-intr-en.c
@@ -21,6 +21,7 @@
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
struct usb_hcd *hcd = mtk->hcd;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct device_node *node = dev->of_node;
ssize_t cnt = 0;
void __iomem *addr;
u32 val;
@@ -65,8 +66,8 @@
cnt += sprintf(buf + cnt,
"USB20 Port%i: 0x%08X\n", i, val);
- ret = query_phy_addr(dev->of_node,
- &index, &io, &length);
+ ret = query_phy_addr(node,
+ &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES) {
if (ret == -EPERM)
cnt += sprintf(buf + cnt,
@@ -140,7 +141,7 @@
hqa_info(mtk, " params: %i %i %s\n",
port, index, str);
- ret = query_phy_addr(node, &index, &io, &length);
+ ret = query_phy_addr(node, &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES)
goto error;
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-reg.c b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-reg.c
new file mode 100644
index 0000000..366747d
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-reg.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * xHCI host controller toolkit driver for intr-en
+ *
+ * Copyright (C) 2021 MediaTek Inc.
+ *
+ * Author: Zhanyong Wang <zhanyong.wang@mediatek.com>
+ */
+
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include "xhci-mtk.h"
+#include "xhci-mtk-test.h"
+#include "xhci-mtk-unusual.h"
+
+#define REGS_LIMIT_XHCI 0x1000
+#define REGS_LIMIT_MU3D 0x2e00
+static ssize_t reg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
+ ssize_t cnt = 0;
+
+ cnt += sprintf(buf + cnt,
+ "SSUSB register operation interface help info.\n"
+ " rx - read xhci reg: offset [len]\n"
+ " rm - read mu3d reg: offset [len]\n"
+ " ri - read ippc reg: offset [len]\n"
+ " rp - read phy reg: offset [len]\n"
+ " wx - write xhci reg: offset value\n"
+ " wm - write mu3d reg: offset value\n"
+ " wi - write ippc reg: offset value\n"
+ " wp - write phy reg: offset value\n"
+ " sx - set xhci mac reg bits: offset bit_start mask value\n"
+ " sm - set mu3d mac reg bits: offset bit_start mask value\n"
+ " si - set ippc reg bits: offset bit_start mask value\n"
+ " sp - set phy reg bits: offset bit_start mask value\n"
+ " px - print xhci mac reg bits: offset bit_start mask\n"
+ " pm - print mu3d mac reg bits: offset bit_start mask\n"
+ " pi - print ippc reg bits: offset bit_start mask\n"
+ " pp - print phy reg bits: offset bit_start mask\n"
+ " NOTE: numbers should be HEX, except bit_star(DEC)\n");
+
+ if (mtk->hqa_pos) {
+ cnt += sprintf(buf + cnt, "%s", mtk->hqa_buf);
+ mtk->hqa_pos = 0;
+ }
+
+ return cnt;
+}
+
+/* base address: return value; limit is put into @limit */
+static void __iomem *get_reg_base_limit(struct xhci_hcd_mtk *mtk,
+ const char *buf, u32 *limit)
+{
+ struct usb_hcd *hcd = mtk->hcd;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct platform_device *device = to_platform_device(mtk->dev);
+ void __iomem *base = NULL;
+ struct device_node *node = mtk->dev->of_node;
+ u32 io = 0;
+ u32 range = 0;
+ u32 len = 0;
+ int index = 0;
+ int ret = 0;
+
+ switch (buf[1]) {
+ case 'x':
+ ret = query_reg_addr(device, &io, &range, "mac");
+ if (ret) break;
+
+ base = ioremap(io, range);
+
+ xhci_info(xhci, "xhci's reg: [0x%08X ~ 0x%08X]\n",
+ io, io + range);
+ hqa_info (mtk, "xhci's reg: [0x%08X ~ 0x%08X]\n",
+ io, io + range);
+ break;
+ case 'm':
+ if (!mtk->has_ippc)
+ device = to_platform_device(device->dev.parent);
+
+ ret = query_reg_addr(device, &io, &range, "mac");
+ if (ret) break;
+
+ if (mtk->has_ippc) {
+ io += REGS_LIMIT_XHCI;
+ range = REGS_LIMIT_MU3D;
+ }
+
+ base = ioremap(io, range);
+ xhci_info(xhci, "mu3d's reg: [0x%08X ~ 0x%08X]\n",
+ io, io + range);
+ hqa_info (mtk, "mu3d's reg: [0x%08X ~ 0x%08X]\n",
+ io, io + range);
+ break;
+ case 'i':
+ ret = query_reg_addr(device, &io, &range, "ippc");
+ if (ret) break;
+
+ base = ioremap(io, range);
+ xhci_info(xhci, "ippc's reg: [0x%08X ~ 0x%08X]\n",
+ io, io + range);
+ hqa_info (mtk, "ippc's reg: [0x%08X ~ 0x%08X]\n",
+ io, io + range);
+ break;
+ case 'p':
+ ret = query_phy_addr(node, &index, &io, &len, PHY_TYPE_USB3);
+ if (ret && ret != -EACCES) break;
+
+ range = io & 0x0000FFFF;
+ range += len;
+
+ io &= 0xFFFF0000;
+
+ base = ioremap(io, range);
+ xhci_info(xhci, "phy's reg: [0x%08X ~ 0x%08X]\n",
+ io, io + range);
+ hqa_info (mtk, "phy's reg: [0x%08X ~ 0x%08X]\n",
+ io, io + range);
+ break;
+ default:
+ base = NULL;
+ }
+
+ *limit = range;
+
+ return base;
+}
+
+static void ssusb_write_reg(struct xhci_hcd_mtk *mtk, const char *buf)
+{
+ struct usb_hcd *hcd = mtk->hcd;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ void __iomem *base;
+ u32 offset = 0;
+ u32 value = 0;
+ u32 old_val = 0;
+ u32 limit = 0;
+ u32 param;
+
+ param = sscanf(buf, "%*s 0x%x 0x%x", &offset, &value);
+ xhci_info(xhci, "params-%d (offset: %#x, value: %#x)\n",
+ param, offset, value);
+ hqa_info (mtk, "params-%d (offset: %#x, value: %#x)\n",
+ param, offset, value);
+
+ base = get_reg_base_limit(mtk, buf, &limit);
+ if (!base || (param != 2)) {
+ xhci_err(xhci, "params are invalid!\n");
+ hqa_info(mtk, "params are invalid since %p, %u!\n",
+ base, param);
+ return;
+ }
+
+ offset &= ~0x3; /* 4-bytes align */
+ if (offset >= limit) {
+ xhci_err(xhci, "reg's offset overrun!\n");
+ hqa_info(mtk, "reg's offset overrun since %u >= %u!\n",
+ offset, limit);
+ return;
+ }
+ old_val = readl(base + offset);
+ writel(value, base + offset);
+ xhci_info(xhci, "0x%8.8x : 0x%8.8x --> 0x%8.8x\n", offset, old_val,
+ readl(base + offset));
+ hqa_info (mtk, "0x%8.8x : 0x%8.8x --> 0x%8.8x\n", offset, old_val,
+ readl(base + offset));
+
+ base = (void __iomem *)((unsigned long)base & 0xFFFF0000);
+ iounmap(base);
+}
+
+static void read_single_reg(struct xhci_hcd_mtk *mtk,
+ void __iomem *base, u32 offset, u32 limit)
+{
+ struct usb_hcd *hcd = mtk->hcd;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ u32 value;
+
+ offset &= ~0x3; /* 4-bytes align */
+ if (offset >= limit) {
+ xhci_err(xhci, "reg's offset overrun!\n");
+ hqa_info(mtk, "reg's offset overrun since %u >= %u!\n",
+ offset, limit);
+ return;
+ }
+ value = readl(base + offset);
+ xhci_err(xhci, "0x%8.8x : 0x%8.8x\n", offset, value);
+ hqa_info(mtk, "0x%8.8x : 0x%8.8x\n", offset, value);
+}
+
+static void read_multi_regs(struct xhci_hcd_mtk *mtk,
+ void __iomem *base, u32 offset, u32 len, u32 limit)
+{
+ struct usb_hcd *hcd = mtk->hcd;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ int i;
+
+ /* at least 4 ints */
+ offset &= ~0xF;
+ len = (len + 0x3) & ~0x3;
+
+ if (offset + len > limit) {
+ xhci_err(xhci, "reg's offset overrun!\n");
+ hqa_info(mtk, "reg's offset overrun since %u > %u!\n",
+ offset + len, limit);
+ return;
+ }
+
+ len >>= 2;
+ xhci_info(xhci, "read regs [%#x, %#x)\n", offset, offset + (len << 4));
+ hqa_info (mtk, "read regs [%#x, %#x)\n", offset, offset + (len << 4));
+ for (i = 0; i < len; i++) {
+ xhci_err(xhci, "0x%8.8x : 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
+ offset, readl(base + offset),
+ readl(base + offset + 0x4),
+ readl(base + offset + 0x8),
+ readl(base + offset + 0xc));
+ hqa_info(mtk, "0x%8.8x : 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
+ offset, readl(base + offset),
+ readl(base + offset + 0x4),
+ readl(base + offset + 0x8),
+ readl(base + offset + 0xc));
+ offset += 0x10;
+ }
+}
+
+static void ssusb_read_regs(struct xhci_hcd_mtk *mtk, const char *buf)
+{
+ struct usb_hcd *hcd = mtk->hcd;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ void __iomem *base;
+ u32 offset = 0;
+ u32 len = 0;
+ u32 limit = 0;
+ u32 param;
+
+ param = sscanf(buf, "%*s 0x%x 0x%x", &offset, &len);
+ xhci_info(xhci, "params-%d (offset: %#x, len: %#x)\n",
+ param, offset, len);
+ hqa_info (mtk, "params-%d (offset: %#x, len: %#x)\n",
+ param, offset, len);
+
+ base = get_reg_base_limit(mtk, buf, &limit);
+ if (!base || !param) {
+ xhci_err(xhci, "params are invalid!\n");
+ hqa_info(mtk, "params are invalid since %p, %u!\n",
+ base, param);
+ return;
+ }
+
+ if (param == 1)
+ read_single_reg(mtk, base, offset, limit);
+ else
+ read_multi_regs(mtk, base, offset, len, limit);
+
+ base = (void __iomem *)((unsigned long)base & 0xFFFF0000);
+ iounmap(base);
+}
+
+static void ssusb_set_reg_bits(struct xhci_hcd_mtk *mtk, const char *buf)
+{
+ struct usb_hcd *hcd = mtk->hcd;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ void __iomem *base;
+ u32 offset = 0;
+ u32 bit_start = 0;
+ u32 mask = 0;
+ u32 value = 0;
+ u32 old_val = 0;
+ u32 new_val = 0;
+ u32 limit = 0;
+ u32 param;
+
+ param = sscanf(buf, "%*s 0x%x %d 0x%x 0x%x",
+ &offset, &bit_start, &mask, &value);
+ xhci_info(xhci, "params-%d (offset:%#x,bit_start:%d,mask:%#x,value:%#x)\n",
+ param, offset, bit_start, mask, value);
+ hqa_info(mtk, "params-%d (offset:%#x,bit_start:%d,mask:%#x,value:%#x)\n",
+ param, offset, bit_start, mask, value);
+
+ base = get_reg_base_limit(mtk, buf, &limit);
+ if (!base || (param != 4) || (bit_start > 31)) {
+ xhci_err(xhci, "params are invalid!\n");
+ hqa_info(mtk, "params are invalid since %p, %u, %u\n",
+ base, param, bit_start);
+ return;
+ }
+
+ offset &= ~0x3; /* 4-bytes align */
+ if (offset >= limit) {
+ xhci_err(xhci, "reg's offset overrun!\n");
+ hqa_info(mtk, "reg's offset overrun since %u >= %u!\n",
+ offset, limit);
+ return;
+ }
+ old_val = readl(base + offset);
+ new_val = old_val;
+ new_val &= ~(mask << bit_start);
+ new_val |= (value << bit_start);
+ writel(new_val, base + offset);
+ xhci_info(xhci, "0x%8.8x : 0x%8.8x --> 0x%8.8x\n", offset, old_val,
+ readl(base + offset));
+ hqa_info (mtk, "0x%8.8x : 0x%8.8x --> 0x%8.8x\n", offset, old_val,
+ readl(base + offset));
+
+ base = (void __iomem *)((unsigned long)base & 0xFFFF0000);
+ iounmap(base);
+}
+
+static void ssusb_print_reg_bits(struct xhci_hcd_mtk *mtk, const char *buf)
+{
+ struct usb_hcd *hcd = mtk->hcd;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ void __iomem *base;
+ u32 offset = 0;
+ u32 bit_start = 0;
+ u32 mask = 0;
+ u32 old_val = 0;
+ u32 new_val = 0;
+ u32 limit = 0;
+ u32 param;
+
+ param = sscanf(buf, "%*s 0x%x %d 0x%x", &offset, &bit_start, &mask);
+ xhci_info(xhci, "params-%d (offset: %#x, bit_start: %d, mask: %#x)\n",
+ param, offset, bit_start, mask);
+ hqa_info (mtk, "params-%d (offset: %#x, bit_start: %d, mask: %#x)\n",
+ param, offset, bit_start, mask);
+
+ base = get_reg_base_limit(mtk, buf, &limit);
+ if (!base || (param != 3) || (bit_start > 31)) {
+ xhci_err(xhci, "params are invalid!\n");
+ hqa_info(mtk, "params are invalid since %p, %u, %u\n",
+ base, param, bit_start);
+ return;
+ }
+
+ offset &= ~0x3; /* 4-bytes align */
+ if (offset >= limit) {
+ xhci_err(xhci, "reg's offset overrun!\n");
+ hqa_info(mtk, "reg's offset overrun since %u >= %u!\n",
+ offset, limit);
+ return;
+ }
+
+ old_val = readl(base + offset);
+ new_val = old_val;
+ new_val >>= bit_start;
+ new_val &= mask;
+ xhci_info(xhci, "0x%8.8x : 0x%8.8x (0x%x)\n", offset, old_val, new_val);
+ hqa_info (mtk, "0x%8.8x : 0x%8.8x (0x%x)\n", offset, old_val, new_val);
+
+ base = (void __iomem *)((unsigned long)base & 0xFFFF0000);
+ iounmap(base);
+}
+
+static ssize_t
+reg_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
+ struct usb_hcd *hcd = mtk->hcd;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+ xhci_info(xhci, "cmd:%s\n", buf);
+ hqa_info (mtk, "cmd:%s\n", buf);
+
+ switch (buf[0]) {
+ case 'w':
+ ssusb_write_reg(mtk, buf);
+ break;
+ case 'r':
+ ssusb_read_regs(mtk, buf);
+ break;
+ case 's':
+ ssusb_set_reg_bits(mtk, buf);
+ break;
+ case 'p':
+ ssusb_print_reg_bits(mtk, buf);
+ break;
+ default:
+ xhci_err(xhci, "No such cmd\n");
+ hqa_info(mtk, "No such cmd\n");
+ }
+
+ return n;
+}
+DEVICE_ATTR_RW(reg);
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-term-vref.c b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-term-vref.c
index 3b40ef9..31861be 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-term-vref.c
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-term-vref.c
@@ -22,6 +22,7 @@
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
struct usb_hcd *hcd = mtk->hcd;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct device_node *node = dev->of_node;
ssize_t cnt = 0;
void __iomem *addr;
u32 val;
@@ -67,8 +68,8 @@
cnt += sprintf(buf + cnt,
"USB20 Port%i: 0x%08X\n", i, val);
- ret = query_phy_addr(dev->of_node,
- &index, &io, &length);
+ ret = query_phy_addr(node,
+ &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES) {
if (ret == -EPERM)
cnt += sprintf(buf + cnt,
@@ -143,7 +144,7 @@
hqa_info(mtk, " params: %i %i %s\n",
port, index, str);
- ret = query_phy_addr(node, &index, &io, &length);
+ ret = query_phy_addr(node, &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES)
goto error;
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-test.c b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-test.c
index 4939e55..36564d2 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-test.c
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-test.c
@@ -16,6 +16,8 @@
#include <linux/kobject.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
#include <dt-bindings/phy/phy.h>
#include "../core/usb.h"
#include "xhci-mtk.h"
@@ -32,20 +34,50 @@
int argc, char **argv);
static int t_test_enumerate_bus(struct xhci_hcd_mtk *mtk,
int argc, char **argv);
+static int t_debug_port(struct xhci_hcd_mtk *mtk, int argc, char **argv);
static int t_power_u1u2(struct xhci_hcd_mtk *mtk, int argc, char **argv);
#define PORT_PLS_VALUE(p) ((p >> 5) & 0xf)
+/* ip_xhci_cap register */
+#define CAP_U3_PORT_NUM(p) ((p) & 0xff)
+#define CAP_U2_PORT_NUM(p) (((p) >> 8) & 0xff)
#define MAX_NAME_SIZE 32
#define MAX_ARG_SIZE 4
+struct class_info {
+ int class;
+ char *class_name;
+};
+
+static const struct class_info clas_info[] = {
+ /* max. 5 chars. per name string */
+ {USB_CLASS_PER_INTERFACE, ">ifc"},
+ {USB_CLASS_AUDIO, "audio"},
+ {USB_CLASS_COMM, "comm."},
+ {USB_CLASS_HID, "HID"},
+ {USB_CLASS_PHYSICAL, "PID"},
+ {USB_CLASS_STILL_IMAGE, "still"},
+ {USB_CLASS_PRINTER, "print"},
+ {USB_CLASS_MASS_STORAGE, "stor."},
+ {USB_CLASS_HUB, "hub"},
+ {USB_CLASS_CDC_DATA, "data"},
+ {USB_CLASS_CSCID, "scard"},
+ {USB_CLASS_CONTENT_SEC, "c-sec"},
+ {USB_CLASS_VIDEO, "video"},
+ {USB_CLASS_WIRELESS_CONTROLLER, "wlcon"},
+ {USB_CLASS_MISC, "misc"},
+ {USB_CLASS_APP_SPEC, "app."},
+ {USB_CLASS_VENDOR_SPEC, "vend."},
+ {-1, "unk."} /* leave as last */
+};
+
struct hqa_test_cmd {
char name[MAX_NAME_SIZE];
int (*cb_func)(struct xhci_hcd_mtk *mtk, int argc, char **argv);
char *discription;
};
-
struct hqa_test_cmd xhci_mtk_hqa_cmds[] = {
{"test.j", &t_test_j, "Test_J"},
{"test.k", &t_test_k, "Test_K"},
@@ -56,10 +88,20 @@
{"test.enumbus", &t_test_enumerate_bus, "Enumerate Bus"},
{"test.getdesc", &t_test_get_device_descriptor,
"Get Device Discriptor"},
+ {"test.debug", &t_debug_port, "debug Port infor"},
{"pm.u1u2", &t_power_u1u2, "Port U1,U2"},
{"", NULL, ""},
};
+static const char *class_decode(const int class)
+{
+ int i;
+
+ for (i = 0; clas_info[i].class != -1; i++)
+ if (clas_info[i].class == class)
+ break;
+ return clas_info[i].class_name;
+}
int call_hqa_func(struct xhci_hcd_mtk *mtk, char *buf)
{
@@ -256,6 +298,82 @@
return retval;
}
+static void show_string(struct usb_device *udev, char *id, char *string)
+{
+ if (!string)
+ return;
+ dev_info(&udev->dev, "%s: %s\n", id, string);
+}
+
+static void announce_device(struct usb_device *udev)
+{
+ u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);
+
+ dev_info(&udev->dev,
+ "New USB device found, idVendor=%04x, idProduct=%04x, bcdDevice=%2x.%02x\n",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct),
+ bcdDevice >> 8, bcdDevice & 0xff);
+ dev_info(&udev->dev,
+ "New USB device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
+ udev->descriptor.iManufacturer,
+ udev->descriptor.iProduct,
+ udev->descriptor.iSerialNumber);
+ show_string(udev, "Product", udev->product);
+ show_string(udev, "Manufacturer", udev->manufacturer);
+ show_string(udev, "SerialNumber", udev->serial);
+}
+
+static int t_debug_port(struct xhci_hcd_mtk *mtk, int argc, char **argv)
+{
+ struct usb_hcd *hcd = mtk->hcd;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct usb_device *usb2_rh;
+ struct usb_device *udev;
+ long port_id;
+ const struct usb_device_descriptor *desc;
+ u16 bcdUSB;
+ u16 bcdDevice;
+
+ port_id = 2;
+
+ if (argc > 1 && kstrtol(argv[1], 10, &port_id))
+ xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
+
+ xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
+
+
+ usb2_rh = hcd->self.root_hub;
+ udev = usb_hub_find_child(usb2_rh, port_id - 1);
+ if (udev == NULL) {
+ xhci_err(xhci, "mu3h %s usb_hub_find_child(..., %i) failed\n", __func__, (int)port_id);
+ return -EPERM;
+ }
+
+ dev_info(&udev->dev, "%s\n", usb_state_string(udev->state));
+ if (udev && udev->state == USB_STATE_CONFIGURED) {
+ announce_device(udev);
+ desc = (const struct usb_device_descriptor *)&udev->descriptor;
+ bcdUSB = le16_to_cpu(desc->bcdUSB);
+ bcdDevice = le16_to_cpu(desc->bcdDevice);
+
+ dev_info(&udev->dev, "D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n",
+ bcdUSB >> 8, bcdUSB & 0xff,
+ desc->bDeviceClass,
+ class_decode(desc->bDeviceClass),
+ desc->bDeviceSubClass,
+ desc->bDeviceProtocol,
+ desc->bMaxPacketSize0,
+ desc->bNumConfigurations);
+
+ dev_info(&udev->dev, "P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n",
+ le16_to_cpu(desc->idVendor),
+ le16_to_cpu(desc->idProduct),
+ bcdDevice >> 8, bcdDevice & 0xff);
+ }
+
+ return 0;
+}
static int t_test_suspend(struct xhci_hcd_mtk *mtk, int argc, char **argv)
{
@@ -447,33 +565,43 @@
u32 val;
u32 ports;
int len = 0;
- int bufLen = PAGE_SIZE;
struct hqa_test_cmd *hqa;
int i;
- len += snprintf(buf+len, bufLen-len, "info:\n");
- len += snprintf(buf+len, bufLen-len,
+ len += sprintf(buf+len, "info:\n");
+ len += sprintf(buf+len,
"\techo -n item port-id > hqa\n");
- len += snprintf(buf+len, bufLen-len,
+ len += sprintf(buf+len,
"\tport-id : based on number of usb3-port, e.g.\n");
- len += snprintf(buf+len, bufLen-len,
+ len += sprintf(buf+len,
"\t\txHCI with 1 u3p, 2 u2p: 1st u2p-id is 2(1+1), 2nd is 3\n");
- len += snprintf(buf+len, bufLen-len, "items:\n");
+ len += sprintf(buf+len, "items:\n");
for (i = 0; i < ARRAY_SIZE(xhci_mtk_hqa_cmds); i++) {
hqa = &xhci_mtk_hqa_cmds[i];
- len += snprintf(buf+len, bufLen-len,
+ len += sprintf(buf+len,
"\t%s: %s\n", hqa->name, hqa->discription);
}
ports = mtk->num_u3_ports + mtk->num_u2_ports;
- for (i = mtk->num_u3_ports + 1; i <= ports; i++) {
- addr = &xhci->op_regs->port_power_base +
+ for (i = 1; i <= ports; i++) {
+ addr = &xhci->op_regs->port_status_base +
NUM_PORT_REGS * ((i - 1) & 0xff);
val = readl(addr);
- len += snprintf(buf+len, bufLen-len,
- "USB20 Port%i PORTMSC[31,28] 4b'0000: 0x%08X\n",
- i, val);
+ if (i <= mtk->num_u3_ports)
+ len += sprintf(buf + len,
+ "USB30 Port%i: 0x%08X\n", i, val);
+ else {
+ len += sprintf(buf + len,
+ "USB20 Port%i: 0x%08X\n", i, val);
+
+ addr = &xhci->op_regs->port_power_base +
+ NUM_PORT_REGS * ((i - 1) & 0xff);
+ val = readl(addr);
+ len += sprintf(buf+len,
+ "USB20 Port%i PORTMSC[31,28] 4b'0000: 0x%08X\n",
+ i, val);
+ }
}
return len;
@@ -511,17 +639,17 @@
int ports;
cnt += sprintf(buf + cnt, "usb3hqa usage:\n");
- cnt += sprintf(buf + cnt, " echo u3port >usb3hqa\n");
+ cnt += sprintf(buf + cnt, " echo [u3port] >usb3hqa\n");
ports = mtk->num_u3_ports + mtk->num_u2_ports;
for (i = 1; i <= ports; i++) {
addr = &xhci->op_regs->port_status_base +
NUM_PORT_REGS * ((i - 1) & 0xff);
val = readl(addr);
- if (i < mtk->num_u3_ports)
+ if (i <= mtk->num_u3_ports)
cnt += sprintf(buf + cnt,
"USB30 Port%i: 0x%08X\n", i, val);
- else
+ else
cnt += sprintf(buf + cnt,
"USB20 Port%i: 0x%08X\n", i, val);
}
@@ -554,8 +682,8 @@
words = sscanf(buf, "%d", &port);
if ((words != 1) ||
(port < 1 || port > mtk->num_u3_ports)) {
- hqa_info(mtk, "usb3hqa: param number:%i, port:%i failure\n",
- words, port);
+ hqa_info(mtk, "usb3hqa: param number:%i, port:%i (%i) failure\n",
+ words, port, mtk->num_u3_ports);
return -EINVAL;
}
@@ -580,9 +708,16 @@
int hqa_create_attr(struct device *dev)
{
- int idx, err = 0;
- int num = ARRAY_SIZE(mu3h_hqa_attr_list);
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
+ struct usb_hcd *hcd = mtk->hcd;
+ struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
+ struct platform_device *device = to_platform_device(dev);
+ int num = ARRAY_SIZE(mu3h_hqa_attr_list);
+ int idx;
+ int err = 0;
+ u32 value;
+ u32 addr = hcd->rsrc_start;
+ u32 length;
if (dev == NULL || mtk == NULL)
return -EINVAL;
@@ -593,6 +728,19 @@
if (!mtk->hqa_buf)
return -ENOMEM;
+ if (!mtk->has_ippc) {
+ err = query_reg_addr(device, &addr, &length, "ippc");
+ if (err)
+ return -EINVAL;
+
+ mtk->ippc_regs = ioremap(addr, length);
+ }
+
+ ippc = mtk->ippc_regs;
+ value = readl(&ippc->ip_xhci_cap);
+ mtk->num_u3_ports = CAP_U3_PORT_NUM(value);
+ mtk->num_u2_ports = CAP_U2_PORT_NUM(value);
+
for (idx = 0; idx < num; idx++) {
err = device_create_file(dev, mu3h_hqa_attr_list[idx]);
if (err)
@@ -614,4 +762,8 @@
kfree(mtk->hqa_buf);
mtk->hqa_size = 0;
mtk->hqa_pos = 0;
+ if (!mtk->has_ippc) {
+ iounmap(mtk->ippc_regs);
+ mtk->ippc_regs = NULL;
+ }
}
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-test.h b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-test.h
index 83e1542..7f76d29 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-test.h
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-test.h
@@ -15,6 +15,8 @@
#ifdef CONFIG_USB_XHCI_MTK_DEBUGFS
int hqa_create_attr(struct device *dev);
void hqa_remove_attr(struct device *dev);
+void ssusb_remap_ip_regs(struct device *dev);
+
#else
static inline int hqa_create_attr(struct device *dev)
{
@@ -23,5 +25,8 @@
static inline void hqa_remove_attr(struct device *dev)
{
}
+static inline void ssusb_remap_ip_regs(struct device *dev)
+{
+}
#endif
#endif /* __XHCI_MTK_TEST_H */
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-unusual.c b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-unusual.c
index 14d7d0b..01029fb 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-unusual.c
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-unusual.c
@@ -13,7 +13,6 @@
#include <linux/usb.h>
#include <linux/of.h>
#include <linux/of_address.h>
-#include <dt-bindings/phy/phy.h>
#include "xhci-mtk.h"
#include "xhci-mtk-test.h"
#include "xhci-mtk-unusual.h"
@@ -127,42 +126,81 @@
return value;
}
-int query_phy_addr(struct device_node *np, int *start, u32 *addr, u32 *length)
+int query_phy_addr(struct device_node *np, int *start, u32 *addr, u32 *length, int type)
{
int ret = -EPERM;
struct of_phandle_args args;
struct resource res;
+ struct device_node *node = np;
int numphys = 0;
int index;
- if (start == NULL || addr == NULL || length == NULL)
+ if (np == NULL || start == NULL || addr == NULL || length == NULL)
return -EINVAL;
- numphys = of_count_phandle_with_args(np, "phys", "#phy-cells");
- for ( index = *start; (numphys > 0) && index < numphys; index++) {
- ret = of_parse_phandle_with_args(np, "phys", "#phy-cells",
+ while (node) {
+ numphys = of_count_phandle_with_args(node,
+ "phys", "#phy-cells");
+ for (index = *start;
+ (numphys > 0) && index < numphys; index++) {
+ ret = of_parse_phandle_with_args(node,
+ "phys", "#phy-cells",
index, &args);
- if (ret < 0)
- break;
+ if (ret < 0)
+ break;
+
+ if (args.args[0] == type) {
+ ret = of_address_to_resource(args.np,
+ 0, &res);
+ if (ret < 0) {
+ of_node_put(args.np);
+ break;
+ }
- if (args.args[0] == PHY_TYPE_USB2) {
- ret = of_address_to_resource(args.np, 0, &res);
- if (ret < 0) {
+ *addr = res.start;
+ *length = (u32)resource_size(&res);
+ *start = index;
+ if (!of_device_is_available(args.np))
+ ret = -EACCES;
+
of_node_put(args.np);
break;
}
+ }
+ if (index < numphys)
+ break;
- *addr = res.start;
- *length = (u32)resource_size(&res);
- *start = index;
- if (!of_device_is_available(args.np))
- ret = -EACCES;
+ node = node->parent;
+ }
+
+ ret = index < numphys ? ret : -EPERM;
+ return ret;
+}
- of_node_put(args.np);
+int query_reg_addr(struct platform_device *pdev, u32 *addr, u32 *length, const char* name)
+{
+ int ret = -EPERM;
+ struct resource *pres;
+ struct platform_device *device = pdev;
+
+ if (pdev == NULL || addr == NULL || length == NULL)
+ return -EINVAL;
+
+ while (device) {
+ pres = platform_get_resource_byname(device, IORESOURCE_MEM, name);
+ if (pres != NULL) {
+ *addr = pres->start;
+ *length = (u32)resource_size(pres);
+ ret = 0;
break;
}
+
+ if (device->dev.parent == NULL)
+ break;
+
+ device = to_platform_device(device->dev.parent);
}
- ret = index < numphys ? ret : -EPERM;
return ret;
}
+
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-unusual.h b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-unusual.h
index ddbf4e3..0bc6dd8 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-unusual.h
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-unusual.h
@@ -10,6 +10,8 @@
#ifndef __XHCI_MTK_UNUSUAL_H
#define __XHCI_MTK_UNUSUAL_H
+#include <dt-bindings/phy/phy.h>
+
#define HQA_PREFIX_SIZE 4*1024
#define BIT_WIDTH_1 1
@@ -131,7 +133,10 @@
u32 shift, const char *buf);
u32 bin2str(u32 value, u32 width, char *buffer);
int query_phy_addr(struct device_node *np, int *start,
- u32 *addr, u32 *length);
+ u32 *addr, u32 *length, int type);
+int query_reg_addr(struct platform_device *pdev, u32 *addr,
+ u32 *length, const char* name);
+
static inline int remaining(struct xhci_hcd_mtk *mtk)
{
u32 surplus = 0;
@@ -178,7 +183,12 @@
return 0;
};
static inline int query_phy_addr(struct device_node *np, int *start,
- u32 *addr, u32 *length)
+ u32 *addr, u32 *length, int type)
+{
+ return -EPERM;
+}
+static inline int query_reg_addr(struct platform_device *pdev, u32 *addr,
+ u32 *length, const char* name)
{
return -EPERM;
}
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-vrt-vref.c b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-vrt-vref.c
index ec0ef75..1a6d611 100644
--- a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-vrt-vref.c
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-vrt-vref.c
@@ -21,6 +21,7 @@
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
struct usb_hcd *hcd = mtk->hcd;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct device_node *node = dev->of_node;
ssize_t cnt = 0;
void __iomem *addr;
u32 val;
@@ -66,8 +67,8 @@
cnt += sprintf(buf + cnt,
"USB20 Port%i: 0x%08X\n", i, val);
- ret = query_phy_addr(dev->of_node,
- &index, &io, &length);
+ ret = query_phy_addr(node,
+ &index, &io, &length, PHY_TYPE_USB2);
if (ret && ret != -EACCES) {
if (ret == -EPERM)
cnt += sprintf(buf + cnt,
@@ -95,7 +96,7 @@
}
if (mtk->hqa_pos) {
- cnt += sprintf(buf + cnt, "%s", mtk->hqa_buf);
+ cnt += sprintf(buf + cnt, "%s", mtk->hqa_buf);
mtk->hqa_pos = 0;
}
@@ -142,8 +143,8 @@
hqa_info(mtk, " params: %i %i %s\n",
port, index, str);
- ret = query_phy_addr(node, &index, &io, &length);
- if (ret && ret != -EACCES)
+ ret = query_phy_addr(node, &index, &io, &length, PHY_TYPE_USB2);
+ if (ret && ret != -EACCES)
goto error;
io += (length != 0x100) ? 0x300 : 0;
@@ -156,7 +157,7 @@
iounmap(addr);
ret = n;
-
+
error:
kfree(str);
return ret;