lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <6c705c9dd24ca8d5d660b9309676c7ded0d948e5.1514967463.git.chunfeng.yun@mediatek.com>
Date:   Wed, 3 Jan 2018 16:53:18 +0800
From:   Chunfeng Yun <chunfeng.yun@...iatek.com>
To:     Mathias Nyman <mathias.nyman@...el.com>,
        Rob Herring <robh+dt@...nel.org>,
        Felipe Balbi <felipe.balbi@...ux.intel.com>
CC:     Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        Matthias Brugger <matthias.bgg@...il.com>,
        Catalin Marinas <catalin.marinas@....com>,
        Will Deacon <will.deacon@....com>,
        Alan Stern <stern@...land.harvard.edu>,
        Chunfeng Yun <chunfeng.yun@...iatek.com>,
        <linux-kernel@...r.kernel.org>,
        <linux-arm-kernel@...ts.infradead.org>,
        <linux-usb@...r.kernel.org>, <linux-mediatek@...ts.infradead.org>,
        <devicetree@...r.kernel.org>
Subject: [v2 PATCH 2/6] usb: mtu3: supports remote wakeup for mt2712 with two SSUSB IPs

The old way of usb wakeup only supports platform with single SSUSB IP,
such as mt8173, but mt2712 has two SSUSB IPs, so rebuild its flow and
also supports the new glue layer of usb wakeup on mt2712 which is
different from mt8173.

Signed-off-by: Chunfeng Yun <chunfeng.yun@...iatek.com>
---
 drivers/usb/mtu3/mtu3.h      |  11 +++--
 drivers/usb/mtu3/mtu3_dr.h   |   3 +-
 drivers/usb/mtu3/mtu3_host.c | 115 +++++++++++++++++++++----------------------
 drivers/usb/mtu3/mtu3_plat.c |   8 +--
 4 files changed, 70 insertions(+), 67 deletions(-)

diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h
index 3c888d9..2cd00a2 100644
--- a/drivers/usb/mtu3/mtu3.h
+++ b/drivers/usb/mtu3/mtu3.h
@@ -229,7 +229,10 @@ struct otg_switch_mtk {
  * @u3p_dis_msk: mask of disabling usb3 ports, for example, bit0==1 to
  *		disable u3port0, bit1==1 to disable u3port1,... etc
  * @dbgfs_root: only used when supports manual dual-role switch via debugfs
- * @wakeup_en: it's true when supports remote wakeup in host mode
+ * @uwk_en: it's true when supports remote wakeup in host mode
+ * @uwk: syscon including usb wakeup glue layer between SSUSB IP and SPM
+ * @uwk_reg_base: the base address of the wakeup glue layer in @uwk
+ * @uwk_vers: the version of the wakeup glue layer
  */
 struct ssusb_mtk {
 	struct device *dev;
@@ -253,8 +256,10 @@ struct ssusb_mtk {
 	int u3p_dis_msk;
 	struct dentry *dbgfs_root;
 	/* usb wakeup for host mode */
-	bool wakeup_en;
-	struct regmap *pericfg;
+	bool uwk_en;
+	struct regmap *uwk;
+	u32 uwk_reg_base;
+	u32 uwk_vers;
 };
 
 /**
diff --git a/drivers/usb/mtu3/mtu3_dr.h b/drivers/usb/mtu3/mtu3_dr.h
index c179192..ae1598d 100644
--- a/drivers/usb/mtu3/mtu3_dr.h
+++ b/drivers/usb/mtu3/mtu3_dr.h
@@ -18,8 +18,7 @@ int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb,
 				struct device_node *dn);
 int ssusb_host_enable(struct ssusb_mtk *ssusb);
 int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend);
-int ssusb_wakeup_enable(struct ssusb_mtk *ssusb);
-void ssusb_wakeup_disable(struct ssusb_mtk *ssusb);
+void ssusb_wakeup_set(struct ssusb_mtk *ssusb, bool enable);
 
 #else
 
diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c
index d237d7e..259beef 100644
--- a/drivers/usb/mtu3/mtu3_host.c
+++ b/drivers/usb/mtu3/mtu3_host.c
@@ -18,66 +18,77 @@
 #include "mtu3.h"
 #include "mtu3_dr.h"
 
-#define PERI_WK_CTRL1		0x404
-#define UWK_CTL1_IS_C(x)	(((x) & 0xf) << 26)
-#define UWK_CTL1_IS_E		BIT(25)
-#define UWK_CTL1_IDDIG_C(x)	(((x) & 0xf) << 11)  /* cycle debounce */
-#define UWK_CTL1_IDDIG_E	BIT(10) /* enable debounce */
-#define UWK_CTL1_IDDIG_P	BIT(9)  /* polarity */
-#define UWK_CTL1_IS_P		BIT(6)  /* polarity for ip sleep */
+/* mt8173 etc */
+#define PERI_WK_CTRL1	0x4
+#define WC1_IS_C(x)	(((x) & 0xf) << 26)  /* cycle debounce */
+#define WC1_IS_EN	BIT(25)
+#define WC1_IS_P	BIT(6)  /* polarity for ip sleep */
+
+/* mt2712 etc */
+#define PERI_SSUSB_SPM_CTRL	0x0
+#define SSC_IP_SLEEP_EN	BIT(4)
+#define SSC_SPM_INT_EN		BIT(1)
+
+enum ssusb_uwk_vers {
+	SSUSB_UWK_V1 = 1,
+	SSUSB_UWK_V2,
+};
 
 /*
  * ip-sleep wakeup mode:
  * all clocks can be turn off, but power domain should be kept on
  */
-static void ssusb_wakeup_ip_sleep_en(struct ssusb_mtk *ssusb)
+static void ssusb_wakeup_ip_sleep_set(struct ssusb_mtk *ssusb, bool enable)
 {
-	u32 tmp;
-	struct regmap *pericfg = ssusb->pericfg;
-
-	regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
-	tmp &= ~UWK_CTL1_IS_P;
-	tmp &= ~(UWK_CTL1_IS_C(0xf));
-	tmp |= UWK_CTL1_IS_C(0x8);
-	regmap_write(pericfg, PERI_WK_CTRL1, tmp);
-	regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_IS_E);
-
-	regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
-	dev_dbg(ssusb->dev, "%s(): WK_CTRL1[P6,E25,C26:29]=%#x\n",
-		__func__, tmp);
-}
-
-static void ssusb_wakeup_ip_sleep_dis(struct ssusb_mtk *ssusb)
-{
-	u32 tmp;
-
-	regmap_read(ssusb->pericfg, PERI_WK_CTRL1, &tmp);
-	tmp &= ~UWK_CTL1_IS_E;
-	regmap_write(ssusb->pericfg, PERI_WK_CTRL1, tmp);
+	u32 reg, msk, val;
+
+	switch (ssusb->uwk_vers) {
+	case SSUSB_UWK_V1:
+		reg = ssusb->uwk_reg_base + PERI_WK_CTRL1;
+		msk = WC1_IS_EN | WC1_IS_C(0xf) | WC1_IS_P;
+		val = enable ? (WC1_IS_EN | WC1_IS_C(0x8)) : 0;
+		break;
+	case SSUSB_UWK_V2:
+		reg = ssusb->uwk_reg_base + PERI_SSUSB_SPM_CTRL;
+		msk = SSC_IP_SLEEP_EN | SSC_SPM_INT_EN;
+		val = enable ? msk : 0;
+		break;
+	default:
+		return;
+	};
+	regmap_update_bits(ssusb->uwk, reg, msk, val);
 }
 
 int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb,
 				struct device_node *dn)
 {
-	struct device *dev = ssusb->dev;
+	struct of_phandle_args args;
+	int ret;
 
-	/*
-	 * Wakeup function is optional, so it is not an error if this property
-	 * does not exist, and in such case, no need to get relative
-	 * properties anymore.
-	 */
-	ssusb->wakeup_en = of_property_read_bool(dn, "mediatek,enable-wakeup");
-	if (!ssusb->wakeup_en)
+	/* wakeup function is optional */
+	ssusb->uwk_en = of_property_read_bool(dn, "wakeup-source");
+	if (!ssusb->uwk_en)
 		return 0;
 
-	ssusb->pericfg = syscon_regmap_lookup_by_phandle(dn,
-						"mediatek,syscon-wakeup");
-	if (IS_ERR(ssusb->pericfg)) {
-		dev_err(dev, "fail to get pericfg regs\n");
-		return PTR_ERR(ssusb->pericfg);
-	}
+	ret = of_parse_phandle_with_fixed_args(dn,
+				"mediatek,syscon-wakeup", 2, 0, &args);
+	if (ret)
+		return ret;
 
-	return 0;
+	ssusb->uwk_reg_base = args.args[0];
+	ssusb->uwk_vers = args.args[1];
+	ssusb->uwk = syscon_node_to_regmap(args.np);
+	of_node_put(args.np);
+	dev_info(ssusb->dev, "uwk - reg:0x%x, version:%d\n",
+			ssusb->uwk_reg_base, ssusb->uwk_vers);
+
+	return PTR_ERR_OR_ZERO(ssusb->uwk);
+}
+
+void ssusb_wakeup_set(struct ssusb_mtk *ssusb, bool enable)
+{
+	if (ssusb->uwk_en)
+		ssusb_wakeup_ip_sleep_set(ssusb, enable);
 }
 
 static void host_ports_num_get(struct ssusb_mtk *ssusb)
