diff options
Diffstat (limited to 'drivers/usb/mtu3/mtu3_host.c')
-rw-r--r-- | drivers/usb/mtu3/mtu3_host.c | 115 |
1 files changed, 56 insertions, 59 deletions
diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c index d237d7e65c44..259beefe3b3b 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); -} |