[][MT79xx add USBIF compliance toolkit]
[Description]
Add USBIF compliance toolkit for MT79xx
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
[Release-log]
N/A
Change-Id: I2f7e4bdf27c2197a198ce10af3a09c362adfc04a
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5351515
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
new file mode 100644
index 0000000..3b40ef9
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-term-vref.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * xHCI host controller toolkit driver for term vref
+ *
+ * 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"
+
+static
+ssize_t RG_USB20_TERM_VREF_SEL_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
+ struct usb_hcd *hcd = mtk->hcd;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ ssize_t cnt = 0;
+ void __iomem *addr;
+ u32 val;
+ u32 i;
+ int ports;
+ char str[32];
+ int index = 0;
+ u32 io, length;
+ int ret;
+
+ ports = mtk->num_u3_ports + mtk->num_u2_ports;
+ cnt += sprintf(buf + cnt, " RG_USB20_TERM_VREF_SEL usage:\n");
+ cnt += sprintf(buf + cnt,
+ " echo u2p index 3b011 > RG_USB20_TERM_VREF_SEL\n");
+ if (mtk->num_u3_ports + 1 != ports)
+ cnt += sprintf(buf + cnt, " parameter: u2p: %i ~ %i\n",
+ mtk->num_u3_ports + 1, ports);
+ else
+ cnt += sprintf(buf + cnt, " parameter: u2p: %i\n",
+ mtk->num_u3_ports + 1);
+
+ if (mtk->num_u2_ports > 1)
+ cnt += sprintf(buf + cnt, " parameter: index: 0 ~ %i\n",
+ mtk->num_u2_ports);
+ else
+ cnt += sprintf(buf + cnt, " parameter: index: 0\n");
+
+ cnt += sprintf(buf + cnt,
+ " e.g.: echo 2 0 3b010 > RG_USB20_TERM_VREF_SEL\n");
+ cnt += sprintf(buf + cnt,
+ " port2 binding phy 0, tune 3b'010 as TERM_VREF value\n");
+
+ cnt += sprintf(buf + cnt,
+ "\n=========current HQA setting check=========\n");
+ 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) {
+ cnt += sprintf(buf + cnt,
+ "USB30 Port%i: 0x%08X\n", i, val);
+ } else {
+ cnt += sprintf(buf + cnt,
+ "USB20 Port%i: 0x%08X\n", i, val);
+
+ ret = query_phy_addr(dev->of_node,
+ &index, &io, &length);
+ if (ret && ret != -EACCES) {
+ if (ret == -EPERM)
+ cnt += sprintf(buf + cnt,
+ "USB20 Port%i (Phy%i: absent)\n",
+ i, index);
+ else
+ cnt += sprintf(buf + cnt,
+ "USB20 Port%i (Phy%i) failure %i\n",
+ i, index, ret);
+ continue;
+ }
+
+ cnt += sprintf(buf + cnt,
+ "USB20 Port%i (Phy%i:%sable): 0x%08X 0x%08X\n",
+ i, index, ret ? " dis" : " en", io, length);
+
+ addr = ioremap_nocache(io, length);
+ addr += (length != 0x100) ? 0x300 : 0;
+
+ HQA_INFORMACTION_COLLECTS();
+
+ iounmap(addr);
+ index ++;
+ }
+ }
+
+ if (mtk->hqa_pos) {
+ cnt += sprintf(buf + cnt, "%s", mtk->hqa_buf);
+ mtk->hqa_pos = 0;
+ }
+
+ return cnt;
+}
+
+static
+ssize_t RG_USB20_TERM_VREF_SEL_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ u32 val;
+ u32 io;
+ u32 length;
+ int ports;
+ int words;
+ int port;
+ int index;
+ int ret;
+ char *str = NULL;
+ void __iomem *addr;
+ struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
+ struct device_node *node = dev->of_node;
+
+ ports = mtk->num_u3_ports + mtk->num_u2_ports;
+ mtk->hqa_pos = 0;
+
+ memset(mtk->hqa_buf, 0, mtk->hqa_size);
+
+ str = kzalloc(n, GFP_ATOMIC);
+
+ hqa_info(mtk, "RG_USB20_TERM_VREF_SEL(%lu): %s\n", n, buf);
+
+ words = sscanf(buf, "%i %i 3b%3[0,1]", &port, &index, str);
+ if ((words != 3) ||
+ (port < mtk->num_u3_ports || port > ports)) {
+ hqa_info(mtk, "Check params(%i):\" %i %i %s\", Please!\n",
+ words, port, index, str);
+
+ ret = -EINVAL;
+ goto error;
+ }
+
+ hqa_info(mtk, " params: %i %i %s\n",
+ port, index, str);
+
+ ret = query_phy_addr(node, &index, &io, &length);
+ if (ret && ret != -EACCES)
+ goto error;
+
+ io += (length != 0x100) ? 0x300 : 0;
+ io += USB20_PHY_USBPHYACR1;
+
+ addr = ioremap_nocache(io, 4);
+ val = binary_write_width3(addr, SHFT_RG_USB20_TERM_VREF_SEL, str);
+ hqa_info(mtk, "Port%i(Phy%i)[0x%08X]: 0x%08X but 0x%08X\n",
+ port, index, io, val, readl(addr));
+
+ iounmap(addr);
+ ret = n;
+
+error:
+ kfree(str);
+ return ret;
+}
+DEVICE_ATTR_RW(RG_USB20_TERM_VREF_SEL);
+