@@ -235,17 +246,3 @@ void ssusb_host_exit(struct ssusb_mtk *ssusb)
 	of_platform_depopulate(ssusb->dev);
 	ssusb_host_cleanup(ssusb);
 }
-
-int ssusb_wakeup_enable(struct ssusb_mtk *ssusb)
-{
-	if (ssusb->wakeup_en)
-		ssusb_wakeup_ip_sleep_en(ssusb);
-
-	return 0;
-}
-
-void ssusb_wakeup_disable(struct ssusb_mtk *ssusb)
-{
-	if (ssusb->wakeup_en)
-		ssusb_wakeup_ip_sleep_dis(ssusb);
-}
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index 5b2110b..628d5ce 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -282,8 +282,10 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 
 	/* if host role is supported */
 	ret = ssusb_wakeup_of_property_parse(ssusb, node);
-	if (ret)
+	if (ret) {
+		dev_err(dev, "failed to parse uwk property\n");
 		return ret;
+	}
 
 	/* optional property, ignore the error if it does not exist */
 	of_property_read_u32(node, "mediatek,u3p-dis-msk",
@@ -457,7 +459,7 @@ static int __maybe_unused mtu3_suspend(struct device *dev)
 	ssusb_host_disable(ssusb, true);
 	ssusb_phy_power_off(ssusb);
 	ssusb_clks_disable(ssusb);
-	ssusb_wakeup_enable(ssusb);
+	ssusb_wakeup_set(ssusb, true);
 
 	return 0;
 }
@@ -473,7 +475,7 @@ static int __maybe_unused mtu3_resume(struct device *dev)
 	if (!ssusb->is_host)
 		return 0;
 
-	ssusb_wakeup_disable(ssusb);
+	ssusb_wakeup_set(ssusb, false);
 	ret = ssusb_clks_enable(ssusb);
 	if (ret)
 		goto clks_err;
-- 
1.9.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