From 721611f31c74bbc255f23151e5d94a944821cb93 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Wed, 22 Mar 2017 13:54:50 +0900 Subject: [PATCH] phy: exynos5-usbdrd: Add USB 3.0 super-speed mode tune It implements PHY tune operation to activate USB 3.0 super-speed mode. Change-Id: I56971effacc2d3383b1fc55c2e73f76f54d603a0 Signed-off-by: Dongwoo Lee --- drivers/phy/phy-exynos5-usbdrd.c | 91 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c index d72ef15..8aa2e06 100644 --- a/drivers/phy/phy-exynos5-usbdrd.c +++ b/drivers/phy/phy-exynos5-usbdrd.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -89,8 +90,18 @@ #define PHYCLKRST_COMMONONN BIT(0) #define EXYNOS5_DRD_PHYREG0 0x14 + +#define PHYREG0_CR_WRITE BIT(19) +#define PHYREG0_CR_READ BIT(18) +#define PHYREG0_CR_DATA_IN(_x) ((_x) << 2) +#define PHYREG0_CR_CR_CAP_DATA BIT(1) +#define PHYREG0_CR_CR_CAP_ADDR BIT(0) + #define EXYNOS5_DRD_PHYREG1 0x18 +#define PHYREG1_CR_DATA_OUT(_x) ((_x) << 1) +#define PHYREG1_CR_ACK BIT(0) + #define EXYNOS5_DRD_PHYPARAM0 0x1c #define PHYPARAM0_REF_USE_PAD BIT(31) @@ -121,6 +132,19 @@ #define KHZ 1000 #define MHZ (KHZ * KHZ) +/* USB 3.0 DRD SS Function Control registers used to access by CR PORT */ +#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN 0x15 + +#define LOSLEVEL_OVRD_IN_LOS_BIAS_5420 (0x5 << 13) +#define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT (0x0 << 13) +#define LOSLEVEL_OVRD_IN_EN (0x1 << 10) +#define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT (0x9 << 0) + +#define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN 0x12 + +#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420 (0x5 << 13) +#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT (0x4 << 13) + enum exynos5_usbdrd_phy_id { EXYNOS5_DRDPHY_UTMI, EXYNOS5_DRDPHY_PIPE3, @@ -190,6 +214,55 @@ struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst) phys[(inst)->index]); } +static int +exynos5_usbdrd_phy_crport_handshake(struct exynos5_usbdrd_phy *phy_drd, + u32 data, u32 command) +{ + int ret; + u32 reg; + + reg = PHYREG0_CR_DATA_IN(data) | command; + writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); + + ret = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1, reg, + (reg & PHYREG1_CR_ACK), 1, 10); + if (ret < 0) + dev_err(phy_drd->dev, "crport handshake timeout\n"); + + return ret; +} + +static void +exynos5_usbdrd_phy_crport_write(struct exynos5_usbdrd_phy *phy_drd, + u32 addr, u32 data) +{ + int ret; + + /* Program Address Register */ + ret = exynos5_usbdrd_phy_crport_handshake(phy_drd, addr, + PHYREG0_CR_CR_CAP_ADDR); + if (ret < 0) + goto err; + + /* Program Data Register */ + ret = exynos5_usbdrd_phy_crport_handshake(phy_drd, data, + PHYREG0_CR_CR_CAP_DATA); + if (ret < 0) + goto err; + + /* Write Data */ + ret = exynos5_usbdrd_phy_crport_handshake(phy_drd, data, + PHYREG0_CR_WRITE); + if (ret < 0) + goto err; + + return; + +err: + dev_err(phy_drd->dev, + "failed to write crport data %x to 0x%x\n", data, addr); +} + /* * exynos5_rate_to_clk() converts the supplied clock rate to the value that * can be written to the phy register. @@ -351,6 +424,23 @@ static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); } +static void exynos5_usbdrd_phy_tune(struct phy *phy) +{ + struct phy_usb_instance *inst = phy_get_drvdata(phy); + struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); + u32 data; + + data = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 | + LOSLEVEL_OVRD_IN_EN | + LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT; + exynos5_usbdrd_phy_crport_write(phy_drd, + EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN, data); + + data = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420; + exynos5_usbdrd_phy_crport_write(phy_drd, + EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN, data); +} + static int exynos5_usbdrd_phy_init(struct phy *phy) { int ret; @@ -542,6 +632,7 @@ static struct phy_ops exynos5_usbdrd_phy_ops = { .exit = exynos5_usbdrd_phy_exit, .power_on = exynos5_usbdrd_phy_power_on, .power_off = exynos5_usbdrd_phy_power_off, + .tune = exynos5_usbdrd_phy_tune, .owner = THIS_MODULE, }; -- 2.7.4