From 050da2107a7eb2a571a8a3d0cee21cc6a44b72b8 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 7 May 2018 12:07:32 +0200 Subject: mediatek: backport upstream mediatek patches Signed-off-by: John Crispin --- ...pports-remote-wakeup-for-mt2712-with-two-.patch | 245 +++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 target/linux/mediatek/patches-4.14/0188-usb-mtu3-supports-remote-wakeup-for-mt2712-with-two-.patch (limited to 'target/linux/mediatek/patches-4.14/0188-usb-mtu3-supports-remote-wakeup-for-mt2712-with-two-.patch') diff --git a/target/linux/mediatek/patches-4.14/0188-usb-mtu3-supports-remote-wakeup-for-mt2712-with-two-.patch b/target/linux/mediatek/patches-4.14/0188-usb-mtu3-supports-remote-wakeup-for-mt2712-with-two-.patch new file mode 100644 index 0000000000..105d6f156b --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0188-usb-mtu3-supports-remote-wakeup-for-mt2712-with-two-.patch @@ -0,0 +1,245 @@ +From 354655aaf0f71ce2b567cbc02afb0664c99e434e Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun +Date: Wed, 3 Jan 2018 16:53:18 +0800 +Subject: [PATCH 188/224] 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 d80e4e813248..ed3aec46eda1 100644 +--- a/drivers/usb/mtu3/mtu3.h ++++ b/drivers/usb/mtu3/mtu3.h +@@ -238,7 +238,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; +@@ -262,8 +265,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 0f0cbac00192..1fa62ce136b6 100644 +--- a/drivers/usb/mtu3/mtu3_dr.h ++++ b/drivers/usb/mtu3/mtu3_dr.h +@@ -27,8 +27,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 ec76b86dd887..1a1b6cf432a1 100644 +--- a/drivers/usb/mtu3/mtu3_host.c ++++ b/drivers/usb/mtu3/mtu3_host.c +@@ -27,66 +27,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) +@@ -244,17 +255,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 a2523ead46cf..4cafd4ca8457 100644 +--- a/drivers/usb/mtu3/mtu3_plat.c ++++ b/drivers/usb/mtu3/mtu3_plat.c +@@ -291,8 +291,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", +@@ -466,7 +468,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; + } +@@ -482,7 +484,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; +-- +2.11.0 + -- cgit v1.2.3