153 lines
4.8 KiB
Diff
153 lines
4.8 KiB
Diff
|
From 5e4e66f0c2d623ef547c0547af7475124fdb367b Mon Sep 17 00:00:00 2001
|
||
|
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||
|
Date: Mon, 3 Apr 2023 20:24:06 +0200
|
||
|
Subject: [PATCH 417/469] phy: phy-rockchip-inno-usb2: add rk3588 phy tuning
|
||
|
support
|
||
|
|
||
|
On RK3588 some registers need to be tweaked to support waking up from
|
||
|
suspend when a USB device is plugged into a port from a suspended PHY.
|
||
|
Without this change USB devices only work when they are plugged at
|
||
|
boot time.
|
||
|
|
||
|
Apart from that it optimizes settings to avoid devices toggling
|
||
|
between fullspeed and highspeed mode.
|
||
|
|
||
|
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||
|
---
|
||
|
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 63 +++++++++++++++++++
|
||
|
1 file changed, 63 insertions(+)
|
||
|
|
||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
|
||
|
index 101b46939f0b..aa8c55609c0d 100644
|
||
|
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
|
||
|
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
|
||
|
@@ -33,6 +33,8 @@
|
||
|
#define SCHEDULE_DELAY (60 * HZ)
|
||
|
#define OTG_SCHEDULE_DELAY (2 * HZ)
|
||
|
|
||
|
+struct rockchip_usb2phy;
|
||
|
+
|
||
|
enum rockchip_usb2phy_port_id {
|
||
|
USB2PHY_PORT_OTG,
|
||
|
USB2PHY_PORT_HOST,
|
||
|
@@ -163,6 +165,7 @@ struct rockchip_usb2phy_port_cfg {
|
||
|
* struct rockchip_usb2phy_cfg - usb-phy configuration.
|
||
|
* @reg: the address offset of grf for usb-phy config.
|
||
|
* @num_ports: specify how many ports that the phy has.
|
||
|
+ * @phy_tuning: phy default parameters tuning.
|
||
|
* @clkout_ctl: keep on/turn off output clk of phy.
|
||
|
* @port_cfgs: usb-phy port configurations.
|
||
|
* @chg_det: charger detection registers.
|
||
|
@@ -170,6 +173,7 @@ struct rockchip_usb2phy_port_cfg {
|
||
|
struct rockchip_usb2phy_cfg {
|
||
|
unsigned int reg;
|
||
|
unsigned int num_ports;
|
||
|
+ int (*phy_tuning)(struct rockchip_usb2phy *rphy);
|
||
|
struct usb2phy_reg clkout_ctl;
|
||
|
const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS];
|
||
|
const struct rockchip_chg_det_reg chg_det;
|
||
|
@@ -1400,6 +1404,12 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
|
||
|
goto disable_clks;
|
||
|
}
|
||
|
|
||
|
+ if (rphy->phy_cfg->phy_tuning) {
|
||
|
+ ret = rphy->phy_cfg->phy_tuning(rphy);
|
||
|
+ if (ret)
|
||
|
+ goto disable_clks;
|
||
|
+ }
|
||
|
+
|
||
|
index = 0;
|
||
|
for_each_available_child_of_node(np, child_np) {
|
||
|
struct rockchip_usb2phy_port *rport = &rphy->ports[index];
|
||
|
@@ -1468,6 +1478,55 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
+static int rk3588_usb2phy_tuning(struct rockchip_usb2phy *rphy)
|
||
|
+{
|
||
|
+ int ret;
|
||
|
+ bool usb3otg = false;
|
||
|
+ /*
|
||
|
+ * utmi_termselect = 1'b1 (en FS terminations)
|
||
|
+ * utmi_xcvrselect = 2'b01 (FS transceiver)
|
||
|
+ */
|
||
|
+ int suspend_cfg = 0x14;
|
||
|
+
|
||
|
+ if (rphy->phy_cfg->reg == 0x0000 || rphy->phy_cfg->reg == 0x4000) {
|
||
|
+ /* USB2 config for USB3_0 and USB3_1 */
|
||
|
+ suspend_cfg |= 0x01; /* utmi_opmode = 2'b01 (no-driving) */
|
||
|
+ usb3otg = true;
|
||
|
+ } else if (rphy->phy_cfg->reg == 0x8000 || rphy->phy_cfg->reg == 0xc000) {
|
||
|
+ /* USB2 config for USB2_0 and USB2_1 */
|
||
|
+ suspend_cfg |= 0x00; /* utmi_opmode = 2'b00 (normal) */
|
||
|
+ } else {
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Deassert SIDDQ to power on analog block */
|
||
|
+ ret = regmap_write(rphy->grf, 0x0008, GENMASK(29, 29) | 0x0000);
|
||
|
+ if (ret)
|
||
|
+ return ret;
|
||
|
+
|
||
|
+ /* Do reset after exit IDDQ mode */
|
||
|
+ ret = rockchip_usb2phy_reset(rphy);
|
||
|
+ if (ret)
|
||
|
+ return ret;
|
||
|
+
|
||
|
+ /* suspend configuration */
|
||
|
+ ret |= regmap_write(rphy->grf, 0x000c, GENMASK(20, 16) | suspend_cfg);
|
||
|
+
|
||
|
+ /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */
|
||
|
+ ret |= regmap_write(rphy->grf, 0x0004, GENMASK(27, 24) | 0x0900);
|
||
|
+
|
||
|
+ /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */
|
||
|
+ ret |= regmap_write(rphy->grf, 0x0008, GENMASK(20, 19) | 0x0010);
|
||
|
+
|
||
|
+ if (!usb3otg)
|
||
|
+ return ret;
|
||
|
+
|
||
|
+ /* Pullup iddig pin for USB3_0 OTG mode */
|
||
|
+ ret |= regmap_write(rphy->grf, 0x0010, GENMASK(17, 16) | 0x0003);
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = {
|
||
|
{
|
||
|
.reg = 0x760,
|
||
|
@@ -1785,6 +1844,7 @@ static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
|
||
|
{
|
||
|
.reg = 0x0000,
|
||
|
.num_ports = 1,
|
||
|
+ .phy_tuning = rk3588_usb2phy_tuning,
|
||
|
.clkout_ctl = { 0x0000, 0, 0, 1, 0 },
|
||
|
.port_cfgs = {
|
||
|
[USB2PHY_PORT_OTG] = {
|
||
|
@@ -1821,6 +1881,7 @@ static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
|
||
|
{
|
||
|
.reg = 0x4000,
|
||
|
.num_ports = 1,
|
||
|
+ .phy_tuning = rk3588_usb2phy_tuning,
|
||
|
.clkout_ctl = { 0x0000, 0, 0, 1, 0 },
|
||
|
.port_cfgs = {
|
||
|
[USB2PHY_PORT_OTG] = {
|
||
|
@@ -1857,6 +1918,7 @@ static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
|
||
|
{
|
||
|
.reg = 0x8000,
|
||
|
.num_ports = 1,
|
||
|
+ .phy_tuning = rk3588_usb2phy_tuning,
|
||
|
.clkout_ctl = { 0x0000, 0, 0, 1, 0 },
|
||
|
.port_cfgs = {
|
||
|
[USB2PHY_PORT_HOST] = {
|
||
|
@@ -1877,6 +1939,7 @@ static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
|
||
|
{
|
||
|
.reg = 0xc000,
|
||
|
.num_ports = 1,
|
||
|
+ .phy_tuning = rk3588_usb2phy_tuning,
|
||
|
.clkout_ctl = { 0x0000, 0, 0, 1, 0 },
|
||
|
.port_cfgs = {
|
||
|
[USB2PHY_PORT_HOST] = {
|
||
|
--
|
||
|
2.34.1
|
||
|
|