phy: rockchip-usb: use rockchip_usb_phy_reset to reset phy during wakeup

It is a hardware bug in RK3288, the only way to solve it is to
reset the phy.

Signed-off-by: Randy Li <ayaka@soulik.info>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
This commit is contained in:
Randy Li 2016-09-10 02:59:38 +08:00 committed by Kishon Vijay Abraham I
parent cac18ecb6f
commit 0f74ab59ce
2 changed files with 23 additions and 0 deletions

View File

@ -27,6 +27,9 @@ Optional Properties:
- clocks : phandle + clock specifier for the phy clocks - clocks : phandle + clock specifier for the phy clocks
- clock-names: string, clock name, must be "phyclk" - clock-names: string, clock name, must be "phyclk"
- #clock-cells: for users of the phy-pll, should be 0 - #clock-cells: for users of the phy-pll, should be 0
- reset-names: Only allow the following entries:
- phy-reset
- resets: Must contain an entry for each entry in reset-names.
Example: Example:

View File

@ -29,6 +29,7 @@
#include <linux/reset.h> #include <linux/reset.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/delay.h>
static int enable_usb_uart; static int enable_usb_uart;
@ -64,6 +65,7 @@ struct rockchip_usb_phy {
struct clk_hw clk480m_hw; struct clk_hw clk480m_hw;
struct phy *phy; struct phy *phy;
bool uart_enabled; bool uart_enabled;
struct reset_control *reset;
}; };
static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
@ -144,9 +146,23 @@ static int rockchip_usb_phy_power_on(struct phy *_phy)
return clk_prepare_enable(phy->clk480m); return clk_prepare_enable(phy->clk480m);
} }
static int rockchip_usb_phy_reset(struct phy *_phy)
{
struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
if (phy->reset) {
reset_control_assert(phy->reset);
udelay(10);
reset_control_deassert(phy->reset);
}
return 0;
}
static const struct phy_ops ops = { static const struct phy_ops ops = {
.power_on = rockchip_usb_phy_power_on, .power_on = rockchip_usb_phy_power_on,
.power_off = rockchip_usb_phy_power_off, .power_off = rockchip_usb_phy_power_off,
.reset = rockchip_usb_phy_reset,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
@ -185,6 +201,10 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
return -EINVAL; return -EINVAL;
} }
rk_phy->reset = of_reset_control_get(child, "phy-reset");
if (IS_ERR(rk_phy->reset))
rk_phy->reset = NULL;
rk_phy->reg_offset = reg_offset; rk_phy->reg_offset = reg_offset;
rk_phy->clk = of_clk_get_by_name(child, "phyclk"); rk_phy->clk = of_clk_get_by_name(child, "phyclk");