Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Randy Li and committed by
Kishon Vijay Abraham I
0f74ab59 cac18ecb

+23
+3
Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
··· 27 27 - clocks : phandle + clock specifier for the phy clocks 28 28 - clock-names: string, clock name, must be "phyclk" 29 29 - #clock-cells: for users of the phy-pll, should be 0 30 + - reset-names: Only allow the following entries: 31 + - phy-reset 32 + - resets: Must contain an entry for each entry in reset-names. 30 33 31 34 Example: 32 35
+20
drivers/phy/phy-rockchip-usb.c
··· 29 29 #include <linux/reset.h> 30 30 #include <linux/regmap.h> 31 31 #include <linux/mfd/syscon.h> 32 + #include <linux/delay.h> 32 33 33 34 static int enable_usb_uart; 34 35 ··· 65 64 struct clk_hw clk480m_hw; 66 65 struct phy *phy; 67 66 bool uart_enabled; 67 + struct reset_control *reset; 68 68 }; 69 69 70 70 static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, ··· 146 144 return clk_prepare_enable(phy->clk480m); 147 145 } 148 146 147 + static int rockchip_usb_phy_reset(struct phy *_phy) 148 + { 149 + struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); 150 + 151 + if (phy->reset) { 152 + reset_control_assert(phy->reset); 153 + udelay(10); 154 + reset_control_deassert(phy->reset); 155 + } 156 + 157 + return 0; 158 + } 159 + 149 160 static const struct phy_ops ops = { 150 161 .power_on = rockchip_usb_phy_power_on, 151 162 .power_off = rockchip_usb_phy_power_off, 163 + .reset = rockchip_usb_phy_reset, 152 164 .owner = THIS_MODULE, 153 165 }; 154 166 ··· 200 184 child->name); 201 185 return -EINVAL; 202 186 } 187 + 188 + rk_phy->reset = of_reset_control_get(child, "phy-reset"); 189 + if (IS_ERR(rk_phy->reset)) 190 + rk_phy->reset = NULL; 203 191 204 192 rk_phy->reg_offset = reg_offset; 205 193