From: Frank Wang <frank.wang@rock-chips.com>
Date: Fri, 22 Jul 2016 01:37:32 +0000 (+0800)
Subject: FROMLIST: phy: rockchip-inno-usb2: support for rk3399 host-port
X-Git-Tag: firefly_0821_release~2100
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=884807d6f73f93e61a44043c9d4c951cdb47b440;p=firefly-linux-kernel-4.4.55.git

FROMLIST: phy: rockchip-inno-usb2: support for rk3399 host-port

This patch just sync the new adds v8 from patchwork list,
the others we have already merged before.

Change-Id: Iad0eb9002d7c8228fdbe6082bf3166a2dec418ba
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
(am from https://patchwork.kernel.org/patch/9236143/)
---

diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/phy-rockchip-inno-usb2.c
index a1977b6c05ed..4a798bd6624a 100644
--- a/drivers/phy/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/phy-rockchip-inno-usb2.c
@@ -52,8 +52,8 @@ enum rockchip_usb2phy_port_id {
 enum rockchip_usb2phy_host_state {
 	PHY_STATE_HS_ONLINE	= 0,
 	PHY_STATE_DISCONNECT	= 1,
-	PHY_STATE_HS_CONNECT	= 2,
-	PHY_STATE_FS_CONNECT	= 4,
+	PHY_STATE_CONNECT	= 2,
+	PHY_STATE_FS_LS_ONLINE	= 4,
 };
 
 /**
@@ -309,9 +309,6 @@ static void rockchip_usb2phy_clk480m_unregister(void *data)
 
 	of_clk_del_provider(rphy->dev->of_node);
 	clk_unregister(rphy->clk480m);
-
-	if (rphy->clk)
-		clk_put(rphy->clk);
 }
 
 static int
@@ -329,16 +326,13 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
 	/* optional override of the clockname */
 	of_property_read_string(node, "clock-output-names", &init.name);
 
-	rphy->clk = of_clk_get_by_name(node, "phyclk");
-	if (IS_ERR(rphy->clk)) {
-		rphy->clk = NULL;
-		init.parent_names = NULL;
-		init.num_parents = 0;
-	} else {
+	if (rphy->clk) {
 		clk_name = __clk_get_name(rphy->clk);
 		init.parent_names = &clk_name;
 		init.num_parents = 1;
-		clk_prepare_enable(rphy->clk);
+	} else {
+		init.parent_names = NULL;
+		init.num_parents = 0;
 	}
 
 	rphy->clk480m_hw.init = &init;
@@ -347,7 +341,7 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
 	rphy->clk480m = clk_register(rphy->dev, &rphy->clk480m_hw);
 	if (IS_ERR(rphy->clk480m)) {
 		ret = PTR_ERR(rphy->clk480m);
-		goto err_register;
+		goto err_ret;
 	}
 
 	ret = of_clk_add_provider(node, of_clk_src_simple_get, rphy->clk480m);
@@ -365,9 +359,7 @@ err_unreg_action:
 	of_clk_del_provider(node);
 err_clk_provider:
 	clk_unregister(rphy->clk480m);
-err_register:
-	if (rphy->clk)
-		clk_put(rphy->clk);
+err_ret:
 	return ret;
 }
 
@@ -472,7 +464,6 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
 		return ret;
 
 	rport->suspended = false;
-
 	return 0;
 }
 
@@ -773,7 +764,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
  * to save power.
  *
  * we rely on utmi_linestate and utmi_hostdisconnect to identify whether
- * FS/HS is disconnect or not. Besides, we do not need care it is FS
+ * devices is disconnect or not. Besides, we do not need care it is FS/LS
  * disconnected or HS disconnected, actually, we just only need get the
  * device is disconnected at last through rearm the delayed work,
  * to suspend the phy port in _PHY_STATE_DISCONNECT_ case.
@@ -816,27 +807,35 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
 	case PHY_STATE_HS_ONLINE:
 		dev_dbg(&rport->phy->dev, "HS online\n");
 		break;
-	case PHY_STATE_FS_CONNECT:
+	case PHY_STATE_FS_LS_ONLINE:
 		/*
-		 * For FS device, the online state share with connect state
+		 * For FS/LS device, the online state share with connect state
 		 * from utmi_ls and utmi_hstdet register, so we distinguish
 		 * them via suspended flag.
+		 *
+		 * Plus, there are two cases, one is D- Line pull-up, and D+
+		 * line pull-down, the state is 4; another is D+ line pull-up,
+		 * and D- line pull-down, the state is 2.
 		 */
 		if (!rport->suspended) {
-			dev_dbg(&rport->phy->dev, "FS online\n");
+			/* D- line pull-up, D+ line pull-down */
+			dev_dbg(&rport->phy->dev, "FS/LS online\n");
 			break;
 		}
 		/* fall through */
-	case PHY_STATE_HS_CONNECT:
+	case PHY_STATE_CONNECT:
 		if (rport->suspended) {
-			dev_dbg(&rport->phy->dev, "HS/FS connected\n");
+			dev_dbg(&rport->phy->dev, "Connected\n");
 			rockchip_usb2phy_power_on(rport->phy);
 			rport->suspended = false;
+		} else {
+			/* D+ line pull-up, D- line pull-down */
+			dev_dbg(&rport->phy->dev, "FS/LS online\n");
 		}
 		break;
 	case PHY_STATE_DISCONNECT:
 		if (!rport->suspended) {
-			dev_dbg(&rport->phy->dev, "HS/FS disconnected\n");
+			dev_dbg(&rport->phy->dev, "Disconnected\n");
 			rockchip_usb2phy_power_off(rport->phy);
 			rport->suspended = true;
 		}
@@ -1067,16 +1066,24 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
+	rphy->clk = of_clk_get_by_name(np, "phyclk");
+	if (!IS_ERR(rphy->clk)) {
+		clk_prepare_enable(rphy->clk);
+	} else {
+		dev_info(&pdev->dev, "no phyclk specified\n");
+		rphy->clk = NULL;
+	}
+
 	ret = rockchip_usb2phy_clk480m_register(rphy);
 	if (ret) {
 		dev_err(dev, "failed to register 480m output clock\n");
-		return ret;
+		goto disable_clks;
 	}
 
 	if (rphy->phy_cfg->phy_tuning) {
 		ret = rphy->phy_cfg->phy_tuning(rphy);
 		if (ret)
-			return ret;
+			goto disable_clks;
 	}
 
 	index = 0;
@@ -1123,6 +1130,11 @@ next_child:
 
 put_child:
 	of_node_put(child_np);
+disable_clks:
+	if (rphy->clk) {
+		clk_disable_unprepare(rphy->clk);
+		clk_put(rphy->clk);
+	}
 	return ret;
 }
 
