[][kernel][mt7988][usb]Add USB 2.0 Phy preemphasis parameter support]
[Description]
Add USB 2.0 phy preemphasis parameter support
[Release-log]
N/A
Change-Id: I0543ec4c840706bafaf0727f6409f40cff5b8056
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6378563
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 70db398..a790c62 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(RG_USB20_PHY_REV);
DEVICE_ATTR_DECLARED(reg);
#define HQA_INFORMACTION_COLLECTS() do {\
@@ -22,5 +23,6 @@
ECHO_HQA(USB20_PHY_USBPHYACR5, RG_USB20_HSTX_SRCTRL, 3); \
ECHO_HQA(USB20_PHY_USBPHYACR6, RG_USB20_DISCTH, 4); \
ECHO_HQA(USB20_PHY_U2PHYBC12C, RG_CHGDT_EN, 1); \
+ ECHO_HQA(USB20_PHY_USBPHYACR6, RG_USB20_PHY_REV, 2); \
} while (0)
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 e898a26..80b786a 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,5 +13,6 @@
UNUSUAL_DEVICE_ATTR(RG_USB20_HSTX_SRCTRL),
UNUSUAL_DEVICE_ATTR(RG_USB20_DISCTH),
UNUSUAL_DEVICE_ATTR(RG_CHGDT_EN),
+UNUSUAL_DEVICE_ATTR(RG_USB20_PHY_REV),
UNUSUAL_DEVICE_ATTR(reg),
diff --git a/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-preemphasic.c b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-preemphasic.c
new file mode 100644
index 0000000..5041dbc
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/usb/host/xhci-mtk-preemphasic.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * xHCI host controller toolkit driver for pre-emphasic
+ *
+ * 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_PHY_REV_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);
+ struct device_node *node = dev->of_node;
+ 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_PHY_REV usage:\n");
+ cnt += sprintf(buf + cnt,
+ " echo u2p index 2b00 > RG_USB20_PHY_REV\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 2b10 > RG_USB20_PHY_REV\n");
+ cnt += sprintf(buf + cnt,
+ " port2 binding phy 0, enable 2b'10 as RG_USB20_PHY_REV\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(node,
+ &index, &io, &length, PHY_TYPE_USB2);
+ 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_PHY_REV_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_PHY_REV(%lu): %s\n", n, buf);
+
+ words = sscanf(buf, "%i %i 2b%2[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, PHY_TYPE_USB2);
+ if (ret && ret != -EACCES)
+ goto error;
+
+ io += (length != 0x100) ? 0x300 : 0;
+ io += USB20_PHY_USBPHYACR6;
+
+ addr = ioremap_nocache(io, 4);
+ val = binary_write_width2(addr, SHFT_RG_USB20_PHY_REV, 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_PHY_REV);
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 01029fb..b02720d 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
@@ -35,6 +35,27 @@
return val;
}
+u32 binary_write_width2(u32 __iomem *addr, u32 shift, const char *buf)
+{
+ u32 val = 0;
+
+ if (!strncmp(buf, STRNG_0_WIDTH_2, BIT_WIDTH_2))
+ val = 0;
+ else if (!strncmp(buf, STRNG_1_WIDTH_2, BIT_WIDTH_2))
+ val = 1;
+ else if (!strncmp(buf, STRNG_2_WIDTH_2, BIT_WIDTH_2))
+ val = 2;
+ else if (!strncmp(buf, STRNG_3_WIDTH_2, BIT_WIDTH_2))
+ val = 3;
+ else
+ val = 0xFFFFFFFF;
+
+ if (val <= 3)
+ val = usb20hqa_write(addr, shift, MSK_WIDTH_2, val);
+
+ return val;
+}
+
u32 binary_write_width3(u32 __iomem *addr, u32 shift, const char *buf)
{
u32 val = 0;
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 0bc6dd8..3850ccf 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
@@ -92,6 +92,11 @@
#define SHFT_RG_CHGDT_EN 0
#define BV_RG_CHGDT_EN BIT(0)
+#define NAME_RG_USB20_PHY_REV "RG_USB20_PHY_REV"
+/* #define USB20_PHY_USBPHYACR6 0x18 */
+#define SHFT_RG_USB20_PHY_REV 30
+#define BV_RG_USB20_PHY_REV GENMASK(31, 30)
+
#define ECHO_HQA(reg, _bd, _bw) do {\
val = usb20hqa_read(addr + (reg), \
SHFT_##_bd, \
@@ -127,6 +132,8 @@
u32 binary_write_width1(u32 __iomem *addr,
u32 shift, const char *buf);
+u32 binary_write_width2(u32 __iomem *addr,
+ u32 shift, const char *buf);
u32 binary_write_width3(u32 __iomem *addr,
u32 shift, const char *buf);
u32 binary_write_width4(u32 __iomem *addr,
@@ -168,6 +175,11 @@
{
return 0;
};
+static inline u32 binary_write_width2(u32 __iomem *addr,
+ u32 shift, const char *buf)
+{
+ return 0;
+};
static inline u32 binary_write_width3(u32 __iomem *addr,
u32 shift, const char *buf)
{