@@ -1178,6 +1190,14 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
 				.bvalid_det_clr	= { 0xe3d0, 3, 3, 0, 1 },
 				.utmi_bvalid	= { 0xe2ac, 7, 7, 0, 1 },
 			},
+			[USB2PHY_PORT_HOST] = {
+				.phy_sus	= { 0xe458, 1, 0, 0x2, 0x1 },
+				.ls_det_en	= { 0xe3c0, 6, 6, 0, 1 },
+				.ls_det_st	= { 0xe3e0, 6, 6, 0, 1 },
+				.ls_det_clr	= { 0xe3d0, 6, 6, 0, 1 },
+				.utmi_ls	= { 0xe2ac, 22, 21, 0, 1 },
+				.utmi_hstdet	= { 0xe2ac, 23, 23, 0, 1 }
+			}
 		},
 		.chg_det = {
 			.opmode		= { 0xe454, 3, 0, 5, 1 },
@@ -1192,6 +1212,21 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
 			.vdp_src_en	= { 0xe450, 11, 11, 0, 1 },
 		},
 	},
+	{
+		.reg		= 0xe460,
+		.num_ports	= 2,
+		.clkout_ctl	= { 0xe460, 4, 4, 1, 0 },
+		.port_cfgs	= {
+			[USB2PHY_PORT_HOST] = {
+				.phy_sus	= { 0xe468, 1, 0, 0x2, 0x1 },
+				.ls_det_en	= { 0xe3c0, 11, 11, 0, 1 },
+				.ls_det_st	= { 0xe3e0, 11, 11, 0, 1 },
+				.ls_det_clr	= { 0xe3d0, 11, 11, 0, 1 },
+				.utmi_ls	= { 0xe2ac, 26, 25, 0, 1 },
+				.utmi_hstdet	= { 0xe2ac, 27, 27, 0, 1 }
+			}
+		},
+	},
 	{ /* sentinel */ }
 };