All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/8] phy: rockchip-usb: correct pll handling and usb-uart
@ 2015-11-19 21:22 ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl, Heiko Stuebner

changes in v3:
- rebase on top of Julias of_node_put fix
- address comments from Kishon Vijay Abraham
  - position of the devm_action in the first patch
  - separate compatible-addition into separate patch
  - don't rephrase comment when moving stuff around
- address Doug's comment and keep clk-tree change and assigned-clocks
  setting together
- add Doug's review-tag to patches 5,6,7
changes in v2:
- add Doug's review-tag to patches 1 and 3
- address comment and add the missing transistional rk_phy->base
  assignment in patch2

Patch 1 might be nice to go in as fix together with Julia's patch?

Patches 2-7 fix a long-standing issue with the clock-tree of Rockchip SoCs
namely our ignorance of the usbphy-internal pll that creates the needed
480MHz but is also a supply-clock back to the core clock-controller in
Rockchip SoCs.

Till now that was worked around using a virtual clock in the cru itself,
but that is of course ignorant of other parts then disabling the phy
behind the cru's back, thus breaking potential users of these clocks.


Patch 8, while not associated with the new pll handling, also builds
on the groundwork introduced there and adds support for the function
repurposing one of the phys as passthrough for uart-data. This enables
attaching a ttl converter to the D+ and D- pins of an usb cable to
receive uart data this way, when it is not really possible to attach
a regular serial console to a board.

One point of critique in my first iteration [0] of this was, that
due to when the reconfiguration happens we may miss parts of the logs
when earlycon is enabled. So far early_initcall gets used as the
unflattened devicetree is necessary to set this up. Doing this for
example in the early_param directly would require parsing the flattened
devicetree to get needed nodes and properties.

I still maintain that if you're working on anything before smp-bringup
you should use a real dev-board instead or try to solder uart cables
on hopefully available test-points :-) .


In any case, if patch 8 causes to much headache, it could be dropped
to not hinder the earlier 7 patches.

[0] http://comments.gmane.org/gmane.linux.ports.arm.rockchip/715

Heiko Stuebner (8):
  phy: rockchip-usb: fix clock get-put mismatch
  phy: rockchip-usb: introduce a common data-struct for the device
  phy: rockchip-usb: move per-phy init into a separate function
  phy: rockchip-usb: add compatible values for rk3066a and rk3188
  phy: rockchip-usb: expose the phy-internal PLLs
  ARM: dts: rockchip: add clock-cells for usb phy nodes
  clk: rockchip: fix usbphy-related clocks
  phy: rockchip-usb: add handler for usb-uart functionality

 .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   6 +-
 Documentation/kernel-parameters.txt                |   6 +
 arch/arm/boot/dts/rk3066a.dtsi                     |   2 +
 arch/arm/boot/dts/rk3188.dtsi                      |   2 +
 arch/arm/boot/dts/rk3288-veyron.dtsi               |   2 +-
 arch/arm/boot/dts/rk3288.dtsi                      |   3 +
 drivers/clk/rockchip/clk-rk3188.c                  |  11 +-
 drivers/clk/rockchip/clk-rk3288.c                  |  16 +-
 drivers/phy/phy-rockchip-usb.c                     | 458 ++++++++++++++++++---
 9 files changed, 417 insertions(+), 89 deletions(-)

-- 
2.6.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 0/8] phy: rockchip-usb: correct pll handling and usb-uart
@ 2015-11-19 21:22 ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: hl, arnd, linux-kernel, dianders, linux-rockchip, romain.perier,
	linux-arm-kernel, Heiko Stuebner

changes in v3:
- rebase on top of Julias of_node_put fix
- address comments from Kishon Vijay Abraham
  - position of the devm_action in the first patch
  - separate compatible-addition into separate patch
  - don't rephrase comment when moving stuff around
- address Doug's comment and keep clk-tree change and assigned-clocks
  setting together
- add Doug's review-tag to patches 5,6,7
changes in v2:
- add Doug's review-tag to patches 1 and 3
- address comment and add the missing transistional rk_phy->base
  assignment in patch2

Patch 1 might be nice to go in as fix together with Julia's patch?

Patches 2-7 fix a long-standing issue with the clock-tree of Rockchip SoCs
namely our ignorance of the usbphy-internal pll that creates the needed
480MHz but is also a supply-clock back to the core clock-controller in
Rockchip SoCs.

Till now that was worked around using a virtual clock in the cru itself,
but that is of course ignorant of other parts then disabling the phy
behind the cru's back, thus breaking potential users of these clocks.


Patch 8, while not associated with the new pll handling, also builds
on the groundwork introduced there and adds support for the function
repurposing one of the phys as passthrough for uart-data. This enables
attaching a ttl converter to the D+ and D- pins of an usb cable to
receive uart data this way, when it is not really possible to attach
a regular serial console to a board.

One point of critique in my first iteration [0] of this was, that
due to when the reconfiguration happens we may miss parts of the logs
when earlycon is enabled. So far early_initcall gets used as the
unflattened devicetree is necessary to set this up. Doing this for
example in the early_param directly would require parsing the flattened
devicetree to get needed nodes and properties.

I still maintain that if you're working on anything before smp-bringup
you should use a real dev-board instead or try to solder uart cables
on hopefully available test-points :-) .


In any case, if patch 8 causes to much headache, it could be dropped
to not hinder the earlier 7 patches.

[0] http://comments.gmane.org/gmane.linux.ports.arm.rockchip/715

Heiko Stuebner (8):
  phy: rockchip-usb: fix clock get-put mismatch
  phy: rockchip-usb: introduce a common data-struct for the device
  phy: rockchip-usb: move per-phy init into a separate function
  phy: rockchip-usb: add compatible values for rk3066a and rk3188
  phy: rockchip-usb: expose the phy-internal PLLs
  ARM: dts: rockchip: add clock-cells for usb phy nodes
  clk: rockchip: fix usbphy-related clocks
  phy: rockchip-usb: add handler for usb-uart functionality

 .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   6 +-
 Documentation/kernel-parameters.txt                |   6 +
 arch/arm/boot/dts/rk3066a.dtsi                     |   2 +
 arch/arm/boot/dts/rk3188.dtsi                      |   2 +
 arch/arm/boot/dts/rk3288-veyron.dtsi               |   2 +-
 arch/arm/boot/dts/rk3288.dtsi                      |   3 +
 drivers/clk/rockchip/clk-rk3188.c                  |  11 +-
 drivers/clk/rockchip/clk-rk3288.c                  |  16 +-
 drivers/phy/phy-rockchip-usb.c                     | 458 ++++++++++++++++++---
 9 files changed, 417 insertions(+), 89 deletions(-)

-- 
2.6.2

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 0/8] phy: rockchip-usb: correct pll handling and usb-uart
@ 2015-11-19 21:22 ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: linux-arm-kernel

changes in v3:
- rebase on top of Julias of_node_put fix
- address comments from Kishon Vijay Abraham
  - position of the devm_action in the first patch
  - separate compatible-addition into separate patch
  - don't rephrase comment when moving stuff around
- address Doug's comment and keep clk-tree change and assigned-clocks
  setting together
- add Doug's review-tag to patches 5,6,7
changes in v2:
- add Doug's review-tag to patches 1 and 3
- address comment and add the missing transistional rk_phy->base
  assignment in patch2

Patch 1 might be nice to go in as fix together with Julia's patch?

Patches 2-7 fix a long-standing issue with the clock-tree of Rockchip SoCs
namely our ignorance of the usbphy-internal pll that creates the needed
480MHz but is also a supply-clock back to the core clock-controller in
Rockchip SoCs.

Till now that was worked around using a virtual clock in the cru itself,
but that is of course ignorant of other parts then disabling the phy
behind the cru's back, thus breaking potential users of these clocks.


Patch 8, while not associated with the new pll handling, also builds
on the groundwork introduced there and adds support for the function
repurposing one of the phys as passthrough for uart-data. This enables
attaching a ttl converter to the D+ and D- pins of an usb cable to
receive uart data this way, when it is not really possible to attach
a regular serial console to a board.

One point of critique in my first iteration [0] of this was, that
due to when the reconfiguration happens we may miss parts of the logs
when earlycon is enabled. So far early_initcall gets used as the
unflattened devicetree is necessary to set this up. Doing this for
example in the early_param directly would require parsing the flattened
devicetree to get needed nodes and properties.

I still maintain that if you're working on anything before smp-bringup
you should use a real dev-board instead or try to solder uart cables
on hopefully available test-points :-) .


In any case, if patch 8 causes to much headache, it could be dropped
to not hinder the earlier 7 patches.

[0] http://comments.gmane.org/gmane.linux.ports.arm.rockchip/715

Heiko Stuebner (8):
  phy: rockchip-usb: fix clock get-put mismatch
  phy: rockchip-usb: introduce a common data-struct for the device
  phy: rockchip-usb: move per-phy init into a separate function
  phy: rockchip-usb: add compatible values for rk3066a and rk3188
  phy: rockchip-usb: expose the phy-internal PLLs
  ARM: dts: rockchip: add clock-cells for usb phy nodes
  clk: rockchip: fix usbphy-related clocks
  phy: rockchip-usb: add handler for usb-uart functionality

 .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   6 +-
 Documentation/kernel-parameters.txt                |   6 +
 arch/arm/boot/dts/rk3066a.dtsi                     |   2 +
 arch/arm/boot/dts/rk3188.dtsi                      |   2 +
 arch/arm/boot/dts/rk3288-veyron.dtsi               |   2 +-
 arch/arm/boot/dts/rk3288.dtsi                      |   3 +
 drivers/clk/rockchip/clk-rk3188.c                  |  11 +-
 drivers/clk/rockchip/clk-rk3288.c                  |  16 +-
 drivers/phy/phy-rockchip-usb.c                     | 458 ++++++++++++++++++---
 9 files changed, 417 insertions(+), 89 deletions(-)

-- 
2.6.2

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 1/8] phy: rockchip-usb: fix clock get-put mismatch
  2015-11-19 21:22 ` Heiko Stuebner
  (?)
@ 2015-11-19 21:22   ` Heiko Stuebner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl, Heiko Stuebner

Currently the phy driver only gets the optional clock reference but
never puts it again, neither during error handling nor on remove.
Fix that by moving the clk_put to a devm-action that gets called at
the right time when all other devm actions are done.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 drivers/phy/phy-rockchip-usb.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 62c43c4..e941444 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -90,6 +90,14 @@ static const struct phy_ops ops = {
 	.owner		= THIS_MODULE,
 };
 
+static void rockchip_usb_phy_action(void *data)
+{
+	struct rockchip_usb_phy *rk_phy = data;
+
+	if (rk_phy->clk)
+		clk_put(rk_phy->clk);
+}
+
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -123,6 +131,10 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 		rk_phy->reg_offset = reg_offset;
 		rk_phy->reg_base = grf;
 
+		err = devm_add_action(dev, rockchip_usb_phy_action, rk_phy);
+		if (err)
+			return err;
+
 		rk_phy->clk = of_clk_get_by_name(child, "phyclk");
 		if (IS_ERR(rk_phy->clk))
 			rk_phy->clk = NULL;
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 1/8] phy: rockchip-usb: fix clock get-put mismatch
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: hl, arnd, linux-kernel, dianders, linux-rockchip, romain.perier,
	linux-arm-kernel, Heiko Stuebner

Currently the phy driver only gets the optional clock reference but
never puts it again, neither during error handling nor on remove.
Fix that by moving the clk_put to a devm-action that gets called at
the right time when all other devm actions are done.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 drivers/phy/phy-rockchip-usb.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 62c43c4..e941444 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -90,6 +90,14 @@ static const struct phy_ops ops = {
 	.owner		= THIS_MODULE,
 };
 
+static void rockchip_usb_phy_action(void *data)
+{
+	struct rockchip_usb_phy *rk_phy = data;
+
+	if (rk_phy->clk)
+		clk_put(rk_phy->clk);
+}
+
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -123,6 +131,10 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 		rk_phy->reg_offset = reg_offset;
 		rk_phy->reg_base = grf;
 
+		err = devm_add_action(dev, rockchip_usb_phy_action, rk_phy);
+		if (err)
+			return err;
+
 		rk_phy->clk = of_clk_get_by_name(child, "phyclk");
 		if (IS_ERR(rk_phy->clk))
 			rk_phy->clk = NULL;
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 1/8] phy: rockchip-usb: fix clock get-put mismatch
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: linux-arm-kernel

Currently the phy driver only gets the optional clock reference but
never puts it again, neither during error handling nor on remove.
Fix that by moving the clk_put to a devm-action that gets called at
the right time when all other devm actions are done.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 drivers/phy/phy-rockchip-usb.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 62c43c4..e941444 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -90,6 +90,14 @@ static const struct phy_ops ops = {
 	.owner		= THIS_MODULE,
 };
 
+static void rockchip_usb_phy_action(void *data)
+{
+	struct rockchip_usb_phy *rk_phy = data;
+
+	if (rk_phy->clk)
+		clk_put(rk_phy->clk);
+}
+
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -123,6 +131,10 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 		rk_phy->reg_offset = reg_offset;
 		rk_phy->reg_base = grf;
 
+		err = devm_add_action(dev, rockchip_usb_phy_action, rk_phy);
+		if (err)
+			return err;
+
 		rk_phy->clk = of_clk_get_by_name(child, "phyclk");
 		if (IS_ERR(rk_phy->clk))
 			rk_phy->clk = NULL;
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 2/8] phy: rockchip-usb: introduce a common data-struct for the device
  2015-11-19 21:22 ` Heiko Stuebner
@ 2015-11-19 21:22   ` Heiko Stuebner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl, Heiko Stuebner

This introduces a common struct that holds data belonging to
the umbrella device that contains all the phys and that we
want to use later.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/phy/phy-rockchip-usb.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index e941444..2b4802a 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -36,9 +36,14 @@
 #define SIDDQ_ON		BIT(13)
 #define SIDDQ_OFF		(0 << 13)
 
+struct rockchip_usb_phy_base {
+	struct device *dev;
+	struct regmap *reg_base;
+};
+
 struct rockchip_usb_phy {
+	struct rockchip_usb_phy_base *base;
 	unsigned int	reg_offset;
-	struct regmap	*reg_base;
 	struct clk	*clk;
 	struct phy	*phy;
 };
@@ -46,7 +51,7 @@ struct rockchip_usb_phy {
 static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
 					   bool siddq)
 {
-	return regmap_write(phy->reg_base, phy->reg_offset,
+	return regmap_write(phy->base->reg_base, phy->reg_offset,
 			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
 }
 
@@ -101,17 +106,23 @@ static void rockchip_usb_phy_action(void *data)
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct rockchip_usb_phy_base *phy_base;
 	struct rockchip_usb_phy *rk_phy;
 	struct phy_provider *phy_provider;
 	struct device_node *child;
-	struct regmap *grf;
 	unsigned int reg_offset;
 	int err;
 
-	grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
-	if (IS_ERR(grf)) {
+	phy_base = devm_kzalloc(dev, sizeof(*phy_base), GFP_KERNEL);
+	if (!phy_base)
+		return -ENOMEM;
+
+	phy_base->dev = dev;
+	phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
+							     "rockchip,grf");
+	if (IS_ERR(phy_base->reg_base)) {
 		dev_err(&pdev->dev, "Missing rockchip,grf property\n");
-		return PTR_ERR(grf);
+		return PTR_ERR(phy_base->reg_base);
 	}
 
 	for_each_available_child_of_node(dev->of_node, child) {
@@ -121,6 +132,8 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 			goto put_child;
 		}
 
+		rk_phy->base = phy_base;
+
 		if (of_property_read_u32(child, "reg", &reg_offset)) {
 			dev_err(dev, "missing reg property in node %s\n",
 				child->name);
@@ -129,7 +142,6 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 		}
 
 		rk_phy->reg_offset = reg_offset;
-		rk_phy->reg_base = grf;
 
 		err = devm_add_action(dev, rockchip_usb_phy_action, rk_phy);
 		if (err)
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 2/8] phy: rockchip-usb: introduce a common data-struct for the device
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: linux-arm-kernel

This introduces a common struct that holds data belonging to
the umbrella device that contains all the phys and that we
want to use later.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/phy/phy-rockchip-usb.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index e941444..2b4802a 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -36,9 +36,14 @@
 #define SIDDQ_ON		BIT(13)
 #define SIDDQ_OFF		(0 << 13)
 
+struct rockchip_usb_phy_base {
+	struct device *dev;
+	struct regmap *reg_base;
+};
+
 struct rockchip_usb_phy {
+	struct rockchip_usb_phy_base *base;
 	unsigned int	reg_offset;
-	struct regmap	*reg_base;
 	struct clk	*clk;
 	struct phy	*phy;
 };
@@ -46,7 +51,7 @@ struct rockchip_usb_phy {
 static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
 					   bool siddq)
 {
-	return regmap_write(phy->reg_base, phy->reg_offset,
+	return regmap_write(phy->base->reg_base, phy->reg_offset,
 			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
 }
 
@@ -101,17 +106,23 @@ static void rockchip_usb_phy_action(void *data)
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct rockchip_usb_phy_base *phy_base;
 	struct rockchip_usb_phy *rk_phy;
 	struct phy_provider *phy_provider;
 	struct device_node *child;
-	struct regmap *grf;
 	unsigned int reg_offset;
 	int err;
 
-	grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
-	if (IS_ERR(grf)) {
+	phy_base = devm_kzalloc(dev, sizeof(*phy_base), GFP_KERNEL);
+	if (!phy_base)
+		return -ENOMEM;
+
+	phy_base->dev = dev;
+	phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
+							     "rockchip,grf");
+	if (IS_ERR(phy_base->reg_base)) {
 		dev_err(&pdev->dev, "Missing rockchip,grf property\n");
-		return PTR_ERR(grf);
+		return PTR_ERR(phy_base->reg_base);
 	}
 
 	for_each_available_child_of_node(dev->of_node, child) {
@@ -121,6 +132,8 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 			goto put_child;
 		}
 
+		rk_phy->base = phy_base;
+
 		if (of_property_read_u32(child, "reg", &reg_offset)) {
 			dev_err(dev, "missing reg property in node %s\n",
 				child->name);
@@ -129,7 +142,6 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 		}
 
 		rk_phy->reg_offset = reg_offset;
-		rk_phy->reg_base = grf;
 
 		err = devm_add_action(dev, rockchip_usb_phy_action, rk_phy);
 		if (err)
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 3/8] phy: rockchip-usb: move per-phy init into a separate function
  2015-11-19 21:22 ` Heiko Stuebner
  (?)
@ 2015-11-19 21:22   ` Heiko Stuebner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl, Heiko Stuebner

This unclutters the loop in probe a lot and makes current (and future)
error handling easier to read.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 drivers/phy/phy-rockchip-usb.c | 83 ++++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 40 deletions(-)

diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 2b4802a..ff3ac33 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -103,14 +103,52 @@ static void rockchip_usb_phy_action(void *data)
 		clk_put(rk_phy->clk);
 }
 
+static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
+				 struct device_node *child)
+{
+	struct rockchip_usb_phy *rk_phy;
+	unsigned int reg_offset;
+	int err;
+
+	rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
+	if (!rk_phy)
+		return -ENOMEM;
+
+	rk_phy->base = base;
+
+	if (of_property_read_u32(child, "reg", &reg_offset)) {
+		dev_err(base->dev, "missing reg property in node %s\n",
+			child->name);
+		return -EINVAL;
+	}
+
+	rk_phy->reg_offset = reg_offset;
+
+	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
+	if (err)
+		return err;
+
+	rk_phy->clk = of_clk_get_by_name(child, "phyclk");
+	if (IS_ERR(rk_phy->clk))
+		rk_phy->clk = NULL;
+
+	rk_phy->phy = devm_phy_create(base->dev, child, &ops);
+	if (IS_ERR(rk_phy->phy)) {
+		dev_err(base->dev, "failed to create PHY\n");
+		return PTR_ERR(rk_phy->phy);
+	}
+	phy_set_drvdata(rk_phy->phy, rk_phy);
+
+	/* only power up usb phy when it use, so disable it when init*/
+	return rockchip_usb_phy_power(rk_phy, 1);
+}
+
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct rockchip_usb_phy_base *phy_base;
-	struct rockchip_usb_phy *rk_phy;
 	struct phy_provider *phy_provider;
 	struct device_node *child;
-	unsigned int reg_offset;
 	int err;
 
 	phy_base = devm_kzalloc(dev, sizeof(*phy_base), GFP_KERNEL);
@@ -126,50 +164,15 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 	}
 
 	for_each_available_child_of_node(dev->of_node, child) {
-		rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
-		if (!rk_phy) {
-			err = -ENOMEM;
-			goto put_child;
-		}
-
-		rk_phy->base = phy_base;
-
-		if (of_property_read_u32(child, "reg", &reg_offset)) {
-			dev_err(dev, "missing reg property in node %s\n",
-				child->name);
-			err = -EINVAL;
-			goto put_child;
-		}
-
-		rk_phy->reg_offset = reg_offset;
-
-		err = devm_add_action(dev, rockchip_usb_phy_action, rk_phy);
-		if (err)
+		err = rockchip_usb_phy_init(phy_base, child);
+		if (err) {
+			of_node_put(child);
 			return err;
-
-		rk_phy->clk = of_clk_get_by_name(child, "phyclk");
-		if (IS_ERR(rk_phy->clk))
-			rk_phy->clk = NULL;
-
-		rk_phy->phy = devm_phy_create(dev, child, &ops);
-		if (IS_ERR(rk_phy->phy)) {
-			dev_err(dev, "failed to create PHY\n");
-			err = PTR_ERR(rk_phy->phy);
-			goto put_child;
 		}
-		phy_set_drvdata(rk_phy->phy, rk_phy);
-
-		/* only power up usb phy when it use, so disable it when init*/
-		err = rockchip_usb_phy_power(rk_phy, 1);
-		if (err)
-			goto put_child;
 	}
 
 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 	return PTR_ERR_OR_ZERO(phy_provider);
-put_child:
-	of_node_put(child);
-	return err;
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 3/8] phy: rockchip-usb: move per-phy init into a separate function
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: hl, arnd, linux-kernel, dianders, linux-rockchip, romain.perier,
	linux-arm-kernel, Heiko Stuebner

This unclutters the loop in probe a lot and makes current (and future)
error handling easier to read.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 drivers/phy/phy-rockchip-usb.c | 83 ++++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 40 deletions(-)

diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 2b4802a..ff3ac33 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -103,14 +103,52 @@ static void rockchip_usb_phy_action(void *data)
 		clk_put(rk_phy->clk);
 }
 
+static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
+				 struct device_node *child)
+{
+	struct rockchip_usb_phy *rk_phy;
+	unsigned int reg_offset;
+	int err;
+
+	rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
+	if (!rk_phy)
+		return -ENOMEM;
+
+	rk_phy->base = base;
+
+	if (of_property_read_u32(child, "reg", &reg_offset)) {
+		dev_err(base->dev, "missing reg property in node %s\n",
+			child->name);
+		return -EINVAL;
+	}
+
+	rk_phy->reg_offset = reg_offset;
+
+	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
+	if (err)
+		return err;
+
+	rk_phy->clk = of_clk_get_by_name(child, "phyclk");
+	if (IS_ERR(rk_phy->clk))
+		rk_phy->clk = NULL;
+
+	rk_phy->phy = devm_phy_create(base->dev, child, &ops);
+	if (IS_ERR(rk_phy->phy)) {
+		dev_err(base->dev, "failed to create PHY\n");
+		return PTR_ERR(rk_phy->phy);
+	}
+	phy_set_drvdata(rk_phy->phy, rk_phy);
+
+	/* only power up usb phy when it use, so disable it when init*/
+	return rockchip_usb_phy_power(rk_phy, 1);
+}
+
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct rockchip_usb_phy_base *phy_base;
-	struct rockchip_usb_phy *rk_phy;
 	struct phy_provider *phy_provider;
 	struct device_node *child;
-	unsigned int reg_offset;
 	int err;
 
 	phy_base = devm_kzalloc(dev, sizeof(*phy_base), GFP_KERNEL);
@@ -126,50 +164,15 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 	}
 
 	for_each_available_child_of_node(dev->of_node, child) {
-		rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
-		if (!rk_phy) {
-			err = -ENOMEM;
-			goto put_child;
-		}
-
-		rk_phy->base = phy_base;
-
-		if (of_property_read_u32(child, "reg", &reg_offset)) {
-			dev_err(dev, "missing reg property in node %s\n",
-				child->name);
-			err = -EINVAL;
-			goto put_child;
-		}
-
-		rk_phy->reg_offset = reg_offset;
-
-		err = devm_add_action(dev, rockchip_usb_phy_action, rk_phy);
-		if (err)
+		err = rockchip_usb_phy_init(phy_base, child);
+		if (err) {
+			of_node_put(child);
 			return err;
-
-		rk_phy->clk = of_clk_get_by_name(child, "phyclk");
-		if (IS_ERR(rk_phy->clk))
-			rk_phy->clk = NULL;
-
-		rk_phy->phy = devm_phy_create(dev, child, &ops);
-		if (IS_ERR(rk_phy->phy)) {
-			dev_err(dev, "failed to create PHY\n");
-			err = PTR_ERR(rk_phy->phy);
-			goto put_child;
 		}
-		phy_set_drvdata(rk_phy->phy, rk_phy);
-
-		/* only power up usb phy when it use, so disable it when init*/
-		err = rockchip_usb_phy_power(rk_phy, 1);
-		if (err)
-			goto put_child;
 	}
 
 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 	return PTR_ERR_OR_ZERO(phy_provider);
-put_child:
-	of_node_put(child);
-	return err;
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 3/8] phy: rockchip-usb: move per-phy init into a separate function
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: linux-arm-kernel

This unclutters the loop in probe a lot and makes current (and future)
error handling easier to read.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 drivers/phy/phy-rockchip-usb.c | 83 ++++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 40 deletions(-)

diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 2b4802a..ff3ac33 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -103,14 +103,52 @@ static void rockchip_usb_phy_action(void *data)
 		clk_put(rk_phy->clk);
 }
 
+static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
+				 struct device_node *child)
+{
+	struct rockchip_usb_phy *rk_phy;
+	unsigned int reg_offset;
+	int err;
+
+	rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
+	if (!rk_phy)
+		return -ENOMEM;
+
+	rk_phy->base = base;
+
+	if (of_property_read_u32(child, "reg", &reg_offset)) {
+		dev_err(base->dev, "missing reg property in node %s\n",
+			child->name);
+		return -EINVAL;
+	}
+
+	rk_phy->reg_offset = reg_offset;
+
+	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
+	if (err)
+		return err;
+
+	rk_phy->clk = of_clk_get_by_name(child, "phyclk");
+	if (IS_ERR(rk_phy->clk))
+		rk_phy->clk = NULL;
+
+	rk_phy->phy = devm_phy_create(base->dev, child, &ops);
+	if (IS_ERR(rk_phy->phy)) {
+		dev_err(base->dev, "failed to create PHY\n");
+		return PTR_ERR(rk_phy->phy);
+	}
+	phy_set_drvdata(rk_phy->phy, rk_phy);
+
+	/* only power up usb phy when it use, so disable it when init*/
+	return rockchip_usb_phy_power(rk_phy, 1);
+}
+
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct rockchip_usb_phy_base *phy_base;
-	struct rockchip_usb_phy *rk_phy;
 	struct phy_provider *phy_provider;
 	struct device_node *child;
-	unsigned int reg_offset;
 	int err;
 
 	phy_base = devm_kzalloc(dev, sizeof(*phy_base), GFP_KERNEL);
@@ -126,50 +164,15 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 	}
 
 	for_each_available_child_of_node(dev->of_node, child) {
-		rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
-		if (!rk_phy) {
-			err = -ENOMEM;
-			goto put_child;
-		}
-
-		rk_phy->base = phy_base;
-
-		if (of_property_read_u32(child, "reg", &reg_offset)) {
-			dev_err(dev, "missing reg property in node %s\n",
-				child->name);
-			err = -EINVAL;
-			goto put_child;
-		}
-
-		rk_phy->reg_offset = reg_offset;
-
-		err = devm_add_action(dev, rockchip_usb_phy_action, rk_phy);
-		if (err)
+		err = rockchip_usb_phy_init(phy_base, child);
+		if (err) {
+			of_node_put(child);
 			return err;
-
-		rk_phy->clk = of_clk_get_by_name(child, "phyclk");
-		if (IS_ERR(rk_phy->clk))
-			rk_phy->clk = NULL;
-
-		rk_phy->phy = devm_phy_create(dev, child, &ops);
-		if (IS_ERR(rk_phy->phy)) {
-			dev_err(dev, "failed to create PHY\n");
-			err = PTR_ERR(rk_phy->phy);
-			goto put_child;
 		}
-		phy_set_drvdata(rk_phy->phy, rk_phy);
-
-		/* only power up usb phy when it use, so disable it when init*/
-		err = rockchip_usb_phy_power(rk_phy, 1);
-		if (err)
-			goto put_child;
 	}
 
 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 	return PTR_ERR_OR_ZERO(phy_provider);
-put_child:
-	of_node_put(child);
-	return err;
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl, Heiko Stuebner

We need custom handling for these two socs in the driver shortly,
so add the necessary compatible values to binding and driver.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
 drivers/phy/phy-rockchip-usb.c                             | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
index 826454a..9b37242 100644
--- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
@@ -1,7 +1,10 @@
 ROCKCHIP USB2 PHY
 
 Required properties:
- - compatible: rockchip,rk3288-usb-phy
+ - compatible: matching the soc type, one of
+     "rockchip,rk3066a-usb-phy"
+     "rockchip,rk3188-usb-phy"
+     "rockchip,rk3288-usb-phy"
  - rockchip,grf : phandle to the syscon managing the "general
    register files"
  - #address-cells: should be 1
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index ff3ac33..16cd533 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -176,6 +176,8 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
+	{ .compatible = "rockchip,rk3066a-usb-phy" },
+	{ .compatible = "rockchip,rk3188-usb-phy" },
 	{ .compatible = "rockchip,rk3288-usb-phy" },
 	{}
 };
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon-l0cyMroinI0, mturquette-rdvid1DuHRBWk0Htik3J/w,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: hl-TNX95d0MmH7DzftRWevZcw, arnd-r2nGTMty4D4,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	romain.perier-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Heiko Stuebner

We need custom handling for these two socs in the driver shortly,
so add the necessary compatible values to binding and driver.

Signed-off-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
---
 Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
 drivers/phy/phy-rockchip-usb.c                             | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
index 826454a..9b37242 100644
--- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
@@ -1,7 +1,10 @@
 ROCKCHIP USB2 PHY
 
 Required properties:
- - compatible: rockchip,rk3288-usb-phy
+ - compatible: matching the soc type, one of
+     "rockchip,rk3066a-usb-phy"
+     "rockchip,rk3188-usb-phy"
+     "rockchip,rk3288-usb-phy"
  - rockchip,grf : phandle to the syscon managing the "general
    register files"
  - #address-cells: should be 1
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index ff3ac33..16cd533 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -176,6 +176,8 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
+	{ .compatible = "rockchip,rk3066a-usb-phy" },
+	{ .compatible = "rockchip,rk3188-usb-phy" },
 	{ .compatible = "rockchip,rk3288-usb-phy" },
 	{}
 };
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: linux-arm-kernel

We need custom handling for these two socs in the driver shortly,
so add the necessary compatible values to binding and driver.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
 drivers/phy/phy-rockchip-usb.c                             | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
index 826454a..9b37242 100644
--- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
@@ -1,7 +1,10 @@
 ROCKCHIP USB2 PHY
 
 Required properties:
- - compatible: rockchip,rk3288-usb-phy
+ - compatible: matching the soc type, one of
+     "rockchip,rk3066a-usb-phy"
+     "rockchip,rk3188-usb-phy"
+     "rockchip,rk3288-usb-phy"
  - rockchip,grf : phandle to the syscon managing the "general
    register files"
  - #address-cells: should be 1
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index ff3ac33..16cd533 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -176,6 +176,8 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
+	{ .compatible = "rockchip,rk3066a-usb-phy" },
+	{ .compatible = "rockchip,rk3188-usb-phy" },
 	{ .compatible = "rockchip,rk3288-usb-phy" },
 	{}
 };
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 5/8] phy: rockchip-usb: expose the phy-internal PLLs
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl, Heiko Stuebner

The USB phys on Rockchip SoCs contain their own internal PLLs to create
the 480MHz needed. Additionally this PLL output is also fed back into the
core clock-controller as possible source for clocks like the GPU or others.

Until now this was modelled incorrectly with a "virtual" factor clock in
the clock controller. The one big caveat is that if we turn off the usb phy
via the siddq signal, all analog components get turned off, including the
PLLs. It is therefore possible that a source clock gets disabled without
the clock driver ever knowing, possibly making the system hang.

Therefore register the phy-plls as real clocks that the clock driver can
then reference again normally, making the clock hirarchy finally reflect
the actual hardware.

The phy-ops get converted to simply turning that new clock on and off
which in turn controls the siddq signal of the phy.

Through this the driver gains handling for platform-specific data, to
handle the phy->clock name association.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   1 +
 drivers/phy/phy-rockchip-usb.c                     | 188 ++++++++++++++++++---
 2 files changed, 162 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
index 9b37242..68498d5 100644
--- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
@@ -24,6 +24,7 @@ required properties:
 Optional Properties:
 - clocks : phandle + clock specifier for the phy clocks
 - clock-names: string, clock name, must be "phyclk"
+- #clock-cells: for users of the phy-pll, should be 0
 
 Example:
 
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 16cd533..33a80eb 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -15,12 +15,14 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_platform.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
@@ -36,15 +38,28 @@
 #define SIDDQ_ON		BIT(13)
 #define SIDDQ_OFF		(0 << 13)
 
+struct rockchip_usb_phys {
+	int reg;
+	const char *pll_name;
+};
+
+struct rockchip_usb_phy_pdata {
+	struct rockchip_usb_phys *phys;
+};
+
 struct rockchip_usb_phy_base {
 	struct device *dev;
 	struct regmap *reg_base;
+	const struct rockchip_usb_phy_pdata *pdata;
 };
 
 struct rockchip_usb_phy {
 	struct rockchip_usb_phy_base *base;
+	struct device_node *np;
 	unsigned int	reg_offset;
 	struct clk	*clk;
+	struct clk      *clk480m;
+	struct clk_hw	clk480m_hw;
 	struct phy	*phy;
 };
 
@@ -55,17 +70,59 @@ static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
 			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
 }
 
-static int rockchip_usb_phy_power_off(struct phy *_phy)
+static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
 {
-	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
-	int ret = 0;
+	return 480000000;
+}
+
+static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
+{
+	struct rockchip_usb_phy *phy = container_of(hw,
+						    struct rockchip_usb_phy,
+						    clk480m_hw);
 
 	/* Power down usb phy analog blocks by set siddq 1 */
-	ret = rockchip_usb_phy_power(phy, 1);
-	if (ret)
+	rockchip_usb_phy_power(phy, 1);
+}
+
+static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
+{
+	struct rockchip_usb_phy *phy = container_of(hw,
+						    struct rockchip_usb_phy,
+						    clk480m_hw);
+
+	/* Power up usb phy analog blocks by set siddq 0 */
+	return rockchip_usb_phy_power(phy, 0);
+}
+
+static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
+{
+	struct rockchip_usb_phy *phy = container_of(hw,
+						    struct rockchip_usb_phy,
+						    clk480m_hw);
+	int ret;
+	u32 val;
+
+	ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
+	if (ret < 0)
 		return ret;
 
-	clk_disable_unprepare(phy->clk);
+	return (val & SIDDQ_ON) ? 0 : 1;
+}
+
+static const struct clk_ops rockchip_usb_phy480m_ops = {
+	.enable = rockchip_usb_phy480m_enable,
+	.disable = rockchip_usb_phy480m_disable,
+	.is_enabled = rockchip_usb_phy480m_is_enabled,
+	.recalc_rate = rockchip_usb_phy480m_recalc_rate,
+};
+
+static int rockchip_usb_phy_power_off(struct phy *_phy)
+{
+	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
+
+	clk_disable_unprepare(phy->clk480m);
 
 	return 0;
 }
@@ -73,20 +130,8 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
 static int rockchip_usb_phy_power_on(struct phy *_phy)
 {
 	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
-	int ret = 0;
 
-	ret = clk_prepare_enable(phy->clk);
-	if (ret)
-		return ret;
-
-	/* Power up usb phy analog blocks by set siddq 0 */
-	ret = rockchip_usb_phy_power(phy, 0);
-	if (ret) {
-		clk_disable_unprepare(phy->clk);
-		return ret;
-	}
-
-	return 0;
+	return clk_prepare_enable(phy->clk480m);
 }
 
 static const struct phy_ops ops = {
@@ -99,6 +144,9 @@ static void rockchip_usb_phy_action(void *data)
 {
 	struct rockchip_usb_phy *rk_phy = data;
 
+	of_clk_del_provider(rk_phy->np);
+	clk_unregister(rk_phy->clk480m);
+
 	if (rk_phy->clk)
 		clk_put(rk_phy->clk);
 }
@@ -108,13 +156,16 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 {
 	struct rockchip_usb_phy *rk_phy;
 	unsigned int reg_offset;
-	int err;
+	const char *clk_name;
+	struct clk_init_data init;
+	int err, i;
 
 	rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
 	if (!rk_phy)
 		return -ENOMEM;
 
 	rk_phy->base = base;
+	rk_phy->np = child;
 
 	if (of_property_read_u32(child, "reg", &reg_offset)) {
 		dev_err(base->dev, "missing reg property in node %s\n",
@@ -124,14 +175,54 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 
 	rk_phy->reg_offset = reg_offset;
 
-	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
-	if (err)
-		return err;
-
 	rk_phy->clk = of_clk_get_by_name(child, "phyclk");
 	if (IS_ERR(rk_phy->clk))
 		rk_phy->clk = NULL;
 
+	i = 0;
+	init.name = NULL;
+	while (base->pdata->phys[i].reg) {
+		if (base->pdata->phys[i].reg == reg_offset) {
+			init.name = base->pdata->phys[i].pll_name;
+			break;
+		}
+		i++;
+	}
+
+	if (!init.name) {
+		dev_err(base->dev, "phy data not found\n");
+		return -EINVAL;
+	}
+
+	if (rk_phy->clk) {
+		clk_name = __clk_get_name(rk_phy->clk);
+		init.flags = 0;
+		init.parent_names = &clk_name;
+		init.num_parents = 1;
+	} else {
+		init.flags = CLK_IS_ROOT;
+		init.parent_names = NULL;
+		init.num_parents = 0;
+	}
+
+	init.ops = &rockchip_usb_phy480m_ops;
+	rk_phy->clk480m_hw.init = &init;
+
+	rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
+	if (IS_ERR(rk_phy->clk480m)) {
+		err = PTR_ERR(rk_phy->clk480m);
+		goto err_clk;
+	}
+
+	err = of_clk_add_provider(child, of_clk_src_simple_get,
+				  rk_phy->clk480m);
+	if (err < 0)
+		goto err_clk_prov;
+
+	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
+	if (err)
+		goto err_devm_action;
+
 	rk_phy->phy = devm_phy_create(base->dev, child, &ops);
 	if (IS_ERR(rk_phy->phy)) {
 		dev_err(base->dev, "failed to create PHY\n");
@@ -141,13 +232,48 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 
 	/* only power up usb phy when it use, so disable it when init*/
 	return rockchip_usb_phy_power(rk_phy, 1);
+
+err_devm_action:
+	of_clk_del_provider(child);
+err_clk_prov:
+	clk_unregister(rk_phy->clk480m);
+err_clk:
+	if (rk_phy->clk)
+		clk_put(rk_phy->clk);
+	return err;
 }
 
+static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
+	.phys = (struct rockchip_usb_phys[]){
+		{ .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
+		{ .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
+		{ /* sentinel */ }
+	},
+};
+
+static const struct rockchip_usb_phy_pdata rk3188_pdata = {
+	.phys = (struct rockchip_usb_phys[]){
+		{ .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
+		{ .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
+		{ /* sentinel */ }
+	},
+};
+
+static const struct rockchip_usb_phy_pdata rk3288_pdata = {
+	.phys = (struct rockchip_usb_phys[]){
+		{ .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
+		{ .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
+		{ .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
+		{ /* sentinel */ }
+	},
+};
+
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct rockchip_usb_phy_base *phy_base;
 	struct phy_provider *phy_provider;
+	const struct of_device_id *match;
 	struct device_node *child;
 	int err;
 
@@ -155,6 +281,14 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 	if (!phy_base)
 		return -ENOMEM;
 
+	match = of_match_device(dev->driver->of_match_table, dev);
+	if (!match || !match->data) {
+		dev_err(dev, "missing phy data\n");
+		return -EINVAL;
+	}
+
+	phy_base->pdata = match->data;
+
 	phy_base->dev = dev;
 	phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
 							     "rockchip,grf");
@@ -176,9 +310,9 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
-	{ .compatible = "rockchip,rk3066a-usb-phy" },
-	{ .compatible = "rockchip,rk3188-usb-phy" },
-	{ .compatible = "rockchip,rk3288-usb-phy" },
+	{ .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
+	{ .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
+	{ .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
 	{}
 };
 
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 5/8] phy: rockchip-usb: expose the phy-internal PLLs
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon-l0cyMroinI0, mturquette-rdvid1DuHRBWk0Htik3J/w,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: hl-TNX95d0MmH7DzftRWevZcw, arnd-r2nGTMty4D4,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	romain.perier-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Heiko Stuebner

The USB phys on Rockchip SoCs contain their own internal PLLs to create
the 480MHz needed. Additionally this PLL output is also fed back into the
core clock-controller as possible source for clocks like the GPU or others.

Until now this was modelled incorrectly with a "virtual" factor clock in
the clock controller. The one big caveat is that if we turn off the usb phy
via the siddq signal, all analog components get turned off, including the
PLLs. It is therefore possible that a source clock gets disabled without
the clock driver ever knowing, possibly making the system hang.

Therefore register the phy-plls as real clocks that the clock driver can
then reference again normally, making the clock hirarchy finally reflect
the actual hardware.

The phy-ops get converted to simply turning that new clock on and off
which in turn controls the siddq signal of the phy.

Through this the driver gains handling for platform-specific data, to
handle the phy->clock name association.

Signed-off-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
Reviewed-by: Douglas Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
 .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   1 +
 drivers/phy/phy-rockchip-usb.c                     | 188 ++++++++++++++++++---
 2 files changed, 162 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
index 9b37242..68498d5 100644
--- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
@@ -24,6 +24,7 @@ required properties:
 Optional Properties:
 - clocks : phandle + clock specifier for the phy clocks
 - clock-names: string, clock name, must be "phyclk"
+- #clock-cells: for users of the phy-pll, should be 0
 
 Example:
 
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 16cd533..33a80eb 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -15,12 +15,14 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_platform.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
@@ -36,15 +38,28 @@
 #define SIDDQ_ON		BIT(13)
 #define SIDDQ_OFF		(0 << 13)
 
+struct rockchip_usb_phys {
+	int reg;
+	const char *pll_name;
+};
+
+struct rockchip_usb_phy_pdata {
+	struct rockchip_usb_phys *phys;
+};
+
 struct rockchip_usb_phy_base {
 	struct device *dev;
 	struct regmap *reg_base;
+	const struct rockchip_usb_phy_pdata *pdata;
 };
 
 struct rockchip_usb_phy {
 	struct rockchip_usb_phy_base *base;
+	struct device_node *np;
 	unsigned int	reg_offset;
 	struct clk	*clk;
+	struct clk      *clk480m;
+	struct clk_hw	clk480m_hw;
 	struct phy	*phy;
 };
 
@@ -55,17 +70,59 @@ static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
 			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
 }
 
-static int rockchip_usb_phy_power_off(struct phy *_phy)
+static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
 {
-	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
-	int ret = 0;
+	return 480000000;
+}
+
+static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
+{
+	struct rockchip_usb_phy *phy = container_of(hw,
+						    struct rockchip_usb_phy,
+						    clk480m_hw);
 
 	/* Power down usb phy analog blocks by set siddq 1 */
-	ret = rockchip_usb_phy_power(phy, 1);
-	if (ret)
+	rockchip_usb_phy_power(phy, 1);
+}
+
+static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
+{
+	struct rockchip_usb_phy *phy = container_of(hw,
+						    struct rockchip_usb_phy,
+						    clk480m_hw);
+
+	/* Power up usb phy analog blocks by set siddq 0 */
+	return rockchip_usb_phy_power(phy, 0);
+}
+
+static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
+{
+	struct rockchip_usb_phy *phy = container_of(hw,
+						    struct rockchip_usb_phy,
+						    clk480m_hw);
+	int ret;
+	u32 val;
+
+	ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
+	if (ret < 0)
 		return ret;
 
-	clk_disable_unprepare(phy->clk);
+	return (val & SIDDQ_ON) ? 0 : 1;
+}
+
+static const struct clk_ops rockchip_usb_phy480m_ops = {
+	.enable = rockchip_usb_phy480m_enable,
+	.disable = rockchip_usb_phy480m_disable,
+	.is_enabled = rockchip_usb_phy480m_is_enabled,
+	.recalc_rate = rockchip_usb_phy480m_recalc_rate,
+};
+
+static int rockchip_usb_phy_power_off(struct phy *_phy)
+{
+	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
+
+	clk_disable_unprepare(phy->clk480m);
 
 	return 0;
 }
@@ -73,20 +130,8 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
 static int rockchip_usb_phy_power_on(struct phy *_phy)
 {
 	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
-	int ret = 0;
 
-	ret = clk_prepare_enable(phy->clk);
-	if (ret)
-		return ret;
-
-	/* Power up usb phy analog blocks by set siddq 0 */
-	ret = rockchip_usb_phy_power(phy, 0);
-	if (ret) {
-		clk_disable_unprepare(phy->clk);
-		return ret;
-	}
-
-	return 0;
+	return clk_prepare_enable(phy->clk480m);
 }
 
 static const struct phy_ops ops = {
@@ -99,6 +144,9 @@ static void rockchip_usb_phy_action(void *data)
 {
 	struct rockchip_usb_phy *rk_phy = data;
 
+	of_clk_del_provider(rk_phy->np);
+	clk_unregister(rk_phy->clk480m);
+
 	if (rk_phy->clk)
 		clk_put(rk_phy->clk);
 }
@@ -108,13 +156,16 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 {
 	struct rockchip_usb_phy *rk_phy;
 	unsigned int reg_offset;
-	int err;
+	const char *clk_name;
+	struct clk_init_data init;
+	int err, i;
 
 	rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
 	if (!rk_phy)
 		return -ENOMEM;
 
 	rk_phy->base = base;
+	rk_phy->np = child;
 
 	if (of_property_read_u32(child, "reg", &reg_offset)) {
 		dev_err(base->dev, "missing reg property in node %s\n",
@@ -124,14 +175,54 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 
 	rk_phy->reg_offset = reg_offset;
 
-	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
-	if (err)
-		return err;
-
 	rk_phy->clk = of_clk_get_by_name(child, "phyclk");
 	if (IS_ERR(rk_phy->clk))
 		rk_phy->clk = NULL;
 
+	i = 0;
+	init.name = NULL;
+	while (base->pdata->phys[i].reg) {
+		if (base->pdata->phys[i].reg == reg_offset) {
+			init.name = base->pdata->phys[i].pll_name;
+			break;
+		}
+		i++;
+	}
+
+	if (!init.name) {
+		dev_err(base->dev, "phy data not found\n");
+		return -EINVAL;
+	}
+
+	if (rk_phy->clk) {
+		clk_name = __clk_get_name(rk_phy->clk);
+		init.flags = 0;
+		init.parent_names = &clk_name;
+		init.num_parents = 1;
+	} else {
+		init.flags = CLK_IS_ROOT;
+		init.parent_names = NULL;
+		init.num_parents = 0;
+	}
+
+	init.ops = &rockchip_usb_phy480m_ops;
+	rk_phy->clk480m_hw.init = &init;
+
+	rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
+	if (IS_ERR(rk_phy->clk480m)) {
+		err = PTR_ERR(rk_phy->clk480m);
+		goto err_clk;
+	}
+
+	err = of_clk_add_provider(child, of_clk_src_simple_get,
+				  rk_phy->clk480m);
+	if (err < 0)
+		goto err_clk_prov;
+
+	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
+	if (err)
+		goto err_devm_action;
+
 	rk_phy->phy = devm_phy_create(base->dev, child, &ops);
 	if (IS_ERR(rk_phy->phy)) {
 		dev_err(base->dev, "failed to create PHY\n");
@@ -141,13 +232,48 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 
 	/* only power up usb phy when it use, so disable it when init*/
 	return rockchip_usb_phy_power(rk_phy, 1);
+
+err_devm_action:
+	of_clk_del_provider(child);
+err_clk_prov:
+	clk_unregister(rk_phy->clk480m);
+err_clk:
+	if (rk_phy->clk)
+		clk_put(rk_phy->clk);
+	return err;
 }
 
+static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
+	.phys = (struct rockchip_usb_phys[]){
+		{ .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
+		{ .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
+		{ /* sentinel */ }
+	},
+};
+
+static const struct rockchip_usb_phy_pdata rk3188_pdata = {
+	.phys = (struct rockchip_usb_phys[]){
+		{ .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
+		{ .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
+		{ /* sentinel */ }
+	},
+};
+
+static const struct rockchip_usb_phy_pdata rk3288_pdata = {
+	.phys = (struct rockchip_usb_phys[]){
+		{ .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
+		{ .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
+		{ .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
+		{ /* sentinel */ }
+	},
+};
+
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct rockchip_usb_phy_base *phy_base;
 	struct phy_provider *phy_provider;
+	const struct of_device_id *match;
 	struct device_node *child;
 	int err;
 
@@ -155,6 +281,14 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 	if (!phy_base)
 		return -ENOMEM;
 
+	match = of_match_device(dev->driver->of_match_table, dev);
+	if (!match || !match->data) {
+		dev_err(dev, "missing phy data\n");
+		return -EINVAL;
+	}
+
+	phy_base->pdata = match->data;
+
 	phy_base->dev = dev;
 	phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
 							     "rockchip,grf");
@@ -176,9 +310,9 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
-	{ .compatible = "rockchip,rk3066a-usb-phy" },
-	{ .compatible = "rockchip,rk3188-usb-phy" },
-	{ .compatible = "rockchip,rk3288-usb-phy" },
+	{ .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
+	{ .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
+	{ .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
 	{}
 };
 
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 5/8] phy: rockchip-usb: expose the phy-internal PLLs
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: linux-arm-kernel

The USB phys on Rockchip SoCs contain their own internal PLLs to create
the 480MHz needed. Additionally this PLL output is also fed back into the
core clock-controller as possible source for clocks like the GPU or others.

Until now this was modelled incorrectly with a "virtual" factor clock in
the clock controller. The one big caveat is that if we turn off the usb phy
via the siddq signal, all analog components get turned off, including the
PLLs. It is therefore possible that a source clock gets disabled without
the clock driver ever knowing, possibly making the system hang.

Therefore register the phy-plls as real clocks that the clock driver can
then reference again normally, making the clock hirarchy finally reflect
the actual hardware.

The phy-ops get converted to simply turning that new clock on and off
which in turn controls the siddq signal of the phy.

Through this the driver gains handling for platform-specific data, to
handle the phy->clock name association.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   1 +
 drivers/phy/phy-rockchip-usb.c                     | 188 ++++++++++++++++++---
 2 files changed, 162 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
index 9b37242..68498d5 100644
--- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
@@ -24,6 +24,7 @@ required properties:
 Optional Properties:
 - clocks : phandle + clock specifier for the phy clocks
 - clock-names: string, clock name, must be "phyclk"
+- #clock-cells: for users of the phy-pll, should be 0
 
 Example:
 
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 16cd533..33a80eb 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -15,12 +15,14 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_platform.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
@@ -36,15 +38,28 @@
 #define SIDDQ_ON		BIT(13)
 #define SIDDQ_OFF		(0 << 13)
 
+struct rockchip_usb_phys {
+	int reg;
+	const char *pll_name;
+};
+
+struct rockchip_usb_phy_pdata {
+	struct rockchip_usb_phys *phys;
+};
+
 struct rockchip_usb_phy_base {
 	struct device *dev;
 	struct regmap *reg_base;
+	const struct rockchip_usb_phy_pdata *pdata;
 };
 
 struct rockchip_usb_phy {
 	struct rockchip_usb_phy_base *base;
+	struct device_node *np;
 	unsigned int	reg_offset;
 	struct clk	*clk;
+	struct clk      *clk480m;
+	struct clk_hw	clk480m_hw;
 	struct phy	*phy;
 };
 
@@ -55,17 +70,59 @@ static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
 			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
 }
 
-static int rockchip_usb_phy_power_off(struct phy *_phy)
+static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
 {
-	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
-	int ret = 0;
+	return 480000000;
+}
+
+static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
+{
+	struct rockchip_usb_phy *phy = container_of(hw,
+						    struct rockchip_usb_phy,
+						    clk480m_hw);
 
 	/* Power down usb phy analog blocks by set siddq 1 */
-	ret = rockchip_usb_phy_power(phy, 1);
-	if (ret)
+	rockchip_usb_phy_power(phy, 1);
+}
+
+static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
+{
+	struct rockchip_usb_phy *phy = container_of(hw,
+						    struct rockchip_usb_phy,
+						    clk480m_hw);
+
+	/* Power up usb phy analog blocks by set siddq 0 */
+	return rockchip_usb_phy_power(phy, 0);
+}
+
+static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
+{
+	struct rockchip_usb_phy *phy = container_of(hw,
+						    struct rockchip_usb_phy,
+						    clk480m_hw);
+	int ret;
+	u32 val;
+
+	ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
+	if (ret < 0)
 		return ret;
 
-	clk_disable_unprepare(phy->clk);
+	return (val & SIDDQ_ON) ? 0 : 1;
+}
+
+static const struct clk_ops rockchip_usb_phy480m_ops = {
+	.enable = rockchip_usb_phy480m_enable,
+	.disable = rockchip_usb_phy480m_disable,
+	.is_enabled = rockchip_usb_phy480m_is_enabled,
+	.recalc_rate = rockchip_usb_phy480m_recalc_rate,
+};
+
+static int rockchip_usb_phy_power_off(struct phy *_phy)
+{
+	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
+
+	clk_disable_unprepare(phy->clk480m);
 
 	return 0;
 }
@@ -73,20 +130,8 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
 static int rockchip_usb_phy_power_on(struct phy *_phy)
 {
 	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
-	int ret = 0;
 
-	ret = clk_prepare_enable(phy->clk);
-	if (ret)
-		return ret;
-
-	/* Power up usb phy analog blocks by set siddq 0 */
-	ret = rockchip_usb_phy_power(phy, 0);
-	if (ret) {
-		clk_disable_unprepare(phy->clk);
-		return ret;
-	}
-
-	return 0;
+	return clk_prepare_enable(phy->clk480m);
 }
 
 static const struct phy_ops ops = {
@@ -99,6 +144,9 @@ static void rockchip_usb_phy_action(void *data)
 {
 	struct rockchip_usb_phy *rk_phy = data;
 
+	of_clk_del_provider(rk_phy->np);
+	clk_unregister(rk_phy->clk480m);
+
 	if (rk_phy->clk)
 		clk_put(rk_phy->clk);
 }
@@ -108,13 +156,16 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 {
 	struct rockchip_usb_phy *rk_phy;
 	unsigned int reg_offset;
-	int err;
+	const char *clk_name;
+	struct clk_init_data init;
+	int err, i;
 
 	rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
 	if (!rk_phy)
 		return -ENOMEM;
 
 	rk_phy->base = base;
+	rk_phy->np = child;
 
 	if (of_property_read_u32(child, "reg", &reg_offset)) {
 		dev_err(base->dev, "missing reg property in node %s\n",
@@ -124,14 +175,54 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 
 	rk_phy->reg_offset = reg_offset;
 
-	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
-	if (err)
-		return err;
-
 	rk_phy->clk = of_clk_get_by_name(child, "phyclk");
 	if (IS_ERR(rk_phy->clk))
 		rk_phy->clk = NULL;
 
+	i = 0;
+	init.name = NULL;
+	while (base->pdata->phys[i].reg) {
+		if (base->pdata->phys[i].reg == reg_offset) {
+			init.name = base->pdata->phys[i].pll_name;
+			break;
+		}
+		i++;
+	}
+
+	if (!init.name) {
+		dev_err(base->dev, "phy data not found\n");
+		return -EINVAL;
+	}
+
+	if (rk_phy->clk) {
+		clk_name = __clk_get_name(rk_phy->clk);
+		init.flags = 0;
+		init.parent_names = &clk_name;
+		init.num_parents = 1;
+	} else {
+		init.flags = CLK_IS_ROOT;
+		init.parent_names = NULL;
+		init.num_parents = 0;
+	}
+
+	init.ops = &rockchip_usb_phy480m_ops;
+	rk_phy->clk480m_hw.init = &init;
+
+	rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
+	if (IS_ERR(rk_phy->clk480m)) {
+		err = PTR_ERR(rk_phy->clk480m);
+		goto err_clk;
+	}
+
+	err = of_clk_add_provider(child, of_clk_src_simple_get,
+				  rk_phy->clk480m);
+	if (err < 0)
+		goto err_clk_prov;
+
+	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
+	if (err)
+		goto err_devm_action;
+
 	rk_phy->phy = devm_phy_create(base->dev, child, &ops);
 	if (IS_ERR(rk_phy->phy)) {
 		dev_err(base->dev, "failed to create PHY\n");
@@ -141,13 +232,48 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 
 	/* only power up usb phy when it use, so disable it when init*/
 	return rockchip_usb_phy_power(rk_phy, 1);
+
+err_devm_action:
+	of_clk_del_provider(child);
+err_clk_prov:
+	clk_unregister(rk_phy->clk480m);
+err_clk:
+	if (rk_phy->clk)
+		clk_put(rk_phy->clk);
+	return err;
 }
 
+static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
+	.phys = (struct rockchip_usb_phys[]){
+		{ .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
+		{ .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
+		{ /* sentinel */ }
+	},
+};
+
+static const struct rockchip_usb_phy_pdata rk3188_pdata = {
+	.phys = (struct rockchip_usb_phys[]){
+		{ .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
+		{ .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
+		{ /* sentinel */ }
+	},
+};
+
+static const struct rockchip_usb_phy_pdata rk3288_pdata = {
+	.phys = (struct rockchip_usb_phys[]){
+		{ .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
+		{ .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
+		{ .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
+		{ /* sentinel */ }
+	},
+};
+
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct rockchip_usb_phy_base *phy_base;
 	struct phy_provider *phy_provider;
+	const struct of_device_id *match;
 	struct device_node *child;
 	int err;
 
@@ -155,6 +281,14 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 	if (!phy_base)
 		return -ENOMEM;
 
+	match = of_match_device(dev->driver->of_match_table, dev);
+	if (!match || !match->data) {
+		dev_err(dev, "missing phy data\n");
+		return -EINVAL;
+	}
+
+	phy_base->pdata = match->data;
+
 	phy_base->dev = dev;
 	phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
 							     "rockchip,grf");
@@ -176,9 +310,9 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
-	{ .compatible = "rockchip,rk3066a-usb-phy" },
-	{ .compatible = "rockchip,rk3188-usb-phy" },
-	{ .compatible = "rockchip,rk3288-usb-phy" },
+	{ .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
+	{ .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
+	{ .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
 	{}
 };
 
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 6/8] ARM: dts: rockchip: add clock-cells for usb phy nodes
  2015-11-19 21:22 ` Heiko Stuebner
  (?)
@ 2015-11-19 21:22   ` Heiko Stuebner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl, Heiko Stuebner

Add the #clock-cells properties for the usbphy nodes as they
provide the pll-clocks now.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 arch/arm/boot/dts/rk3066a.dtsi | 2 ++
 arch/arm/boot/dts/rk3188.dtsi  | 2 ++
 arch/arm/boot/dts/rk3288.dtsi  | 3 +++
 3 files changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index 946f187..3e4b41b 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -181,6 +181,7 @@
 			reg = <0x17c>;
 			clocks = <&cru SCLK_OTGPHY0>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy1: usb-phy1 {
@@ -188,6 +189,7 @@
 			reg = <0x188>;
 			clocks = <&cru SCLK_OTGPHY1>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 6399942..48a287e 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -156,6 +156,7 @@
 			reg = <0x10c>;
 			clocks = <&cru SCLK_OTGPHY0>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy1: usb-phy1 {
@@ -163,6 +164,7 @@
 			reg = <0x11c>;
 			clocks = <&cru SCLK_OTGPHY1>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 6a79c9c..9c71b5e 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -896,6 +896,7 @@
 			reg = <0x320>;
 			clocks = <&cru SCLK_OTGPHY0>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy1: usb-phy1 {
@@ -903,6 +904,7 @@
 			reg = <0x334>;
 			clocks = <&cru SCLK_OTGPHY1>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy2: usb-phy2 {
@@ -910,6 +912,7 @@
 			reg = <0x348>;
 			clocks = <&cru SCLK_OTGPHY2>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 	};
 
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 6/8] ARM: dts: rockchip: add clock-cells for usb phy nodes
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: hl, arnd, linux-kernel, dianders, linux-rockchip, romain.perier,
	linux-arm-kernel, Heiko Stuebner

Add the #clock-cells properties for the usbphy nodes as they
provide the pll-clocks now.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 arch/arm/boot/dts/rk3066a.dtsi | 2 ++
 arch/arm/boot/dts/rk3188.dtsi  | 2 ++
 arch/arm/boot/dts/rk3288.dtsi  | 3 +++
 3 files changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index 946f187..3e4b41b 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -181,6 +181,7 @@
 			reg = <0x17c>;
 			clocks = <&cru SCLK_OTGPHY0>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy1: usb-phy1 {
@@ -188,6 +189,7 @@
 			reg = <0x188>;
 			clocks = <&cru SCLK_OTGPHY1>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 6399942..48a287e 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -156,6 +156,7 @@
 			reg = <0x10c>;
 			clocks = <&cru SCLK_OTGPHY0>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy1: usb-phy1 {
@@ -163,6 +164,7 @@
 			reg = <0x11c>;
 			clocks = <&cru SCLK_OTGPHY1>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 6a79c9c..9c71b5e 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -896,6 +896,7 @@
 			reg = <0x320>;
 			clocks = <&cru SCLK_OTGPHY0>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy1: usb-phy1 {
@@ -903,6 +904,7 @@
 			reg = <0x334>;
 			clocks = <&cru SCLK_OTGPHY1>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy2: usb-phy2 {
@@ -910,6 +912,7 @@
 			reg = <0x348>;
 			clocks = <&cru SCLK_OTGPHY2>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 	};
 
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 6/8] ARM: dts: rockchip: add clock-cells for usb phy nodes
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: linux-arm-kernel

Add the #clock-cells properties for the usbphy nodes as they
provide the pll-clocks now.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 arch/arm/boot/dts/rk3066a.dtsi | 2 ++
 arch/arm/boot/dts/rk3188.dtsi  | 2 ++
 arch/arm/boot/dts/rk3288.dtsi  | 3 +++
 3 files changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index 946f187..3e4b41b 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -181,6 +181,7 @@
 			reg = <0x17c>;
 			clocks = <&cru SCLK_OTGPHY0>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy1: usb-phy1 {
@@ -188,6 +189,7 @@
 			reg = <0x188>;
 			clocks = <&cru SCLK_OTGPHY1>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 6399942..48a287e 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -156,6 +156,7 @@
 			reg = <0x10c>;
 			clocks = <&cru SCLK_OTGPHY0>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy1: usb-phy1 {
@@ -163,6 +164,7 @@
 			reg = <0x11c>;
 			clocks = <&cru SCLK_OTGPHY1>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 6a79c9c..9c71b5e 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -896,6 +896,7 @@
 			reg = <0x320>;
 			clocks = <&cru SCLK_OTGPHY0>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy1: usb-phy1 {
@@ -903,6 +904,7 @@
 			reg = <0x334>;
 			clocks = <&cru SCLK_OTGPHY1>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 
 		usbphy2: usb-phy2 {
@@ -910,6 +912,7 @@
 			reg = <0x348>;
 			clocks = <&cru SCLK_OTGPHY2>;
 			clock-names = "phyclk";
+			#clock-cells = <0>;
 		};
 	};
 
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
  2015-11-19 21:22 ` Heiko Stuebner
  (?)
@ 2015-11-19 21:22   ` Heiko Stuebner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl, Heiko Stuebner

The otgphy clocks really only drive the phy blocks. These in turn
contain plls that then generate the 480m clocks the clock controller
uses to supply some other clocks like uart0, gpu or the video-codec.

So fix this structure to actually respect that hirarchy and removed
that usb480m fixed-rate clock working as a placeholder till now, as
this wouldn't even work if the supplying phy gets turned off while
its pll-output gets used elsewhere.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 arch/arm/boot/dts/rk3288-veyron.dtsi |  2 +-
 drivers/clk/rockchip/clk-rk3188.c    | 11 +++--------
 drivers/clk/rockchip/clk-rk3288.c    | 16 +++++-----------
 3 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
index 5e61f07..0a43e21 100644
--- a/arch/arm/boot/dts/rk3288-veyron.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
@@ -416,7 +416,7 @@
 	status = "okay";
 
 	assigned-clocks = <&cru SCLK_USBPHY480M_SRC>;
-	assigned-clock-parents = <&cru SCLK_OTGPHY0>;
+	assigned-clock-parents = <&usbphy0>;
 	dr_mode = "host";
 };
 
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index abb4760..7836a97 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -319,9 +319,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	 * the 480m are generated inside the usb block from these clocks,
 	 * but they are also a source for the hsicphy clock.
 	 */
-	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(1), 5, GFLAGS),
-	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(1), 6, GFLAGS),
 
 	COMPOSITE(0, "mac_src", mux_mac_p, 0,
@@ -635,7 +635,7 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = {
 	{ /* sentinel */ },
 };
 
-PNAME(mux_hsicphy_p)		= { "sclk_otgphy0", "sclk_otgphy1",
+PNAME(mux_hsicphy_p)		= { "sclk_otgphy0_480m", "sclk_otgphy1_480m",
 				    "gpll", "cpll" };
 
 static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
@@ -739,11 +739,6 @@ static void __init rk3188_common_clk_init(struct device_node *np)
 		pr_warn("%s: could not register clock xin12m: %ld\n",
 			__func__, PTR_ERR(clk));
 
-	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock usb480m: %ld\n",
-			__func__, PTR_ERR(clk));
-
 	rockchip_clk_register_branches(common_clk_branches,
 				  ARRAY_SIZE(common_clk_branches));
 
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 9040878..7c8a3e9 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -195,8 +195,8 @@ PNAME(mux_hsadcout_p)	= { "hsadc_src", "ext_hsadc" };
 PNAME(mux_edp_24m_p)	= { "ext_edp_24m", "xin24m" };
 PNAME(mux_tspout_p)	= { "cpll", "gpll", "npll", "xin27m" };
 
-PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1", "sclk_otgphy2",
-				    "sclk_otgphy0" };
+PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1_480m", "sclk_otgphy2_480m",
+				    "sclk_otgphy0_480m" };
 PNAME(mux_hsicphy480m_p)	= { "cpll", "gpll", "usbphy480m_src" };
 PNAME(mux_hsicphy12m_p)		= { "hsicphy12m_xin12m", "hsicphy12m_usbphy" };
 
@@ -506,11 +506,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 			RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
 			RK3288_CLKGATE_CON(4), 10, GFLAGS),
 
-	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 4, GFLAGS),
-	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 5, GFLAGS),
-	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "xin24m", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 6, GFLAGS),
 	GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 7, GFLAGS),
@@ -874,12 +874,6 @@ static void __init rk3288_clk_init(struct device_node *np)
 		pr_warn("%s: could not register clock xin12m: %ld\n",
 			__func__, PTR_ERR(clk));
 
-
-	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock usb480m: %ld\n",
-			__func__, PTR_ERR(clk));
-
 	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
 					"hclk_vcodec_pre_v", 0, 1, 4);
 	if (IS_ERR(clk))
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: hl, arnd, linux-kernel, dianders, linux-rockchip, romain.perier,
	linux-arm-kernel, Heiko Stuebner

The otgphy clocks really only drive the phy blocks. These in turn
contain plls that then generate the 480m clocks the clock controller
uses to supply some other clocks like uart0, gpu or the video-codec.

So fix this structure to actually respect that hirarchy and removed
that usb480m fixed-rate clock working as a placeholder till now, as
this wouldn't even work if the supplying phy gets turned off while
its pll-output gets used elsewhere.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 arch/arm/boot/dts/rk3288-veyron.dtsi |  2 +-
 drivers/clk/rockchip/clk-rk3188.c    | 11 +++--------
 drivers/clk/rockchip/clk-rk3288.c    | 16 +++++-----------
 3 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
index 5e61f07..0a43e21 100644
--- a/arch/arm/boot/dts/rk3288-veyron.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
@@ -416,7 +416,7 @@
 	status = "okay";
 
 	assigned-clocks = <&cru SCLK_USBPHY480M_SRC>;
-	assigned-clock-parents = <&cru SCLK_OTGPHY0>;
+	assigned-clock-parents = <&usbphy0>;
 	dr_mode = "host";
 };
 
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index abb4760..7836a97 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -319,9 +319,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	 * the 480m are generated inside the usb block from these clocks,
 	 * but they are also a source for the hsicphy clock.
 	 */
-	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(1), 5, GFLAGS),
-	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(1), 6, GFLAGS),
 
 	COMPOSITE(0, "mac_src", mux_mac_p, 0,
@@ -635,7 +635,7 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = {
 	{ /* sentinel */ },
 };
 
-PNAME(mux_hsicphy_p)		= { "sclk_otgphy0", "sclk_otgphy1",
+PNAME(mux_hsicphy_p)		= { "sclk_otgphy0_480m", "sclk_otgphy1_480m",
 				    "gpll", "cpll" };
 
 static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
@@ -739,11 +739,6 @@ static void __init rk3188_common_clk_init(struct device_node *np)
 		pr_warn("%s: could not register clock xin12m: %ld\n",
 			__func__, PTR_ERR(clk));
 
-	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock usb480m: %ld\n",
-			__func__, PTR_ERR(clk));
-
 	rockchip_clk_register_branches(common_clk_branches,
 				  ARRAY_SIZE(common_clk_branches));
 
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 9040878..7c8a3e9 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -195,8 +195,8 @@ PNAME(mux_hsadcout_p)	= { "hsadc_src", "ext_hsadc" };
 PNAME(mux_edp_24m_p)	= { "ext_edp_24m", "xin24m" };
 PNAME(mux_tspout_p)	= { "cpll", "gpll", "npll", "xin27m" };
 
-PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1", "sclk_otgphy2",
-				    "sclk_otgphy0" };
+PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1_480m", "sclk_otgphy2_480m",
+				    "sclk_otgphy0_480m" };
 PNAME(mux_hsicphy480m_p)	= { "cpll", "gpll", "usbphy480m_src" };
 PNAME(mux_hsicphy12m_p)		= { "hsicphy12m_xin12m", "hsicphy12m_usbphy" };
 
@@ -506,11 +506,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 			RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
 			RK3288_CLKGATE_CON(4), 10, GFLAGS),
 
-	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 4, GFLAGS),
-	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 5, GFLAGS),
-	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "xin24m", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 6, GFLAGS),
 	GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 7, GFLAGS),
@@ -874,12 +874,6 @@ static void __init rk3288_clk_init(struct device_node *np)
 		pr_warn("%s: could not register clock xin12m: %ld\n",
 			__func__, PTR_ERR(clk));
 
-
-	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock usb480m: %ld\n",
-			__func__, PTR_ERR(clk));
-
 	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
 					"hclk_vcodec_pre_v", 0, 1, 4);
 	if (IS_ERR(clk))
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: linux-arm-kernel

The otgphy clocks really only drive the phy blocks. These in turn
contain plls that then generate the 480m clocks the clock controller
uses to supply some other clocks like uart0, gpu or the video-codec.

So fix this structure to actually respect that hirarchy and removed
that usb480m fixed-rate clock working as a placeholder till now, as
this wouldn't even work if the supplying phy gets turned off while
its pll-output gets used elsewhere.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 arch/arm/boot/dts/rk3288-veyron.dtsi |  2 +-
 drivers/clk/rockchip/clk-rk3188.c    | 11 +++--------
 drivers/clk/rockchip/clk-rk3288.c    | 16 +++++-----------
 3 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
index 5e61f07..0a43e21 100644
--- a/arch/arm/boot/dts/rk3288-veyron.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
@@ -416,7 +416,7 @@
 	status = "okay";
 
 	assigned-clocks = <&cru SCLK_USBPHY480M_SRC>;
-	assigned-clock-parents = <&cru SCLK_OTGPHY0>;
+	assigned-clock-parents = <&usbphy0>;
 	dr_mode = "host";
 };
 
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index abb4760..7836a97 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -319,9 +319,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	 * the 480m are generated inside the usb block from these clocks,
 	 * but they are also a source for the hsicphy clock.
 	 */
-	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(1), 5, GFLAGS),
-	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(1), 6, GFLAGS),
 
 	COMPOSITE(0, "mac_src", mux_mac_p, 0,
@@ -635,7 +635,7 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = {
 	{ /* sentinel */ },
 };
 
-PNAME(mux_hsicphy_p)		= { "sclk_otgphy0", "sclk_otgphy1",
+PNAME(mux_hsicphy_p)		= { "sclk_otgphy0_480m", "sclk_otgphy1_480m",
 				    "gpll", "cpll" };
 
 static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
@@ -739,11 +739,6 @@ static void __init rk3188_common_clk_init(struct device_node *np)
 		pr_warn("%s: could not register clock xin12m: %ld\n",
 			__func__, PTR_ERR(clk));
 
-	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock usb480m: %ld\n",
-			__func__, PTR_ERR(clk));
-
 	rockchip_clk_register_branches(common_clk_branches,
 				  ARRAY_SIZE(common_clk_branches));
 
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 9040878..7c8a3e9 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -195,8 +195,8 @@ PNAME(mux_hsadcout_p)	= { "hsadc_src", "ext_hsadc" };
 PNAME(mux_edp_24m_p)	= { "ext_edp_24m", "xin24m" };
 PNAME(mux_tspout_p)	= { "cpll", "gpll", "npll", "xin27m" };
 
-PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1", "sclk_otgphy2",
-				    "sclk_otgphy0" };
+PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1_480m", "sclk_otgphy2_480m",
+				    "sclk_otgphy0_480m" };
 PNAME(mux_hsicphy480m_p)	= { "cpll", "gpll", "usbphy480m_src" };
 PNAME(mux_hsicphy12m_p)		= { "hsicphy12m_xin12m", "hsicphy12m_usbphy" };
 
@@ -506,11 +506,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 			RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
 			RK3288_CLKGATE_CON(4), 10, GFLAGS),
 
-	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 4, GFLAGS),
-	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 5, GFLAGS),
-	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "xin24m", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 6, GFLAGS),
 	GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 7, GFLAGS),
@@ -874,12 +874,6 @@ static void __init rk3288_clk_init(struct device_node *np)
 		pr_warn("%s: could not register clock xin12m: %ld\n",
 			__func__, PTR_ERR(clk));
 
-
-	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock usb480m: %ld\n",
-			__func__, PTR_ERR(clk));
-
 	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
 					"hclk_vcodec_pre_v", 0, 1, 4);
 	if (IS_ERR(clk))
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 8/8] phy: rockchip-usb: add handler for usb-uart functionality
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl, Heiko Stuebner

Most newer Rockchip SoCs provide the possibility to use a usb-phy
as passthrough for the debug uart (uart2), making it possible to
for example get console output without needing to open the device.

This patch adds an early_initcall to enable this functionality
conditionally via the commandline and also disables the corresponding
usb controller in the devicetree.

Currently only data for the rk3288 is provided, but at least the
rk3188 and arm64 rk3368 also provide this functionality and will be
enabled later.

On a spliced usb cable the signals are tx on white wire(D+) and
rx on green wire(D-).

The one caveat is that currently the reconfiguration of the phy
happens as early_initcall, as the code depends on the unflattened
devicetree being available. Everything is fine if only a regular
console is active as the console-replay will happen after the
reconfiguation. But with earlycon active output up to smp-init
currently will get lost.

The phy is an optional property for the connected dwc2 controller,
so we still provide the phy device but fail all phy-ops with -EBUSY
to make sure the dwc2 does not try to transmit anything on the
repurposed phy.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 Documentation/kernel-parameters.txt |   6 +
 drivers/phy/phy-rockchip-usb.c      | 231 ++++++++++++++++++++++++++++++------
 2 files changed, 201 insertions(+), 36 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f8aae63..870e786 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3412,6 +3412,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
 	ro		[KNL] Mount root device read-only on boot
 
+	rockchip.usb_uart
+			Enable the uart passthrough on the designated usb port
+			on Rockchip SoCs. When active, the signals of the
+			debug-uart get routed to the D+ and D- pins of the usb
+			port and the regular usb controller gets disabled.
+
 	root=		[KNL] Root filesystem
 			See name_to_dev_t comment in init/do_mounts.c.
 
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 33a80eb..e162513 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -30,21 +30,23 @@
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
 
-/*
- * The higher 16-bit of this register is used for write protection
- * only if BIT(13 + 16) set to 1 the BIT(13) can be written.
- */
-#define SIDDQ_WRITE_ENA	BIT(29)
-#define SIDDQ_ON		BIT(13)
-#define SIDDQ_OFF		(0 << 13)
+static int enable_usb_uart;
+
+#define HIWORD_UPDATE(val, mask) \
+		((val) | (mask) << 16)
+
+#define UOC_CON0_SIDDQ BIT(13)
 
 struct rockchip_usb_phys {
 	int reg;
 	const char *pll_name;
 };
 
+struct rockchip_usb_phy_base;
 struct rockchip_usb_phy_pdata {
 	struct rockchip_usb_phys *phys;
+	int (*init_usb_uart)(struct regmap *grf);
+	int usb_uart_phy;
 };
 
 struct rockchip_usb_phy_base {
@@ -61,13 +63,15 @@ struct rockchip_usb_phy {
 	struct clk      *clk480m;
 	struct clk_hw	clk480m_hw;
 	struct phy	*phy;
+	bool		uart_enabled;
 };
 
 static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
 					   bool siddq)
 {
-	return regmap_write(phy->base->reg_base, phy->reg_offset,
-			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
+	u32 val = HIWORD_UPDATE(siddq ? UOC_CON0_SIDDQ : 0, UOC_CON0_SIDDQ);
+
+	return regmap_write(phy->base->reg_base, phy->reg_offset, val);
 }
 
 static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
@@ -108,7 +112,7 @@ static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
 	if (ret < 0)
 		return ret;
 
-	return (val & SIDDQ_ON) ? 0 : 1;
+	return (val & UOC_CON0_SIDDQ) ? 0 : 1;
 }
 
 static const struct clk_ops rockchip_usb_phy480m_ops = {
@@ -122,6 +126,9 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
 {
 	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
 
+	if (phy->uart_enabled)
+		return -EBUSY;
+
 	clk_disable_unprepare(phy->clk480m);
 
 	return 0;
@@ -131,6 +138,9 @@ static int rockchip_usb_phy_power_on(struct phy *_phy)
 {
 	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
 
+	if (phy->uart_enabled)
+		return -EBUSY;
+
 	return clk_prepare_enable(phy->clk480m);
 }
 
@@ -144,8 +154,10 @@ static void rockchip_usb_phy_action(void *data)
 {
 	struct rockchip_usb_phy *rk_phy = data;
 
-	of_clk_del_provider(rk_phy->np);
-	clk_unregister(rk_phy->clk480m);
+	if (!rk_phy->uart_enabled) {
+		of_clk_del_provider(rk_phy->np);
+		clk_unregister(rk_phy->clk480m);
+	}
 
 	if (rk_phy->clk)
 		clk_put(rk_phy->clk);
@@ -194,30 +206,35 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 		return -EINVAL;
 	}
 
-	if (rk_phy->clk) {
-		clk_name = __clk_get_name(rk_phy->clk);
-		init.flags = 0;
-		init.parent_names = &clk_name;
-		init.num_parents = 1;
+	if (enable_usb_uart && base->pdata->usb_uart_phy == i) {
+		dev_dbg(base->dev, "phy%d used as uart output\n", i);
+		rk_phy->uart_enabled = true;
 	} else {
-		init.flags = CLK_IS_ROOT;
-		init.parent_names = NULL;
-		init.num_parents = 0;
-	}
+		if (rk_phy->clk) {
+			clk_name = __clk_get_name(rk_phy->clk);
+			init.flags = 0;
+			init.parent_names = &clk_name;
+			init.num_parents = 1;
+		} else {
+			init.flags = CLK_IS_ROOT;
+			init.parent_names = NULL;
+			init.num_parents = 0;
+		}
 
-	init.ops = &rockchip_usb_phy480m_ops;
-	rk_phy->clk480m_hw.init = &init;
+		init.ops = &rockchip_usb_phy480m_ops;
+		rk_phy->clk480m_hw.init = &init;
 
-	rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
-	if (IS_ERR(rk_phy->clk480m)) {
-		err = PTR_ERR(rk_phy->clk480m);
-		goto err_clk;
-	}
+		rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
+		if (IS_ERR(rk_phy->clk480m)) {
+			err = PTR_ERR(rk_phy->clk480m);
+			goto err_clk;
+		}
 
-	err = of_clk_add_provider(child, of_clk_src_simple_get,
-				  rk_phy->clk480m);
-	if (err < 0)
-		goto err_clk_prov;
+		err = of_clk_add_provider(child, of_clk_src_simple_get,
+					rk_phy->clk480m);
+		if (err < 0)
+			goto err_clk_prov;
+	}
 
 	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
 	if (err)
@@ -230,13 +247,21 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 	}
 	phy_set_drvdata(rk_phy->phy, rk_phy);
 
-	/* only power up usb phy when it use, so disable it when init*/
-	return rockchip_usb_phy_power(rk_phy, 1);
+	/*
+	 * When acting as uart-pipe, just keep clock on otherwise
+	 * only power up usb phy when it use, so disable it when init
+	 */
+	if (rk_phy->uart_enabled)
+		return clk_prepare_enable(rk_phy->clk);
+	else
+		return rockchip_usb_phy_power(rk_phy, 1);
 
 err_devm_action:
-	of_clk_del_provider(child);
+	if (!rk_phy->uart_enabled)
+		of_clk_del_provider(child);
 err_clk_prov:
-	clk_unregister(rk_phy->clk480m);
+	if (!rk_phy->uart_enabled)
+		clk_unregister(rk_phy->clk480m);
 err_clk:
 	if (rk_phy->clk)
 		clk_put(rk_phy->clk);
@@ -259,6 +284,86 @@ static const struct rockchip_usb_phy_pdata rk3188_pdata = {
 	},
 };
 
+#define RK3288_UOC0_CON0				0x320
+#define RK3288_UOC0_CON0_COMMON_ON_N			BIT(0)
+#define RK3288_UOC0_CON0_DISABLE			BIT(4)
+
+#define RK3288_UOC0_CON2				0x328
+#define RK3288_UOC0_CON2_SOFT_CON_SEL			BIT(2)
+
+#define RK3288_UOC0_CON3				0x32c
+#define RK3288_UOC0_CON3_UTMI_SUSPENDN			BIT(0)
+#define RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING		(1 << 1)
+#define RK3288_UOC0_CON3_UTMI_OPMODE_MASK		(3 << 1)
+#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC	(1 << 3)
+#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK		(3 << 3)
+#define RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED		BIT(5)
+#define RK3288_UOC0_CON3_BYPASSDMEN			BIT(6)
+#define RK3288_UOC0_CON3_BYPASSSEL			BIT(7)
+
+/*
+ * Enable the bypass of uart2 data through the otg usb phy.
+ * Original description in the TRM.
+ * 1. Disable the OTG block by setting OTGDISABLE0 to 1’b1.
+ * 2. Disable the pull-up resistance on the D+ line by setting
+ *    OPMODE0[1:0] to 2’b01.
+ * 3. To ensure that the XO, Bias, and PLL blocks are powered down in Suspend
+ *    mode, set COMMONONN to 1’b1.
+ * 4. Place the USB PHY in Suspend mode by setting SUSPENDM0 to 1’b0.
+ * 5. Set BYPASSSEL0 to 1’b1.
+ * 6. To transmit data, controls BYPASSDMEN0, and BYPASSDMDATA0.
+ * To receive data, monitor FSVPLUS0.
+ *
+ * The actual code in the vendor kernel does some things differently.
+ */
+static int __init rk3288_init_usb_uart(struct regmap *grf)
+{
+	u32 val;
+	int ret;
+
+	/*
+	 * COMMON_ON and DISABLE settings are described in the TRM,
+	 * but were not present in the original code.
+	 * Also disable the analog phy components to save power.
+	 */
+	val = HIWORD_UPDATE(RK3288_UOC0_CON0_COMMON_ON_N
+				| RK3288_UOC0_CON0_DISABLE
+				| UOC_CON0_SIDDQ,
+			    RK3288_UOC0_CON0_COMMON_ON_N
+				| RK3288_UOC0_CON0_DISABLE
+				| UOC_CON0_SIDDQ);
+	ret = regmap_write(grf, RK3288_UOC0_CON0, val);
+	if (ret)
+		return ret;
+
+	val = HIWORD_UPDATE(RK3288_UOC0_CON2_SOFT_CON_SEL,
+			    RK3288_UOC0_CON2_SOFT_CON_SEL);
+	ret = regmap_write(grf, RK3288_UOC0_CON2, val);
+	if (ret)
+		return ret;
+
+	val = HIWORD_UPDATE(RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING
+				| RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC
+				| RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED,
+			    RK3288_UOC0_CON3_UTMI_SUSPENDN
+				| RK3288_UOC0_CON3_UTMI_OPMODE_MASK
+				| RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK
+				| RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED);
+	ret = regmap_write(grf, RK3288_UOC0_CON3, val);
+	if (ret)
+		return ret;
+
+	val = HIWORD_UPDATE(RK3288_UOC0_CON3_BYPASSSEL
+				| RK3288_UOC0_CON3_BYPASSDMEN,
+			    RK3288_UOC0_CON3_BYPASSSEL
+				| RK3288_UOC0_CON3_BYPASSDMEN);
+	ret = regmap_write(grf, RK3288_UOC0_CON3, val);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static const struct rockchip_usb_phy_pdata rk3288_pdata = {
 	.phys = (struct rockchip_usb_phys[]){
 		{ .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
@@ -266,6 +371,8 @@ static const struct rockchip_usb_phy_pdata rk3288_pdata = {
 		{ .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
 		{ /* sentinel */ }
 	},
+	.init_usb_uart = rk3288_init_usb_uart,
+	.usb_uart_phy = 0,
 };
 
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
@@ -328,6 +435,58 @@ static struct platform_driver rockchip_usb_driver = {
 
 module_platform_driver(rockchip_usb_driver);
 
+static int __init rockchip_init_usb_uart(void)
+{
+	const struct of_device_id *match;
+	const struct rockchip_usb_phy_pdata *data;
+	struct device_node *np;
+	struct regmap *grf;
+	int ret;
+
+	if (!enable_usb_uart)
+		return 0;
+
+	np = of_find_matching_node_and_match(NULL, rockchip_usb_phy_dt_ids,
+					     &match);
+	if (!np) {
+		pr_err("%s: failed to find usbphy node\n", __func__);
+		return -ENOTSUPP;
+	}
+
+	pr_debug("%s: using settings for %s\n", __func__, match->compatible);
+	data = match->data;
+
+	if (!data->init_usb_uart) {
+		pr_err("%s: usb-uart not available on %s\n",
+		       __func__, match->compatible);
+		return -ENOTSUPP;
+	}
+
+	grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	if (IS_ERR(grf)) {
+		pr_err("%s: Missing rockchip,grf property, %lu\n",
+		       __func__, PTR_ERR(grf));
+		return PTR_ERR(grf);
+	}
+
+	ret = data->init_usb_uart(grf);
+	if (ret) {
+		pr_err("%s: could not init usb_uart, %d\n", __func__, ret);
+		enable_usb_uart = 0;
+		return ret;
+	}
+
+	return 0;
+}
+early_initcall(rockchip_init_usb_uart);
+
+static int __init rockchip_usb_uart(char *buf)
+{
+	enable_usb_uart = true;
+	return 0;
+}
+early_param("rockchip.usb_uart", rockchip_usb_uart);
+
 MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>");
 MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");
 MODULE_LICENSE("GPL v2");
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 8/8] phy: rockchip-usb: add handler for usb-uart functionality
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: kishon-l0cyMroinI0, mturquette-rdvid1DuHRBWk0Htik3J/w,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: hl-TNX95d0MmH7DzftRWevZcw, arnd-r2nGTMty4D4,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	romain.perier-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Heiko Stuebner

Most newer Rockchip SoCs provide the possibility to use a usb-phy
as passthrough for the debug uart (uart2), making it possible to
for example get console output without needing to open the device.

This patch adds an early_initcall to enable this functionality
conditionally via the commandline and also disables the corresponding
usb controller in the devicetree.

Currently only data for the rk3288 is provided, but at least the
rk3188 and arm64 rk3368 also provide this functionality and will be
enabled later.

On a spliced usb cable the signals are tx on white wire(D+) and
rx on green wire(D-).

The one caveat is that currently the reconfiguration of the phy
happens as early_initcall, as the code depends on the unflattened
devicetree being available. Everything is fine if only a regular
console is active as the console-replay will happen after the
reconfiguation. But with earlycon active output up to smp-init
currently will get lost.

The phy is an optional property for the connected dwc2 controller,
so we still provide the phy device but fail all phy-ops with -EBUSY
to make sure the dwc2 does not try to transmit anything on the
repurposed phy.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 Documentation/kernel-parameters.txt |   6 +
 drivers/phy/phy-rockchip-usb.c      | 231 ++++++++++++++++++++++++++++++------
 2 files changed, 201 insertions(+), 36 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f8aae63..870e786 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3412,6 +3412,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
 	ro		[KNL] Mount root device read-only on boot
 
+	rockchip.usb_uart
+			Enable the uart passthrough on the designated usb port
+			on Rockchip SoCs. When active, the signals of the
+			debug-uart get routed to the D+ and D- pins of the usb
+			port and the regular usb controller gets disabled.
+
 	root=		[KNL] Root filesystem
 			See name_to_dev_t comment in init/do_mounts.c.
 
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 33a80eb..e162513 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -30,21 +30,23 @@
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
 
-/*
- * The higher 16-bit of this register is used for write protection
- * only if BIT(13 + 16) set to 1 the BIT(13) can be written.
- */
-#define SIDDQ_WRITE_ENA	BIT(29)
-#define SIDDQ_ON		BIT(13)
-#define SIDDQ_OFF		(0 << 13)
+static int enable_usb_uart;
+
+#define HIWORD_UPDATE(val, mask) \
+		((val) | (mask) << 16)
+
+#define UOC_CON0_SIDDQ BIT(13)
 
 struct rockchip_usb_phys {
 	int reg;
 	const char *pll_name;
 };
 
+struct rockchip_usb_phy_base;
 struct rockchip_usb_phy_pdata {
 	struct rockchip_usb_phys *phys;
+	int (*init_usb_uart)(struct regmap *grf);
+	int usb_uart_phy;
 };
 
 struct rockchip_usb_phy_base {
@@ -61,13 +63,15 @@ struct rockchip_usb_phy {
 	struct clk      *clk480m;
 	struct clk_hw	clk480m_hw;
 	struct phy	*phy;
+	bool		uart_enabled;
 };
 
 static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
 					   bool siddq)
 {
-	return regmap_write(phy->base->reg_base, phy->reg_offset,
-			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
+	u32 val = HIWORD_UPDATE(siddq ? UOC_CON0_SIDDQ : 0, UOC_CON0_SIDDQ);
+
+	return regmap_write(phy->base->reg_base, phy->reg_offset, val);
 }
 
 static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
@@ -108,7 +112,7 @@ static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
 	if (ret < 0)
 		return ret;
 
-	return (val & SIDDQ_ON) ? 0 : 1;
+	return (val & UOC_CON0_SIDDQ) ? 0 : 1;
 }
 
 static const struct clk_ops rockchip_usb_phy480m_ops = {
@@ -122,6 +126,9 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
 {
 	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
 
+	if (phy->uart_enabled)
+		return -EBUSY;
+
 	clk_disable_unprepare(phy->clk480m);
 
 	return 0;
@@ -131,6 +138,9 @@ static int rockchip_usb_phy_power_on(struct phy *_phy)
 {
 	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
 
+	if (phy->uart_enabled)
+		return -EBUSY;
+
 	return clk_prepare_enable(phy->clk480m);
 }
 
@@ -144,8 +154,10 @@ static void rockchip_usb_phy_action(void *data)
 {
 	struct rockchip_usb_phy *rk_phy = data;
 
-	of_clk_del_provider(rk_phy->np);
-	clk_unregister(rk_phy->clk480m);
+	if (!rk_phy->uart_enabled) {
+		of_clk_del_provider(rk_phy->np);
+		clk_unregister(rk_phy->clk480m);
+	}
 
 	if (rk_phy->clk)
 		clk_put(rk_phy->clk);
@@ -194,30 +206,35 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 		return -EINVAL;
 	}
 
-	if (rk_phy->clk) {
-		clk_name = __clk_get_name(rk_phy->clk);
-		init.flags = 0;
-		init.parent_names = &clk_name;
-		init.num_parents = 1;
+	if (enable_usb_uart && base->pdata->usb_uart_phy == i) {
+		dev_dbg(base->dev, "phy%d used as uart output\n", i);
+		rk_phy->uart_enabled = true;
 	} else {
-		init.flags = CLK_IS_ROOT;
-		init.parent_names = NULL;
-		init.num_parents = 0;
-	}
+		if (rk_phy->clk) {
+			clk_name = __clk_get_name(rk_phy->clk);
+			init.flags = 0;
+			init.parent_names = &clk_name;
+			init.num_parents = 1;
+		} else {
+			init.flags = CLK_IS_ROOT;
+			init.parent_names = NULL;
+			init.num_parents = 0;
+		}
 
-	init.ops = &rockchip_usb_phy480m_ops;
-	rk_phy->clk480m_hw.init = &init;
+		init.ops = &rockchip_usb_phy480m_ops;
+		rk_phy->clk480m_hw.init = &init;
 
-	rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
-	if (IS_ERR(rk_phy->clk480m)) {
-		err = PTR_ERR(rk_phy->clk480m);
-		goto err_clk;
-	}
+		rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
+		if (IS_ERR(rk_phy->clk480m)) {
+			err = PTR_ERR(rk_phy->clk480m);
+			goto err_clk;
+		}
 
-	err = of_clk_add_provider(child, of_clk_src_simple_get,
-				  rk_phy->clk480m);
-	if (err < 0)
-		goto err_clk_prov;
+		err = of_clk_add_provider(child, of_clk_src_simple_get,
+					rk_phy->clk480m);
+		if (err < 0)
+			goto err_clk_prov;
+	}
 
 	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
 	if (err)
@@ -230,13 +247,21 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 	}
 	phy_set_drvdata(rk_phy->phy, rk_phy);
 
-	/* only power up usb phy when it use, so disable it when init*/
-	return rockchip_usb_phy_power(rk_phy, 1);
+	/*
+	 * When acting as uart-pipe, just keep clock on otherwise
+	 * only power up usb phy when it use, so disable it when init
+	 */
+	if (rk_phy->uart_enabled)
+		return clk_prepare_enable(rk_phy->clk);
+	else
+		return rockchip_usb_phy_power(rk_phy, 1);
 
 err_devm_action:
-	of_clk_del_provider(child);
+	if (!rk_phy->uart_enabled)
+		of_clk_del_provider(child);
 err_clk_prov:
-	clk_unregister(rk_phy->clk480m);
+	if (!rk_phy->uart_enabled)
+		clk_unregister(rk_phy->clk480m);
 err_clk:
 	if (rk_phy->clk)
 		clk_put(rk_phy->clk);
@@ -259,6 +284,86 @@ static const struct rockchip_usb_phy_pdata rk3188_pdata = {
 	},
 };
 
+#define RK3288_UOC0_CON0				0x320
+#define RK3288_UOC0_CON0_COMMON_ON_N			BIT(0)
+#define RK3288_UOC0_CON0_DISABLE			BIT(4)
+
+#define RK3288_UOC0_CON2				0x328
+#define RK3288_UOC0_CON2_SOFT_CON_SEL			BIT(2)
+
+#define RK3288_UOC0_CON3				0x32c
+#define RK3288_UOC0_CON3_UTMI_SUSPENDN			BIT(0)
+#define RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING		(1 << 1)
+#define RK3288_UOC0_CON3_UTMI_OPMODE_MASK		(3 << 1)
+#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC	(1 << 3)
+#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK		(3 << 3)
+#define RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED		BIT(5)
+#define RK3288_UOC0_CON3_BYPASSDMEN			BIT(6)
+#define RK3288_UOC0_CON3_BYPASSSEL			BIT(7)
+
+/*
+ * Enable the bypass of uart2 data through the otg usb phy.
+ * Original description in the TRM.
+ * 1. Disable the OTG block by setting OTGDISABLE0 to 1’b1.
+ * 2. Disable the pull-up resistance on the D+ line by setting
+ *    OPMODE0[1:0] to 2’b01.
+ * 3. To ensure that the XO, Bias, and PLL blocks are powered down in Suspend
+ *    mode, set COMMONONN to 1’b1.
+ * 4. Place the USB PHY in Suspend mode by setting SUSPENDM0 to 1’b0.
+ * 5. Set BYPASSSEL0 to 1’b1.
+ * 6. To transmit data, controls BYPASSDMEN0, and BYPASSDMDATA0.
+ * To receive data, monitor FSVPLUS0.
+ *
+ * The actual code in the vendor kernel does some things differently.
+ */
+static int __init rk3288_init_usb_uart(struct regmap *grf)
+{
+	u32 val;
+	int ret;
+
+	/*
+	 * COMMON_ON and DISABLE settings are described in the TRM,
+	 * but were not present in the original code.
+	 * Also disable the analog phy components to save power.
+	 */
+	val = HIWORD_UPDATE(RK3288_UOC0_CON0_COMMON_ON_N
+				| RK3288_UOC0_CON0_DISABLE
+				| UOC_CON0_SIDDQ,
+			    RK3288_UOC0_CON0_COMMON_ON_N
+				| RK3288_UOC0_CON0_DISABLE
+				| UOC_CON0_SIDDQ);
+	ret = regmap_write(grf, RK3288_UOC0_CON0, val);
+	if (ret)
+		return ret;
+
+	val = HIWORD_UPDATE(RK3288_UOC0_CON2_SOFT_CON_SEL,
+			    RK3288_UOC0_CON2_SOFT_CON_SEL);
+	ret = regmap_write(grf, RK3288_UOC0_CON2, val);
+	if (ret)
+		return ret;
+
+	val = HIWORD_UPDATE(RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING
+				| RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC
+				| RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED,
+			    RK3288_UOC0_CON3_UTMI_SUSPENDN
+				| RK3288_UOC0_CON3_UTMI_OPMODE_MASK
+				| RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK
+				| RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED);
+	ret = regmap_write(grf, RK3288_UOC0_CON3, val);
+	if (ret)
+		return ret;
+
+	val = HIWORD_UPDATE(RK3288_UOC0_CON3_BYPASSSEL
+				| RK3288_UOC0_CON3_BYPASSDMEN,
+			    RK3288_UOC0_CON3_BYPASSSEL
+				| RK3288_UOC0_CON3_BYPASSDMEN);
+	ret = regmap_write(grf, RK3288_UOC0_CON3, val);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static const struct rockchip_usb_phy_pdata rk3288_pdata = {
 	.phys = (struct rockchip_usb_phys[]){
 		{ .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
@@ -266,6 +371,8 @@ static const struct rockchip_usb_phy_pdata rk3288_pdata = {
 		{ .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
 		{ /* sentinel */ }
 	},
+	.init_usb_uart = rk3288_init_usb_uart,
+	.usb_uart_phy = 0,
 };
 
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
@@ -328,6 +435,58 @@ static struct platform_driver rockchip_usb_driver = {
 
 module_platform_driver(rockchip_usb_driver);
 
+static int __init rockchip_init_usb_uart(void)
+{
+	const struct of_device_id *match;
+	const struct rockchip_usb_phy_pdata *data;
+	struct device_node *np;
+	struct regmap *grf;
+	int ret;
+
+	if (!enable_usb_uart)
+		return 0;
+
+	np = of_find_matching_node_and_match(NULL, rockchip_usb_phy_dt_ids,
+					     &match);
+	if (!np) {
+		pr_err("%s: failed to find usbphy node\n", __func__);
+		return -ENOTSUPP;
+	}
+
+	pr_debug("%s: using settings for %s\n", __func__, match->compatible);
+	data = match->data;
+
+	if (!data->init_usb_uart) {
+		pr_err("%s: usb-uart not available on %s\n",
+		       __func__, match->compatible);
+		return -ENOTSUPP;
+	}
+
+	grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	if (IS_ERR(grf)) {
+		pr_err("%s: Missing rockchip,grf property, %lu\n",
+		       __func__, PTR_ERR(grf));
+		return PTR_ERR(grf);
+	}
+
+	ret = data->init_usb_uart(grf);
+	if (ret) {
+		pr_err("%s: could not init usb_uart, %d\n", __func__, ret);
+		enable_usb_uart = 0;
+		return ret;
+	}
+
+	return 0;
+}
+early_initcall(rockchip_init_usb_uart);
+
+static int __init rockchip_usb_uart(char *buf)
+{
+	enable_usb_uart = true;
+	return 0;
+}
+early_param("rockchip.usb_uart", rockchip_usb_uart);
+
 MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>");
 MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");
 MODULE_LICENSE("GPL v2");
-- 
2.6.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 8/8] phy: rockchip-usb: add handler for usb-uart functionality
@ 2015-11-19 21:22   ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-19 21:22 UTC (permalink / raw)
  To: linux-arm-kernel

Most newer Rockchip SoCs provide the possibility to use a usb-phy
as passthrough for the debug uart (uart2), making it possible to
for example get console output without needing to open the device.

This patch adds an early_initcall to enable this functionality
conditionally via the commandline and also disables the corresponding
usb controller in the devicetree.

Currently only data for the rk3288 is provided, but at least the
rk3188 and arm64 rk3368 also provide this functionality and will be
enabled later.

On a spliced usb cable the signals are tx on white wire(D+) and
rx on green wire(D-).

The one caveat is that currently the reconfiguration of the phy
happens as early_initcall, as the code depends on the unflattened
devicetree being available. Everything is fine if only a regular
console is active as the console-replay will happen after the
reconfiguation. But with earlycon active output up to smp-init
currently will get lost.

The phy is an optional property for the connected dwc2 controller,
so we still provide the phy device but fail all phy-ops with -EBUSY
to make sure the dwc2 does not try to transmit anything on the
repurposed phy.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 Documentation/kernel-parameters.txt |   6 +
 drivers/phy/phy-rockchip-usb.c      | 231 ++++++++++++++++++++++++++++++------
 2 files changed, 201 insertions(+), 36 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f8aae63..870e786 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3412,6 +3412,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
 	ro		[KNL] Mount root device read-only on boot
 
+	rockchip.usb_uart
+			Enable the uart passthrough on the designated usb port
+			on Rockchip SoCs. When active, the signals of the
+			debug-uart get routed to the D+ and D- pins of the usb
+			port and the regular usb controller gets disabled.
+
 	root=		[KNL] Root filesystem
 			See name_to_dev_t comment in init/do_mounts.c.
 
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 33a80eb..e162513 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -30,21 +30,23 @@
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
 
-/*
- * The higher 16-bit of this register is used for write protection
- * only if BIT(13 + 16) set to 1 the BIT(13) can be written.
- */
-#define SIDDQ_WRITE_ENA	BIT(29)
-#define SIDDQ_ON		BIT(13)
-#define SIDDQ_OFF		(0 << 13)
+static int enable_usb_uart;
+
+#define HIWORD_UPDATE(val, mask) \
+		((val) | (mask) << 16)
+
+#define UOC_CON0_SIDDQ BIT(13)
 
 struct rockchip_usb_phys {
 	int reg;
 	const char *pll_name;
 };
 
+struct rockchip_usb_phy_base;
 struct rockchip_usb_phy_pdata {
 	struct rockchip_usb_phys *phys;
+	int (*init_usb_uart)(struct regmap *grf);
+	int usb_uart_phy;
 };
 
 struct rockchip_usb_phy_base {
@@ -61,13 +63,15 @@ struct rockchip_usb_phy {
 	struct clk      *clk480m;
 	struct clk_hw	clk480m_hw;
 	struct phy	*phy;
+	bool		uart_enabled;
 };
 
 static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
 					   bool siddq)
 {
-	return regmap_write(phy->base->reg_base, phy->reg_offset,
-			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
+	u32 val = HIWORD_UPDATE(siddq ? UOC_CON0_SIDDQ : 0, UOC_CON0_SIDDQ);
+
+	return regmap_write(phy->base->reg_base, phy->reg_offset, val);
 }
 
 static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
@@ -108,7 +112,7 @@ static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
 	if (ret < 0)
 		return ret;
 
-	return (val & SIDDQ_ON) ? 0 : 1;
+	return (val & UOC_CON0_SIDDQ) ? 0 : 1;
 }
 
 static const struct clk_ops rockchip_usb_phy480m_ops = {
@@ -122,6 +126,9 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
 {
 	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
 
+	if (phy->uart_enabled)
+		return -EBUSY;
+
 	clk_disable_unprepare(phy->clk480m);
 
 	return 0;
@@ -131,6 +138,9 @@ static int rockchip_usb_phy_power_on(struct phy *_phy)
 {
 	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
 
+	if (phy->uart_enabled)
+		return -EBUSY;
+
 	return clk_prepare_enable(phy->clk480m);
 }
 
@@ -144,8 +154,10 @@ static void rockchip_usb_phy_action(void *data)
 {
 	struct rockchip_usb_phy *rk_phy = data;
 
-	of_clk_del_provider(rk_phy->np);
-	clk_unregister(rk_phy->clk480m);
+	if (!rk_phy->uart_enabled) {
+		of_clk_del_provider(rk_phy->np);
+		clk_unregister(rk_phy->clk480m);
+	}
 
 	if (rk_phy->clk)
 		clk_put(rk_phy->clk);
@@ -194,30 +206,35 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 		return -EINVAL;
 	}
 
-	if (rk_phy->clk) {
-		clk_name = __clk_get_name(rk_phy->clk);
-		init.flags = 0;
-		init.parent_names = &clk_name;
-		init.num_parents = 1;
+	if (enable_usb_uart && base->pdata->usb_uart_phy == i) {
+		dev_dbg(base->dev, "phy%d used as uart output\n", i);
+		rk_phy->uart_enabled = true;
 	} else {
-		init.flags = CLK_IS_ROOT;
-		init.parent_names = NULL;
-		init.num_parents = 0;
-	}
+		if (rk_phy->clk) {
+			clk_name = __clk_get_name(rk_phy->clk);
+			init.flags = 0;
+			init.parent_names = &clk_name;
+			init.num_parents = 1;
+		} else {
+			init.flags = CLK_IS_ROOT;
+			init.parent_names = NULL;
+			init.num_parents = 0;
+		}
 
-	init.ops = &rockchip_usb_phy480m_ops;
-	rk_phy->clk480m_hw.init = &init;
+		init.ops = &rockchip_usb_phy480m_ops;
+		rk_phy->clk480m_hw.init = &init;
 
-	rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
-	if (IS_ERR(rk_phy->clk480m)) {
-		err = PTR_ERR(rk_phy->clk480m);
-		goto err_clk;
-	}
+		rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
+		if (IS_ERR(rk_phy->clk480m)) {
+			err = PTR_ERR(rk_phy->clk480m);
+			goto err_clk;
+		}
 
-	err = of_clk_add_provider(child, of_clk_src_simple_get,
-				  rk_phy->clk480m);
-	if (err < 0)
-		goto err_clk_prov;
+		err = of_clk_add_provider(child, of_clk_src_simple_get,
+					rk_phy->clk480m);
+		if (err < 0)
+			goto err_clk_prov;
+	}
 
 	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
 	if (err)
@@ -230,13 +247,21 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
 	}
 	phy_set_drvdata(rk_phy->phy, rk_phy);
 
-	/* only power up usb phy when it use, so disable it when init*/
-	return rockchip_usb_phy_power(rk_phy, 1);
+	/*
+	 * When acting as uart-pipe, just keep clock on otherwise
+	 * only power up usb phy when it use, so disable it when init
+	 */
+	if (rk_phy->uart_enabled)
+		return clk_prepare_enable(rk_phy->clk);
+	else
+		return rockchip_usb_phy_power(rk_phy, 1);
 
 err_devm_action:
-	of_clk_del_provider(child);
+	if (!rk_phy->uart_enabled)
+		of_clk_del_provider(child);
 err_clk_prov:
-	clk_unregister(rk_phy->clk480m);
+	if (!rk_phy->uart_enabled)
+		clk_unregister(rk_phy->clk480m);
 err_clk:
 	if (rk_phy->clk)
 		clk_put(rk_phy->clk);
@@ -259,6 +284,86 @@ static const struct rockchip_usb_phy_pdata rk3188_pdata = {
 	},
 };
 
+#define RK3288_UOC0_CON0				0x320
+#define RK3288_UOC0_CON0_COMMON_ON_N			BIT(0)
+#define RK3288_UOC0_CON0_DISABLE			BIT(4)
+
+#define RK3288_UOC0_CON2				0x328
+#define RK3288_UOC0_CON2_SOFT_CON_SEL			BIT(2)
+
+#define RK3288_UOC0_CON3				0x32c
+#define RK3288_UOC0_CON3_UTMI_SUSPENDN			BIT(0)
+#define RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING		(1 << 1)
+#define RK3288_UOC0_CON3_UTMI_OPMODE_MASK		(3 << 1)
+#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC	(1 << 3)
+#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK		(3 << 3)
+#define RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED		BIT(5)
+#define RK3288_UOC0_CON3_BYPASSDMEN			BIT(6)
+#define RK3288_UOC0_CON3_BYPASSSEL			BIT(7)
+
+/*
+ * Enable the bypass of uart2 data through the otg usb phy.
+ * Original description in the TRM.
+ * 1. Disable the OTG block by setting OTGDISABLE0 to 1?b1.
+ * 2. Disable the pull-up resistance on the D+ line by setting
+ *    OPMODE0[1:0] to 2?b01.
+ * 3. To ensure that the XO, Bias, and PLL blocks are powered down in Suspend
+ *    mode, set COMMONONN to 1?b1.
+ * 4. Place the USB PHY in Suspend mode by setting SUSPENDM0 to 1?b0.
+ * 5. Set BYPASSSEL0 to 1?b1.
+ * 6. To transmit data, controls BYPASSDMEN0, and BYPASSDMDATA0.
+ * To receive data, monitor FSVPLUS0.
+ *
+ * The actual code in the vendor kernel does some things differently.
+ */
+static int __init rk3288_init_usb_uart(struct regmap *grf)
+{
+	u32 val;
+	int ret;
+
+	/*
+	 * COMMON_ON and DISABLE settings are described in the TRM,
+	 * but were not present in the original code.
+	 * Also disable the analog phy components to save power.
+	 */
+	val = HIWORD_UPDATE(RK3288_UOC0_CON0_COMMON_ON_N
+				| RK3288_UOC0_CON0_DISABLE
+				| UOC_CON0_SIDDQ,
+			    RK3288_UOC0_CON0_COMMON_ON_N
+				| RK3288_UOC0_CON0_DISABLE
+				| UOC_CON0_SIDDQ);
+	ret = regmap_write(grf, RK3288_UOC0_CON0, val);
+	if (ret)
+		return ret;
+
+	val = HIWORD_UPDATE(RK3288_UOC0_CON2_SOFT_CON_SEL,
+			    RK3288_UOC0_CON2_SOFT_CON_SEL);
+	ret = regmap_write(grf, RK3288_UOC0_CON2, val);
+	if (ret)
+		return ret;
+
+	val = HIWORD_UPDATE(RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING
+				| RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC
+				| RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED,
+			    RK3288_UOC0_CON3_UTMI_SUSPENDN
+				| RK3288_UOC0_CON3_UTMI_OPMODE_MASK
+				| RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK
+				| RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED);
+	ret = regmap_write(grf, RK3288_UOC0_CON3, val);
+	if (ret)
+		return ret;
+
+	val = HIWORD_UPDATE(RK3288_UOC0_CON3_BYPASSSEL
+				| RK3288_UOC0_CON3_BYPASSDMEN,
+			    RK3288_UOC0_CON3_BYPASSSEL
+				| RK3288_UOC0_CON3_BYPASSDMEN);
+	ret = regmap_write(grf, RK3288_UOC0_CON3, val);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static const struct rockchip_usb_phy_pdata rk3288_pdata = {
 	.phys = (struct rockchip_usb_phys[]){
 		{ .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
@@ -266,6 +371,8 @@ static const struct rockchip_usb_phy_pdata rk3288_pdata = {
 		{ .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
 		{ /* sentinel */ }
 	},
+	.init_usb_uart = rk3288_init_usb_uart,
+	.usb_uart_phy = 0,
 };
 
 static int rockchip_usb_phy_probe(struct platform_device *pdev)
@@ -328,6 +435,58 @@ static struct platform_driver rockchip_usb_driver = {
 
 module_platform_driver(rockchip_usb_driver);
 
+static int __init rockchip_init_usb_uart(void)
+{
+	const struct of_device_id *match;
+	const struct rockchip_usb_phy_pdata *data;
+	struct device_node *np;
+	struct regmap *grf;
+	int ret;
+
+	if (!enable_usb_uart)
+		return 0;
+
+	np = of_find_matching_node_and_match(NULL, rockchip_usb_phy_dt_ids,
+					     &match);
+	if (!np) {
+		pr_err("%s: failed to find usbphy node\n", __func__);
+		return -ENOTSUPP;
+	}
+
+	pr_debug("%s: using settings for %s\n", __func__, match->compatible);
+	data = match->data;
+
+	if (!data->init_usb_uart) {
+		pr_err("%s: usb-uart not available on %s\n",
+		       __func__, match->compatible);
+		return -ENOTSUPP;
+	}
+
+	grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	if (IS_ERR(grf)) {
+		pr_err("%s: Missing rockchip,grf property, %lu\n",
+		       __func__, PTR_ERR(grf));
+		return PTR_ERR(grf);
+	}
+
+	ret = data->init_usb_uart(grf);
+	if (ret) {
+		pr_err("%s: could not init usb_uart, %d\n", __func__, ret);
+		enable_usb_uart = 0;
+		return ret;
+	}
+
+	return 0;
+}
+early_initcall(rockchip_init_usb_uart);
+
+static int __init rockchip_usb_uart(char *buf)
+{
+	enable_usb_uart = true;
+	return 0;
+}
+early_param("rockchip.usb_uart", rockchip_usb_uart);
+
 MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>");
 MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");
 MODULE_LICENSE("GPL v2");
-- 
2.6.2

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
  2015-11-19 21:22   ` Heiko Stuebner
  (?)
@ 2015-11-20  0:32     ` Doug Anderson
  -1 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-20  0:32 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Heiko,

On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> We need custom handling for these two socs in the driver shortly,
> so add the necessary compatible values to binding and driver.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
>  drivers/phy/phy-rockchip-usb.c                             | 2 ++
>  2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> index 826454a..9b37242 100644
> --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> @@ -1,7 +1,10 @@
>  ROCKCHIP USB2 PHY
>
>  Required properties:
> - - compatible: rockchip,rk3288-usb-phy
> + - compatible: matching the soc type, one of
> +     "rockchip,rk3066a-usb-phy"
> +     "rockchip,rk3188-usb-phy"
> +     "rockchip,rk3288-usb-phy"

I can never quite keep it straight how this is supposed to work, but
since previously only "rockchip,rk3288-usb-phy" was supported and now
we have these new compatible strings, I would have expected the new
strings to specify the old ones as fallback.  That would mean your
choices would be:

- "rockchip,rk3288-usb-phy" - A real rk3288
- "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
fallback to 3288 driver.
- "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
with fallback to 3288 driver.

That means that if you land the dts changes without the driver changes
that things still work OK.

-Doug

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-20  0:32     ` Doug Anderson
  0 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-20  0:32 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Heiko,

On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> We need custom handling for these two socs in the driver shortly,
> so add the necessary compatible values to binding and driver.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
>  drivers/phy/phy-rockchip-usb.c                             | 2 ++
>  2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> index 826454a..9b37242 100644
> --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> @@ -1,7 +1,10 @@
>  ROCKCHIP USB2 PHY
>
>  Required properties:
> - - compatible: rockchip,rk3288-usb-phy
> + - compatible: matching the soc type, one of
> +     "rockchip,rk3066a-usb-phy"
> +     "rockchip,rk3188-usb-phy"
> +     "rockchip,rk3288-usb-phy"

I can never quite keep it straight how this is supposed to work, but
since previously only "rockchip,rk3288-usb-phy" was supported and now
we have these new compatible strings, I would have expected the new
strings to specify the old ones as fallback.  That would mean your
choices would be:

- "rockchip,rk3288-usb-phy" - A real rk3288
- "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
fallback to 3288 driver.
- "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
with fallback to 3288 driver.

That means that if you land the dts changes without the driver changes
that things still work OK.

-Doug

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-20  0:32     ` Doug Anderson
  0 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-20  0:32 UTC (permalink / raw)
  To: linux-arm-kernel

Heiko,

On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> We need custom handling for these two socs in the driver shortly,
> so add the necessary compatible values to binding and driver.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
>  drivers/phy/phy-rockchip-usb.c                             | 2 ++
>  2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> index 826454a..9b37242 100644
> --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> @@ -1,7 +1,10 @@
>  ROCKCHIP USB2 PHY
>
>  Required properties:
> - - compatible: rockchip,rk3288-usb-phy
> + - compatible: matching the soc type, one of
> +     "rockchip,rk3066a-usb-phy"
> +     "rockchip,rk3188-usb-phy"
> +     "rockchip,rk3288-usb-phy"

I can never quite keep it straight how this is supposed to work, but
since previously only "rockchip,rk3288-usb-phy" was supported and now
we have these new compatible strings, I would have expected the new
strings to specify the old ones as fallback.  That would mean your
choices would be:

- "rockchip,rk3288-usb-phy" - A real rk3288
- "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
fallback to 3288 driver.
- "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
with fallback to 3288 driver.

That means that if you land the dts changes without the driver changes
that things still work OK.

-Doug

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 2/8] phy: rockchip-usb: introduce a common data-struct for the device
  2015-11-19 21:22   ` Heiko Stuebner
  (?)
@ 2015-11-20  0:38     ` Doug Anderson
  -1 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-20  0:38 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Heiko,

On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> This introduces a common struct that holds data belonging to
> the umbrella device that contains all the phys and that we
> want to use later.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  drivers/phy/phy-rockchip-usb.c | 26 +++++++++++++++++++-------
>  1 file changed, 19 insertions(+), 7 deletions(-)

Huh, apparently in my whole talk about bindings I forgot my review
last time.  :(

Reviewed-by: Douglas Anderson <dianders@chromium.org>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 2/8] phy: rockchip-usb: introduce a common data-struct for the device
@ 2015-11-20  0:38     ` Doug Anderson
  0 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-20  0:38 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Heiko,

On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> This introduces a common struct that holds data belonging to
> the umbrella device that contains all the phys and that we
> want to use later.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  drivers/phy/phy-rockchip-usb.c | 26 +++++++++++++++++++-------
>  1 file changed, 19 insertions(+), 7 deletions(-)

Huh, apparently in my whole talk about bindings I forgot my review
last time.  :(

Reviewed-by: Douglas Anderson <dianders@chromium.org>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 2/8] phy: rockchip-usb: introduce a common data-struct for the device
@ 2015-11-20  0:38     ` Doug Anderson
  0 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-20  0:38 UTC (permalink / raw)
  To: linux-arm-kernel

Heiko,

On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> This introduces a common struct that holds data belonging to
> the umbrella device that contains all the phys and that we
> want to use later.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  drivers/phy/phy-rockchip-usb.c | 26 +++++++++++++++++++-------
>  1 file changed, 19 insertions(+), 7 deletions(-)

Huh, apparently in my whole talk about bindings I forgot my review
last time.  :(

Reviewed-by: Douglas Anderson <dianders@chromium.org>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
  2015-11-20  0:32     ` Doug Anderson
  (?)
@ 2015-11-22 19:49       ` Heiko Stuebner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-22 19:49 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
> Heiko,
> 
> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> > We need custom handling for these two socs in the driver shortly,
> > so add the necessary compatible values to binding and driver.
> >
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
> >  2 files changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt 
b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > index 826454a..9b37242 100644
> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > @@ -1,7 +1,10 @@
> >  ROCKCHIP USB2 PHY
> >
> >  Required properties:
> > - - compatible: rockchip,rk3288-usb-phy
> > + - compatible: matching the soc type, one of
> > +     "rockchip,rk3066a-usb-phy"
> > +     "rockchip,rk3188-usb-phy"
> > +     "rockchip,rk3288-usb-phy"
> 
> I can never quite keep it straight how this is supposed to work, but
> since previously only "rockchip,rk3288-usb-phy" was supported and now
> we have these new compatible strings, I would have expected the new
> strings to specify the old ones as fallback.  That would mean your
> choices would be:
> 
> - "rockchip,rk3288-usb-phy" - A real rk3288
> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
> fallback to 3288 driver.
> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
> with fallback to 3288 driver.

How this is supposed to be done also is sometimes confusing for me :-)

But I don't think that specifying the "fallbacks" is part of the binding at 
all, when the binding really is done in a soc-specific way.  For example 
following the suggestion of the dt-maintainers at the time we're specifying 
the uarts as

	compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"

as a measure to use a more-special driver if there is ever the need for it. 
But here the "snps,dw-apb-uart" actually is a superset (a more generic 
implementation), while in the usb-uart-case


> That means that if you land the dts changes without the driver changes
> that things still work OK.

We already have the alternative for the usb-phys in the devicetree, but I 
still don't think that this alternative is part of the binding itself :-)


Heiko

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-22 19:49       ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-22 19:49 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
> Heiko,
> 
> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> > We need custom handling for these two socs in the driver shortly,
> > so add the necessary compatible values to binding and driver.
> >
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
> >  2 files changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt 
b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > index 826454a..9b37242 100644
> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > @@ -1,7 +1,10 @@
> >  ROCKCHIP USB2 PHY
> >
> >  Required properties:
> > - - compatible: rockchip,rk3288-usb-phy
> > + - compatible: matching the soc type, one of
> > +     "rockchip,rk3066a-usb-phy"
> > +     "rockchip,rk3188-usb-phy"
> > +     "rockchip,rk3288-usb-phy"
> 
> I can never quite keep it straight how this is supposed to work, but
> since previously only "rockchip,rk3288-usb-phy" was supported and now
> we have these new compatible strings, I would have expected the new
> strings to specify the old ones as fallback.  That would mean your
> choices would be:
> 
> - "rockchip,rk3288-usb-phy" - A real rk3288
> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
> fallback to 3288 driver.
> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
> with fallback to 3288 driver.

How this is supposed to be done also is sometimes confusing for me :-)

But I don't think that specifying the "fallbacks" is part of the binding at 
all, when the binding really is done in a soc-specific way.  For example 
following the suggestion of the dt-maintainers at the time we're specifying 
the uarts as

	compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"

as a measure to use a more-special driver if there is ever the need for it. 
But here the "snps,dw-apb-uart" actually is a superset (a more generic 
implementation), while in the usb-uart-case


> That means that if you land the dts changes without the driver changes
> that things still work OK.

We already have the alternative for the usb-phys in the devicetree, but I 
still don't think that this alternative is part of the binding itself :-)


Heiko

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-22 19:49       ` Heiko Stuebner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stuebner @ 2015-11-22 19:49 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
> Heiko,
> 
> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> > We need custom handling for these two socs in the driver shortly,
> > so add the necessary compatible values to binding and driver.
> >
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
> >  2 files changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt 
b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > index 826454a..9b37242 100644
> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > @@ -1,7 +1,10 @@
> >  ROCKCHIP USB2 PHY
> >
> >  Required properties:
> > - - compatible: rockchip,rk3288-usb-phy
> > + - compatible: matching the soc type, one of
> > +     "rockchip,rk3066a-usb-phy"
> > +     "rockchip,rk3188-usb-phy"
> > +     "rockchip,rk3288-usb-phy"
> 
> I can never quite keep it straight how this is supposed to work, but
> since previously only "rockchip,rk3288-usb-phy" was supported and now
> we have these new compatible strings, I would have expected the new
> strings to specify the old ones as fallback.  That would mean your
> choices would be:
> 
> - "rockchip,rk3288-usb-phy" - A real rk3288
> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
> fallback to 3288 driver.
> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
> with fallback to 3288 driver.

How this is supposed to be done also is sometimes confusing for me :-)

But I don't think that specifying the "fallbacks" is part of the binding at 
all, when the binding really is done in a soc-specific way.  For example 
following the suggestion of the dt-maintainers at the time we're specifying 
the uarts as

	compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"

as a measure to use a more-special driver if there is ever the need for it. 
But here the "snps,dw-apb-uart" actually is a superset (a more generic 
implementation), while in the usb-uart-case


> That means that if you land the dts changes without the driver changes
> that things still work OK.

We already have the alternative for the usb-phys in the devicetree, but I 
still don't think that this alternative is part of the binding itself :-)


Heiko

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
  2015-11-22 19:49       ` Heiko Stuebner
  (?)
@ 2015-11-25 17:04         ` Doug Anderson
  -1 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-25 17:04 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Hi,

On Sun, Nov 22, 2015 at 11:49 AM, Heiko Stuebner <heiko@sntech.de> wrote:
> Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
>> Heiko,
>>
>> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
>> > We need custom handling for these two socs in the driver shortly,
>> > so add the necessary compatible values to binding and driver.
>> >
>> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> > ---
>> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
>> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
>> >  2 files changed, 6 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> > index 826454a..9b37242 100644
>> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> > @@ -1,7 +1,10 @@
>> >  ROCKCHIP USB2 PHY
>> >
>> >  Required properties:
>> > - - compatible: rockchip,rk3288-usb-phy
>> > + - compatible: matching the soc type, one of
>> > +     "rockchip,rk3066a-usb-phy"
>> > +     "rockchip,rk3188-usb-phy"
>> > +     "rockchip,rk3288-usb-phy"
>>
>> I can never quite keep it straight how this is supposed to work, but
>> since previously only "rockchip,rk3288-usb-phy" was supported and now
>> we have these new compatible strings, I would have expected the new
>> strings to specify the old ones as fallback.  That would mean your
>> choices would be:
>>
>> - "rockchip,rk3288-usb-phy" - A real rk3288
>> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
>> fallback to 3288 driver.
>> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
>> with fallback to 3288 driver.
>
> How this is supposed to be done also is sometimes confusing for me :-)
>
> But I don't think that specifying the "fallbacks" is part of the binding at
> all, when the binding really is done in a soc-specific way.  For example
> following the suggestion of the dt-maintainers at the time we're specifying
> the uarts as
>
>         compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"
>
> as a measure to use a more-special driver if there is ever the need for it.
> But here the "snps,dw-apb-uart" actually is a superset (a more generic
> implementation), while in the usb-uart-case

Hrm, this gets into the whole issue of coming up with generic names.
It's not always easy, especially when marketing gets involved.  If
Synopsis comes up with a new APB UART that's not compatible, I guess
you call it a v2 and people just need to figure out which one they
have?  I remember it being terribly confusing with exynos since
Samsung called things "exynos" that were very different, and I think
even "exynos5" devices were pretty different form each other.  Anyway,
that's getting pretty far afield.

The general way of doing things in Linux is that the first driver
there becomes the generic, right?  So if the first supported SoC using
this PHY was rk3288 then it gets the name and becomes the generic.  If
rk3066a and 3188 are 90% the same and initially can actually use the
same driver, then they specify the specific "3188" and the generic
"3288" as a fallback.  It sounds like that was what was actually done
in the DTS files anyway, which is right as far as I'm concerned.

...but personally I'd love to see it documented.  ...someone reading
the binding should be able to create a DTS and it's not obvious from
the DTS that "rk3288" is the generic as far as this binding is
concerned.

Quite honestly, though, it's not terribly important to me and
definitely not something I feel like I can make a call on.  If you
feel strongly about keeping it the way you have it and nobody else has
any objections, I won't yell.

-Doug

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-25 17:04         ` Doug Anderson
  0 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-25 17:04 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Hi,

On Sun, Nov 22, 2015 at 11:49 AM, Heiko Stuebner <heiko@sntech.de> wrote:
> Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
>> Heiko,
>>
>> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
>> > We need custom handling for these two socs in the driver shortly,
>> > so add the necessary compatible values to binding and driver.
>> >
>> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> > ---
>> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
>> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
>> >  2 files changed, 6 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> > index 826454a..9b37242 100644
>> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> > @@ -1,7 +1,10 @@
>> >  ROCKCHIP USB2 PHY
>> >
>> >  Required properties:
>> > - - compatible: rockchip,rk3288-usb-phy
>> > + - compatible: matching the soc type, one of
>> > +     "rockchip,rk3066a-usb-phy"
>> > +     "rockchip,rk3188-usb-phy"
>> > +     "rockchip,rk3288-usb-phy"
>>
>> I can never quite keep it straight how this is supposed to work, but
>> since previously only "rockchip,rk3288-usb-phy" was supported and now
>> we have these new compatible strings, I would have expected the new
>> strings to specify the old ones as fallback.  That would mean your
>> choices would be:
>>
>> - "rockchip,rk3288-usb-phy" - A real rk3288
>> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
>> fallback to 3288 driver.
>> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
>> with fallback to 3288 driver.
>
> How this is supposed to be done also is sometimes confusing for me :-)
>
> But I don't think that specifying the "fallbacks" is part of the binding at
> all, when the binding really is done in a soc-specific way.  For example
> following the suggestion of the dt-maintainers at the time we're specifying
> the uarts as
>
>         compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"
>
> as a measure to use a more-special driver if there is ever the need for it.
> But here the "snps,dw-apb-uart" actually is a superset (a more generic
> implementation), while in the usb-uart-case

Hrm, this gets into the whole issue of coming up with generic names.
It's not always easy, especially when marketing gets involved.  If
Synopsis comes up with a new APB UART that's not compatible, I guess
you call it a v2 and people just need to figure out which one they
have?  I remember it being terribly confusing with exynos since
Samsung called things "exynos" that were very different, and I think
even "exynos5" devices were pretty different form each other.  Anyway,
that's getting pretty far afield.

The general way of doing things in Linux is that the first driver
there becomes the generic, right?  So if the first supported SoC using
this PHY was rk3288 then it gets the name and becomes the generic.  If
rk3066a and 3188 are 90% the same and initially can actually use the
same driver, then they specify the specific "3188" and the generic
"3288" as a fallback.  It sounds like that was what was actually done
in the DTS files anyway, which is right as far as I'm concerned.

...but personally I'd love to see it documented.  ...someone reading
the binding should be able to create a DTS and it's not obvious from
the DTS that "rk3288" is the generic as far as this binding is
concerned.

Quite honestly, though, it's not terribly important to me and
definitely not something I feel like I can make a call on.  If you
feel strongly about keeping it the way you have it and nobody else has
any objections, I won't yell.

-Doug

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-25 17:04         ` Doug Anderson
  0 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-25 17:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Sun, Nov 22, 2015 at 11:49 AM, Heiko Stuebner <heiko@sntech.de> wrote:
> Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
>> Heiko,
>>
>> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
>> > We need custom handling for these two socs in the driver shortly,
>> > so add the necessary compatible values to binding and driver.
>> >
>> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> > ---
>> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
>> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
>> >  2 files changed, 6 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> > index 826454a..9b37242 100644
>> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> > @@ -1,7 +1,10 @@
>> >  ROCKCHIP USB2 PHY
>> >
>> >  Required properties:
>> > - - compatible: rockchip,rk3288-usb-phy
>> > + - compatible: matching the soc type, one of
>> > +     "rockchip,rk3066a-usb-phy"
>> > +     "rockchip,rk3188-usb-phy"
>> > +     "rockchip,rk3288-usb-phy"
>>
>> I can never quite keep it straight how this is supposed to work, but
>> since previously only "rockchip,rk3288-usb-phy" was supported and now
>> we have these new compatible strings, I would have expected the new
>> strings to specify the old ones as fallback.  That would mean your
>> choices would be:
>>
>> - "rockchip,rk3288-usb-phy" - A real rk3288
>> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
>> fallback to 3288 driver.
>> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
>> with fallback to 3288 driver.
>
> How this is supposed to be done also is sometimes confusing for me :-)
>
> But I don't think that specifying the "fallbacks" is part of the binding at
> all, when the binding really is done in a soc-specific way.  For example
> following the suggestion of the dt-maintainers at the time we're specifying
> the uarts as
>
>         compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"
>
> as a measure to use a more-special driver if there is ever the need for it.
> But here the "snps,dw-apb-uart" actually is a superset (a more generic
> implementation), while in the usb-uart-case

Hrm, this gets into the whole issue of coming up with generic names.
It's not always easy, especially when marketing gets involved.  If
Synopsis comes up with a new APB UART that's not compatible, I guess
you call it a v2 and people just need to figure out which one they
have?  I remember it being terribly confusing with exynos since
Samsung called things "exynos" that were very different, and I think
even "exynos5" devices were pretty different form each other.  Anyway,
that's getting pretty far afield.

The general way of doing things in Linux is that the first driver
there becomes the generic, right?  So if the first supported SoC using
this PHY was rk3288 then it gets the name and becomes the generic.  If
rk3066a and 3188 are 90% the same and initially can actually use the
same driver, then they specify the specific "3188" and the generic
"3288" as a fallback.  It sounds like that was what was actually done
in the DTS files anyway, which is right as far as I'm concerned.

...but personally I'd love to see it documented.  ...someone reading
the binding should be able to create a DTS and it's not obvious from
the DTS that "rk3288" is the generic as far as this binding is
concerned.

Quite honestly, though, it's not terribly important to me and
definitely not something I feel like I can make a call on.  If you
feel strongly about keeping it the way you have it and nobody else has
any objections, I won't yell.

-Doug

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
  2015-11-25 17:04         ` Doug Anderson
  (?)
@ 2015-11-25 18:24           ` Heiko Stübner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2015-11-25 18:24 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Am Mittwoch, 25. November 2015, 09:04:19 schrieb Doug Anderson:
> Hi,
> 
> On Sun, Nov 22, 2015 at 11:49 AM, Heiko Stuebner <heiko@sntech.de> wrote:
> > Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
> >> Heiko,
> >> 
> >> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> >> > We need custom handling for these two socs in the driver shortly,
> >> > so add the necessary compatible values to binding and driver.
> >> > 
> >> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> >> > ---
> >> > 
> >> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
> >> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
> >> >  2 files changed, 6 insertions(+), 1 deletion(-)
> >> > 
> >> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > 
> > b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > 
> >> > index 826454a..9b37242 100644
> >> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> >> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> >> > @@ -1,7 +1,10 @@
> >> > 
> >> >  ROCKCHIP USB2 PHY
> >> > 
> >> >  Required properties:
> >> > - - compatible: rockchip,rk3288-usb-phy
> >> > + - compatible: matching the soc type, one of
> >> > +     "rockchip,rk3066a-usb-phy"
> >> > +     "rockchip,rk3188-usb-phy"
> >> > +     "rockchip,rk3288-usb-phy"
> >> 
> >> I can never quite keep it straight how this is supposed to work, but
> >> since previously only "rockchip,rk3288-usb-phy" was supported and now
> >> we have these new compatible strings, I would have expected the new
> >> strings to specify the old ones as fallback.  That would mean your
> >> choices would be:
> >> 
> >> - "rockchip,rk3288-usb-phy" - A real rk3288
> >> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
> >> fallback to 3288 driver.
> >> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
> >> with fallback to 3288 driver.
> > 
> > How this is supposed to be done also is sometimes confusing for me :-)
> > 
> > But I don't think that specifying the "fallbacks" is part of the binding
> > at
> > all, when the binding really is done in a soc-specific way.  For example
> > following the suggestion of the dt-maintainers at the time we're
> > specifying
> > the uarts as
> > 
> >         compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"
> > 
> > as a measure to use a more-special driver if there is ever the need for
> > it.
> > But here the "snps,dw-apb-uart" actually is a superset (a more generic
> > implementation), while in the usb-uart-case
> 
> Hrm, this gets into the whole issue of coming up with generic names.
> It's not always easy, especially when marketing gets involved.  If
> Synopsis comes up with a new APB UART that's not compatible, I guess
> you call it a v2 and people just need to figure out which one they
> have?  I remember it being terribly confusing with exynos since
> Samsung called things "exynos" that were very different, and I think
> even "exynos5" devices were pretty different form each other.  Anyway,
> that's getting pretty far afield.
> 
> The general way of doing things in Linux is that the first driver
> there becomes the generic, right?  So if the first supported SoC using
> this PHY was rk3288 then it gets the name and becomes the generic. If
> rk3066a and 3188 are 90% the same and initially can actually use the
> same driver, then they specify the specific "3188" and the generic
> "3288" as a fallback.  It sounds like that was what was actually done
> in the DTS files anyway, which is right as far as I'm concerned.
> 
> ...but personally I'd love to see it documented.  ...someone reading
> the binding should be able to create a DTS and it's not obvious from
> the DTS that "rk3288" is the generic as far as this binding is
> concerned.

I'd like to disagree here :-)

Generic is actually currently "rockchip-usb-phy", the platform-driver name, 
but thankfully that hasn't leaked into the dts, as even that name + filename 
should change in the future. What rk3288 (and before) uses is a Designware 
picophy with custom registers in the grf, so it should actually be
"rockchip-usb-picophy" or so. Following socs use a different IP (Innosilicon 
if I remember correctly), with different clock/pll handling and a whole 
different set of registers, so will get a new driver.

In terms of hardware compatibility, the phys aren't actually compatible, it's 
only per chance that the used SIDDQ bit has the same position on all socs :-)
Everything else seems to move around quite happily in the registers.


As it stands now, the rk3188 dts has a compatible of 
"rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy", matching the usable 
[refraining from calling it generic] driver on old kernels, while now it is 
supposed to match the actually correct rk3188 variant. So that combination 
works with the same dts on both old and new kernels fullfilling the ABI-
stability promise.

With the new matching code (clock-names etc) you actually get issues if you 
try to match against "rockchip,rk3288-usb-phy" on a rk3188, so there is no 
"generic" part. And that difference will widen if we need to control other 
parts of the usb-phy as well.

So essentially that second property should go completely, I just didn't wanted 
to create the impression of changing the ABI here ;-)


Sorry for that wall of text.

Heiko


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-25 18:24           ` Heiko Stübner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2015-11-25 18:24 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Am Mittwoch, 25. November 2015, 09:04:19 schrieb Doug Anderson:
> Hi,
> 
> On Sun, Nov 22, 2015 at 11:49 AM, Heiko Stuebner <heiko@sntech.de> wrote:
> > Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
> >> Heiko,
> >> 
> >> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> >> > We need custom handling for these two socs in the driver shortly,
> >> > so add the necessary compatible values to binding and driver.
> >> > 
> >> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> >> > ---
> >> > 
> >> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
> >> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
> >> >  2 files changed, 6 insertions(+), 1 deletion(-)
> >> > 
> >> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > 
> > b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > 
> >> > index 826454a..9b37242 100644
> >> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> >> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> >> > @@ -1,7 +1,10 @@
> >> > 
> >> >  ROCKCHIP USB2 PHY
> >> > 
> >> >  Required properties:
> >> > - - compatible: rockchip,rk3288-usb-phy
> >> > + - compatible: matching the soc type, one of
> >> > +     "rockchip,rk3066a-usb-phy"
> >> > +     "rockchip,rk3188-usb-phy"
> >> > +     "rockchip,rk3288-usb-phy"
> >> 
> >> I can never quite keep it straight how this is supposed to work, but
> >> since previously only "rockchip,rk3288-usb-phy" was supported and now
> >> we have these new compatible strings, I would have expected the new
> >> strings to specify the old ones as fallback.  That would mean your
> >> choices would be:
> >> 
> >> - "rockchip,rk3288-usb-phy" - A real rk3288
> >> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
> >> fallback to 3288 driver.
> >> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
> >> with fallback to 3288 driver.
> > 
> > How this is supposed to be done also is sometimes confusing for me :-)
> > 
> > But I don't think that specifying the "fallbacks" is part of the binding
> > at
> > all, when the binding really is done in a soc-specific way.  For example
> > following the suggestion of the dt-maintainers at the time we're
> > specifying
> > the uarts as
> > 
> >         compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"
> > 
> > as a measure to use a more-special driver if there is ever the need for
> > it.
> > But here the "snps,dw-apb-uart" actually is a superset (a more generic
> > implementation), while in the usb-uart-case
> 
> Hrm, this gets into the whole issue of coming up with generic names.
> It's not always easy, especially when marketing gets involved.  If
> Synopsis comes up with a new APB UART that's not compatible, I guess
> you call it a v2 and people just need to figure out which one they
> have?  I remember it being terribly confusing with exynos since
> Samsung called things "exynos" that were very different, and I think
> even "exynos5" devices were pretty different form each other.  Anyway,
> that's getting pretty far afield.
> 
> The general way of doing things in Linux is that the first driver
> there becomes the generic, right?  So if the first supported SoC using
> this PHY was rk3288 then it gets the name and becomes the generic. If
> rk3066a and 3188 are 90% the same and initially can actually use the
> same driver, then they specify the specific "3188" and the generic
> "3288" as a fallback.  It sounds like that was what was actually done
> in the DTS files anyway, which is right as far as I'm concerned.
> 
> ...but personally I'd love to see it documented.  ...someone reading
> the binding should be able to create a DTS and it's not obvious from
> the DTS that "rk3288" is the generic as far as this binding is
> concerned.

I'd like to disagree here :-)

Generic is actually currently "rockchip-usb-phy", the platform-driver name, 
but thankfully that hasn't leaked into the dts, as even that name + filename 
should change in the future. What rk3288 (and before) uses is a Designware 
picophy with custom registers in the grf, so it should actually be
"rockchip-usb-picophy" or so. Following socs use a different IP (Innosilicon 
if I remember correctly), with different clock/pll handling and a whole 
different set of registers, so will get a new driver.

In terms of hardware compatibility, the phys aren't actually compatible, it's 
only per chance that the used SIDDQ bit has the same position on all socs :-)
Everything else seems to move around quite happily in the registers.


As it stands now, the rk3188 dts has a compatible of 
"rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy", matching the usable 
[refraining from calling it generic] driver on old kernels, while now it is 
supposed to match the actually correct rk3188 variant. So that combination 
works with the same dts on both old and new kernels fullfilling the ABI-
stability promise.

With the new matching code (clock-names etc) you actually get issues if you 
try to match against "rockchip,rk3288-usb-phy" on a rk3188, so there is no 
"generic" part. And that difference will widen if we need to control other 
parts of the usb-phy as well.

So essentially that second property should go completely, I just didn't wanted 
to create the impression of changing the ABI here ;-)


Sorry for that wall of text.

Heiko

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-25 18:24           ` Heiko Stübner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2015-11-25 18:24 UTC (permalink / raw)
  To: linux-arm-kernel

Am Mittwoch, 25. November 2015, 09:04:19 schrieb Doug Anderson:
> Hi,
> 
> On Sun, Nov 22, 2015 at 11:49 AM, Heiko Stuebner <heiko@sntech.de> wrote:
> > Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
> >> Heiko,
> >> 
> >> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
> >> > We need custom handling for these two socs in the driver shortly,
> >> > so add the necessary compatible values to binding and driver.
> >> > 
> >> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> >> > ---
> >> > 
> >> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
> >> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
> >> >  2 files changed, 6 insertions(+), 1 deletion(-)
> >> > 
> >> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > 
> > b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> > 
> >> > index 826454a..9b37242 100644
> >> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> >> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> >> > @@ -1,7 +1,10 @@
> >> > 
> >> >  ROCKCHIP USB2 PHY
> >> > 
> >> >  Required properties:
> >> > - - compatible: rockchip,rk3288-usb-phy
> >> > + - compatible: matching the soc type, one of
> >> > +     "rockchip,rk3066a-usb-phy"
> >> > +     "rockchip,rk3188-usb-phy"
> >> > +     "rockchip,rk3288-usb-phy"
> >> 
> >> I can never quite keep it straight how this is supposed to work, but
> >> since previously only "rockchip,rk3288-usb-phy" was supported and now
> >> we have these new compatible strings, I would have expected the new
> >> strings to specify the old ones as fallback.  That would mean your
> >> choices would be:
> >> 
> >> - "rockchip,rk3288-usb-phy" - A real rk3288
> >> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
> >> fallback to 3288 driver.
> >> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
> >> with fallback to 3288 driver.
> > 
> > How this is supposed to be done also is sometimes confusing for me :-)
> > 
> > But I don't think that specifying the "fallbacks" is part of the binding
> > at
> > all, when the binding really is done in a soc-specific way.  For example
> > following the suggestion of the dt-maintainers at the time we're
> > specifying
> > the uarts as
> > 
> >         compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"
> > 
> > as a measure to use a more-special driver if there is ever the need for
> > it.
> > But here the "snps,dw-apb-uart" actually is a superset (a more generic
> > implementation), while in the usb-uart-case
> 
> Hrm, this gets into the whole issue of coming up with generic names.
> It's not always easy, especially when marketing gets involved.  If
> Synopsis comes up with a new APB UART that's not compatible, I guess
> you call it a v2 and people just need to figure out which one they
> have?  I remember it being terribly confusing with exynos since
> Samsung called things "exynos" that were very different, and I think
> even "exynos5" devices were pretty different form each other.  Anyway,
> that's getting pretty far afield.
> 
> The general way of doing things in Linux is that the first driver
> there becomes the generic, right?  So if the first supported SoC using
> this PHY was rk3288 then it gets the name and becomes the generic. If
> rk3066a and 3188 are 90% the same and initially can actually use the
> same driver, then they specify the specific "3188" and the generic
> "3288" as a fallback.  It sounds like that was what was actually done
> in the DTS files anyway, which is right as far as I'm concerned.
> 
> ...but personally I'd love to see it documented.  ...someone reading
> the binding should be able to create a DTS and it's not obvious from
> the DTS that "rk3288" is the generic as far as this binding is
> concerned.

I'd like to disagree here :-)

Generic is actually currently "rockchip-usb-phy", the platform-driver name, 
but thankfully that hasn't leaked into the dts, as even that name + filename 
should change in the future. What rk3288 (and before) uses is a Designware 
picophy with custom registers in the grf, so it should actually be
"rockchip-usb-picophy" or so. Following socs use a different IP (Innosilicon 
if I remember correctly), with different clock/pll handling and a whole 
different set of registers, so will get a new driver.

In terms of hardware compatibility, the phys aren't actually compatible, it's 
only per chance that the used SIDDQ bit has the same position on all socs :-)
Everything else seems to move around quite happily in the registers.


As it stands now, the rk3188 dts has a compatible of 
"rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy", matching the usable 
[refraining from calling it generic] driver on old kernels, while now it is 
supposed to match the actually correct rk3188 variant. So that combination 
works with the same dts on both old and new kernels fullfilling the ABI-
stability promise.

With the new matching code (clock-names etc) you actually get issues if you 
try to match against "rockchip,rk3288-usb-phy" on a rk3188, so there is no 
"generic" part. And that difference will widen if we need to control other 
parts of the usb-phy as well.

So essentially that second property should go completely, I just didn't wanted 
to create the impression of changing the ABI here ;-)


Sorry for that wall of text.

Heiko

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
  2015-11-25 18:24           ` Heiko Stübner
  (?)
@ 2015-11-25 18:35             ` Doug Anderson
  -1 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-25 18:35 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
	linux-arm-kernel, linux-kernel, open list:ARM/Rockchip SoC...,
	Romain Perier, Arnd Bergmann, Lin Huang

Hi,

On Wed, Nov 25, 2015 at 10:24 AM, Heiko Stübner <heiko@sntech.de> wrote:
> Am Mittwoch, 25. November 2015, 09:04:19 schrieb Doug Anderson:
>> Hi,
>>
>> On Sun, Nov 22, 2015 at 11:49 AM, Heiko Stuebner <heiko@sntech.de> wrote:
>> > Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
>> >> Heiko,
>> >>
>> >> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
>> >> > We need custom handling for these two socs in the driver shortly,
>> >> > so add the necessary compatible values to binding and driver.
>> >> >
>> >> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> >> > ---
>> >> >
>> >> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
>> >> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
>> >> >  2 files changed, 6 insertions(+), 1 deletion(-)
>> >> >
>> >> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >
>> > b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >
>> >> > index 826454a..9b37242 100644
>> >> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >> > @@ -1,7 +1,10 @@
>> >> >
>> >> >  ROCKCHIP USB2 PHY
>> >> >
>> >> >  Required properties:
>> >> > - - compatible: rockchip,rk3288-usb-phy
>> >> > + - compatible: matching the soc type, one of
>> >> > +     "rockchip,rk3066a-usb-phy"
>> >> > +     "rockchip,rk3188-usb-phy"
>> >> > +     "rockchip,rk3288-usb-phy"
>> >>
>> >> I can never quite keep it straight how this is supposed to work, but
>> >> since previously only "rockchip,rk3288-usb-phy" was supported and now
>> >> we have these new compatible strings, I would have expected the new
>> >> strings to specify the old ones as fallback.  That would mean your
>> >> choices would be:
>> >>
>> >> - "rockchip,rk3288-usb-phy" - A real rk3288
>> >> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
>> >> fallback to 3288 driver.
>> >> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
>> >> with fallback to 3288 driver.
>> >
>> > How this is supposed to be done also is sometimes confusing for me :-)
>> >
>> > But I don't think that specifying the "fallbacks" is part of the binding
>> > at
>> > all, when the binding really is done in a soc-specific way.  For example
>> > following the suggestion of the dt-maintainers at the time we're
>> > specifying
>> > the uarts as
>> >
>> >         compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"
>> >
>> > as a measure to use a more-special driver if there is ever the need for
>> > it.
>> > But here the "snps,dw-apb-uart" actually is a superset (a more generic
>> > implementation), while in the usb-uart-case
>>
>> Hrm, this gets into the whole issue of coming up with generic names.
>> It's not always easy, especially when marketing gets involved.  If
>> Synopsis comes up with a new APB UART that's not compatible, I guess
>> you call it a v2 and people just need to figure out which one they
>> have?  I remember it being terribly confusing with exynos since
>> Samsung called things "exynos" that were very different, and I think
>> even "exynos5" devices were pretty different form each other.  Anyway,
>> that's getting pretty far afield.
>>
>> The general way of doing things in Linux is that the first driver
>> there becomes the generic, right?  So if the first supported SoC using
>> this PHY was rk3288 then it gets the name and becomes the generic. If
>> rk3066a and 3188 are 90% the same and initially can actually use the
>> same driver, then they specify the specific "3188" and the generic
>> "3288" as a fallback.  It sounds like that was what was actually done
>> in the DTS files anyway, which is right as far as I'm concerned.
>>
>> ...but personally I'd love to see it documented.  ...someone reading
>> the binding should be able to create a DTS and it's not obvious from
>> the DTS that "rk3288" is the generic as far as this binding is
>> concerned.
>
> I'd like to disagree here :-)
>
> Generic is actually currently "rockchip-usb-phy", the platform-driver name,
> but thankfully that hasn't leaked into the dts, as even that name + filename
> should change in the future. What rk3288 (and before) uses is a Designware
> picophy with custom registers in the grf, so it should actually be
> "rockchip-usb-picophy" or so. Following socs use a different IP (Innosilicon
> if I remember correctly), with different clock/pll handling and a whole
> different set of registers, so will get a new driver.
>
> In terms of hardware compatibility, the phys aren't actually compatible, it's
> only per chance that the used SIDDQ bit has the same position on all socs :-)
> Everything else seems to move around quite happily in the registers.
>
>
> As it stands now, the rk3188 dts has a compatible of
> "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy", matching the usable
> [refraining from calling it generic] driver on old kernels, while now it is
> supposed to match the actually correct rk3188 variant. So that combination
> works with the same dts on both old and new kernels fullfilling the ABI-
> stability promise.
>
> With the new matching code (clock-names etc) you actually get issues if you
> try to match against "rockchip,rk3288-usb-phy" on a rk3188, so there is no
> "generic" part. And that difference will widen if we need to control other
> parts of the usb-phy as well.
>
> So essentially that second property should go completely, I just didn't wanted
> to create the impression of changing the ABI here ;-)

OK, fair enough.  I'm not terribly familiar with rk3066a and rk3188,
so didn't realize how different they were.  I guess I assumed that
they were more like 90% compatible, but perhaps not...

I also think some of these corner cases of device tree still haven't
seeped into my consciousness yet and become instinct.  Maybe in
another few years.  ;)

-Doug

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-25 18:35             ` Doug Anderson
  0 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-25 18:35 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Lin Huang, Arnd Bergmann, Michael Turquette, Stephen Boyd,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Kishon Vijay Abraham I,
	open list:ARM/Rockchip SoC...,
	Romain Perier, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi,

On Wed, Nov 25, 2015 at 10:24 AM, Heiko Stübner <heiko@sntech.de> wrote:
> Am Mittwoch, 25. November 2015, 09:04:19 schrieb Doug Anderson:
>> Hi,
>>
>> On Sun, Nov 22, 2015 at 11:49 AM, Heiko Stuebner <heiko@sntech.de> wrote:
>> > Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
>> >> Heiko,
>> >>
>> >> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
>> >> > We need custom handling for these two socs in the driver shortly,
>> >> > so add the necessary compatible values to binding and driver.
>> >> >
>> >> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> >> > ---
>> >> >
>> >> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
>> >> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
>> >> >  2 files changed, 6 insertions(+), 1 deletion(-)
>> >> >
>> >> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >
>> > b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >
>> >> > index 826454a..9b37242 100644
>> >> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >> > @@ -1,7 +1,10 @@
>> >> >
>> >> >  ROCKCHIP USB2 PHY
>> >> >
>> >> >  Required properties:
>> >> > - - compatible: rockchip,rk3288-usb-phy
>> >> > + - compatible: matching the soc type, one of
>> >> > +     "rockchip,rk3066a-usb-phy"
>> >> > +     "rockchip,rk3188-usb-phy"
>> >> > +     "rockchip,rk3288-usb-phy"
>> >>
>> >> I can never quite keep it straight how this is supposed to work, but
>> >> since previously only "rockchip,rk3288-usb-phy" was supported and now
>> >> we have these new compatible strings, I would have expected the new
>> >> strings to specify the old ones as fallback.  That would mean your
>> >> choices would be:
>> >>
>> >> - "rockchip,rk3288-usb-phy" - A real rk3288
>> >> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
>> >> fallback to 3288 driver.
>> >> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
>> >> with fallback to 3288 driver.
>> >
>> > How this is supposed to be done also is sometimes confusing for me :-)
>> >
>> > But I don't think that specifying the "fallbacks" is part of the binding
>> > at
>> > all, when the binding really is done in a soc-specific way.  For example
>> > following the suggestion of the dt-maintainers at the time we're
>> > specifying
>> > the uarts as
>> >
>> >         compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"
>> >
>> > as a measure to use a more-special driver if there is ever the need for
>> > it.
>> > But here the "snps,dw-apb-uart" actually is a superset (a more generic
>> > implementation), while in the usb-uart-case
>>
>> Hrm, this gets into the whole issue of coming up with generic names.
>> It's not always easy, especially when marketing gets involved.  If
>> Synopsis comes up with a new APB UART that's not compatible, I guess
>> you call it a v2 and people just need to figure out which one they
>> have?  I remember it being terribly confusing with exynos since
>> Samsung called things "exynos" that were very different, and I think
>> even "exynos5" devices were pretty different form each other.  Anyway,
>> that's getting pretty far afield.
>>
>> The general way of doing things in Linux is that the first driver
>> there becomes the generic, right?  So if the first supported SoC using
>> this PHY was rk3288 then it gets the name and becomes the generic. If
>> rk3066a and 3188 are 90% the same and initially can actually use the
>> same driver, then they specify the specific "3188" and the generic
>> "3288" as a fallback.  It sounds like that was what was actually done
>> in the DTS files anyway, which is right as far as I'm concerned.
>>
>> ...but personally I'd love to see it documented.  ...someone reading
>> the binding should be able to create a DTS and it's not obvious from
>> the DTS that "rk3288" is the generic as far as this binding is
>> concerned.
>
> I'd like to disagree here :-)
>
> Generic is actually currently "rockchip-usb-phy", the platform-driver name,
> but thankfully that hasn't leaked into the dts, as even that name + filename
> should change in the future. What rk3288 (and before) uses is a Designware
> picophy with custom registers in the grf, so it should actually be
> "rockchip-usb-picophy" or so. Following socs use a different IP (Innosilicon
> if I remember correctly), with different clock/pll handling and a whole
> different set of registers, so will get a new driver.
>
> In terms of hardware compatibility, the phys aren't actually compatible, it's
> only per chance that the used SIDDQ bit has the same position on all socs :-)
> Everything else seems to move around quite happily in the registers.
>
>
> As it stands now, the rk3188 dts has a compatible of
> "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy", matching the usable
> [refraining from calling it generic] driver on old kernels, while now it is
> supposed to match the actually correct rk3188 variant. So that combination
> works with the same dts on both old and new kernels fullfilling the ABI-
> stability promise.
>
> With the new matching code (clock-names etc) you actually get issues if you
> try to match against "rockchip,rk3288-usb-phy" on a rk3188, so there is no
> "generic" part. And that difference will widen if we need to control other
> parts of the usb-phy as well.
>
> So essentially that second property should go completely, I just didn't wanted
> to create the impression of changing the ABI here ;-)

OK, fair enough.  I'm not terribly familiar with rk3066a and rk3188,
so didn't realize how different they were.  I guess I assumed that
they were more like 90% compatible, but perhaps not...

I also think some of these corner cases of device tree still haven't
seeped into my consciousness yet and become instinct.  Maybe in
another few years.  ;)

-Doug

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188
@ 2015-11-25 18:35             ` Doug Anderson
  0 siblings, 0 replies; 67+ messages in thread
From: Doug Anderson @ 2015-11-25 18:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Wed, Nov 25, 2015 at 10:24 AM, Heiko St?bner <heiko@sntech.de> wrote:
> Am Mittwoch, 25. November 2015, 09:04:19 schrieb Doug Anderson:
>> Hi,
>>
>> On Sun, Nov 22, 2015 at 11:49 AM, Heiko Stuebner <heiko@sntech.de> wrote:
>> > Am Donnerstag, 19. November 2015, 16:32:23 schrieb Doug Anderson:
>> >> Heiko,
>> >>
>> >> On Thu, Nov 19, 2015 at 1:22 PM, Heiko Stuebner <heiko@sntech.de> wrote:
>> >> > We need custom handling for these two socs in the driver shortly,
>> >> > so add the necessary compatible values to binding and driver.
>> >> >
>> >> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> >> > ---
>> >> >
>> >> >  Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 5 ++++-
>> >> >  drivers/phy/phy-rockchip-usb.c                             | 2 ++
>> >> >  2 files changed, 6 insertions(+), 1 deletion(-)
>> >> >
>> >> > diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >
>> > b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >
>> >> > index 826454a..9b37242 100644
>> >> > --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >> > +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> >> > @@ -1,7 +1,10 @@
>> >> >
>> >> >  ROCKCHIP USB2 PHY
>> >> >
>> >> >  Required properties:
>> >> > - - compatible: rockchip,rk3288-usb-phy
>> >> > + - compatible: matching the soc type, one of
>> >> > +     "rockchip,rk3066a-usb-phy"
>> >> > +     "rockchip,rk3188-usb-phy"
>> >> > +     "rockchip,rk3288-usb-phy"
>> >>
>> >> I can never quite keep it straight how this is supposed to work, but
>> >> since previously only "rockchip,rk3288-usb-phy" was supported and now
>> >> we have these new compatible strings, I would have expected the new
>> >> strings to specify the old ones as fallback.  That would mean your
>> >> choices would be:
>> >>
>> >> - "rockchip,rk3288-usb-phy" - A real rk3288
>> >> - "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy" - A rk3188 with
>> >> fallback to 3288 driver.
>> >> - "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy" - A rk3066a
>> >> with fallback to 3288 driver.
>> >
>> > How this is supposed to be done also is sometimes confusing for me :-)
>> >
>> > But I don't think that specifying the "fallbacks" is part of the binding
>> > at
>> > all, when the binding really is done in a soc-specific way.  For example
>> > following the suggestion of the dt-maintainers at the time we're
>> > specifying
>> > the uarts as
>> >
>> >         compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"
>> >
>> > as a measure to use a more-special driver if there is ever the need for
>> > it.
>> > But here the "snps,dw-apb-uart" actually is a superset (a more generic
>> > implementation), while in the usb-uart-case
>>
>> Hrm, this gets into the whole issue of coming up with generic names.
>> It's not always easy, especially when marketing gets involved.  If
>> Synopsis comes up with a new APB UART that's not compatible, I guess
>> you call it a v2 and people just need to figure out which one they
>> have?  I remember it being terribly confusing with exynos since
>> Samsung called things "exynos" that were very different, and I think
>> even "exynos5" devices were pretty different form each other.  Anyway,
>> that's getting pretty far afield.
>>
>> The general way of doing things in Linux is that the first driver
>> there becomes the generic, right?  So if the first supported SoC using
>> this PHY was rk3288 then it gets the name and becomes the generic. If
>> rk3066a and 3188 are 90% the same and initially can actually use the
>> same driver, then they specify the specific "3188" and the generic
>> "3288" as a fallback.  It sounds like that was what was actually done
>> in the DTS files anyway, which is right as far as I'm concerned.
>>
>> ...but personally I'd love to see it documented.  ...someone reading
>> the binding should be able to create a DTS and it's not obvious from
>> the DTS that "rk3288" is the generic as far as this binding is
>> concerned.
>
> I'd like to disagree here :-)
>
> Generic is actually currently "rockchip-usb-phy", the platform-driver name,
> but thankfully that hasn't leaked into the dts, as even that name + filename
> should change in the future. What rk3288 (and before) uses is a Designware
> picophy with custom registers in the grf, so it should actually be
> "rockchip-usb-picophy" or so. Following socs use a different IP (Innosilicon
> if I remember correctly), with different clock/pll handling and a whole
> different set of registers, so will get a new driver.
>
> In terms of hardware compatibility, the phys aren't actually compatible, it's
> only per chance that the used SIDDQ bit has the same position on all socs :-)
> Everything else seems to move around quite happily in the registers.
>
>
> As it stands now, the rk3188 dts has a compatible of
> "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy", matching the usable
> [refraining from calling it generic] driver on old kernels, while now it is
> supposed to match the actually correct rk3188 variant. So that combination
> works with the same dts on both old and new kernels fullfilling the ABI-
> stability promise.
>
> With the new matching code (clock-names etc) you actually get issues if you
> try to match against "rockchip,rk3288-usb-phy" on a rk3188, so there is no
> "generic" part. And that difference will widen if we need to control other
> parts of the usb-phy as well.
>
> So essentially that second property should go completely, I just didn't wanted
> to create the impression of changing the ABI here ;-)

OK, fair enough.  I'm not terribly familiar with rk3066a and rk3188,
so didn't realize how different they were.  I guess I assumed that
they were more like 90% compatible, but perhaps not...

I also think some of these corner cases of device tree still haven't
seeped into my consciousness yet and become instinct.  Maybe in
another few years.  ;)

-Doug

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 0/8] phy: rockchip-usb: correct pll handling and usb-uart
  2015-11-19 21:22 ` Heiko Stuebner
@ 2015-12-02 15:32   ` Heiko Stübner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2015-12-02 15:32 UTC (permalink / raw)
  To: kishon
  Cc: mturquette, sboyd, linux-arm-kernel, linux-kernel,
	linux-rockchip, dianders, romain.perier, arnd, hl

Hi Kishon,

Am Donnerstag, 19. November 2015, 22:22:21 schrieb Heiko Stuebner:
> changes in v3:
> - rebase on top of Julias of_node_put fix
> - address comments from Kishon Vijay Abraham
>   - position of the devm_action in the first patch
>   - separate compatible-addition into separate patch
>   - don't rephrase comment when moving stuff around
> - address Doug's comment and keep clk-tree change and assigned-clocks
>   setting together
> - add Doug's review-tag to patches 5,6,7
> changes in v2:
> - add Doug's review-tag to patches 1 and 3
> - address comment and add the missing transistional rk_phy->base
>   assignment in patch2

do you have any further comments for this series?


Thanks
Heiko

> Patch 1 might be nice to go in as fix together with Julia's patch?
> 
> Patches 2-7 fix a long-standing issue with the clock-tree of Rockchip SoCs
> namely our ignorance of the usbphy-internal pll that creates the needed
> 480MHz but is also a supply-clock back to the core clock-controller in
> Rockchip SoCs.
> 
> Till now that was worked around using a virtual clock in the cru itself,
> but that is of course ignorant of other parts then disabling the phy
> behind the cru's back, thus breaking potential users of these clocks.
> 
> 
> Patch 8, while not associated with the new pll handling, also builds
> on the groundwork introduced there and adds support for the function
> repurposing one of the phys as passthrough for uart-data. This enables
> attaching a ttl converter to the D+ and D- pins of an usb cable to
> receive uart data this way, when it is not really possible to attach
> a regular serial console to a board.
> 
> One point of critique in my first iteration [0] of this was, that
> due to when the reconfiguration happens we may miss parts of the logs
> when earlycon is enabled. So far early_initcall gets used as the
> unflattened devicetree is necessary to set this up. Doing this for
> example in the early_param directly would require parsing the flattened
> devicetree to get needed nodes and properties.
> 
> I still maintain that if you're working on anything before smp-bringup
> you should use a real dev-board instead or try to solder uart cables
> on hopefully available test-points :-) .
> 
> 
> In any case, if patch 8 causes to much headache, it could be dropped
> to not hinder the earlier 7 patches.
> 
> [0] http://comments.gmane.org/gmane.linux.ports.arm.rockchip/715
> 
> Heiko Stuebner (8):
>   phy: rockchip-usb: fix clock get-put mismatch
>   phy: rockchip-usb: introduce a common data-struct for the device
>   phy: rockchip-usb: move per-phy init into a separate function
>   phy: rockchip-usb: add compatible values for rk3066a and rk3188
>   phy: rockchip-usb: expose the phy-internal PLLs
>   ARM: dts: rockchip: add clock-cells for usb phy nodes
>   clk: rockchip: fix usbphy-related clocks
>   phy: rockchip-usb: add handler for usb-uart functionality
> 
>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   6 +-
>  Documentation/kernel-parameters.txt                |   6 +
>  arch/arm/boot/dts/rk3066a.dtsi                     |   2 +
>  arch/arm/boot/dts/rk3188.dtsi                      |   2 +
>  arch/arm/boot/dts/rk3288-veyron.dtsi               |   2 +-
>  arch/arm/boot/dts/rk3288.dtsi                      |   3 +
>  drivers/clk/rockchip/clk-rk3188.c                  |  11 +-
>  drivers/clk/rockchip/clk-rk3288.c                  |  16 +-
>  drivers/phy/phy-rockchip-usb.c                     | 458
> ++++++++++++++++++--- 9 files changed, 417 insertions(+), 89 deletions(-)


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 0/8] phy: rockchip-usb: correct pll handling and usb-uart
@ 2015-12-02 15:32   ` Heiko Stübner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2015-12-02 15:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kishon,

Am Donnerstag, 19. November 2015, 22:22:21 schrieb Heiko Stuebner:
> changes in v3:
> - rebase on top of Julias of_node_put fix
> - address comments from Kishon Vijay Abraham
>   - position of the devm_action in the first patch
>   - separate compatible-addition into separate patch
>   - don't rephrase comment when moving stuff around
> - address Doug's comment and keep clk-tree change and assigned-clocks
>   setting together
> - add Doug's review-tag to patches 5,6,7
> changes in v2:
> - add Doug's review-tag to patches 1 and 3
> - address comment and add the missing transistional rk_phy->base
>   assignment in patch2

do you have any further comments for this series?


Thanks
Heiko

> Patch 1 might be nice to go in as fix together with Julia's patch?
> 
> Patches 2-7 fix a long-standing issue with the clock-tree of Rockchip SoCs
> namely our ignorance of the usbphy-internal pll that creates the needed
> 480MHz but is also a supply-clock back to the core clock-controller in
> Rockchip SoCs.
> 
> Till now that was worked around using a virtual clock in the cru itself,
> but that is of course ignorant of other parts then disabling the phy
> behind the cru's back, thus breaking potential users of these clocks.
> 
> 
> Patch 8, while not associated with the new pll handling, also builds
> on the groundwork introduced there and adds support for the function
> repurposing one of the phys as passthrough for uart-data. This enables
> attaching a ttl converter to the D+ and D- pins of an usb cable to
> receive uart data this way, when it is not really possible to attach
> a regular serial console to a board.
> 
> One point of critique in my first iteration [0] of this was, that
> due to when the reconfiguration happens we may miss parts of the logs
> when earlycon is enabled. So far early_initcall gets used as the
> unflattened devicetree is necessary to set this up. Doing this for
> example in the early_param directly would require parsing the flattened
> devicetree to get needed nodes and properties.
> 
> I still maintain that if you're working on anything before smp-bringup
> you should use a real dev-board instead or try to solder uart cables
> on hopefully available test-points :-) .
> 
> 
> In any case, if patch 8 causes to much headache, it could be dropped
> to not hinder the earlier 7 patches.
> 
> [0] http://comments.gmane.org/gmane.linux.ports.arm.rockchip/715
> 
> Heiko Stuebner (8):
>   phy: rockchip-usb: fix clock get-put mismatch
>   phy: rockchip-usb: introduce a common data-struct for the device
>   phy: rockchip-usb: move per-phy init into a separate function
>   phy: rockchip-usb: add compatible values for rk3066a and rk3188
>   phy: rockchip-usb: expose the phy-internal PLLs
>   ARM: dts: rockchip: add clock-cells for usb phy nodes
>   clk: rockchip: fix usbphy-related clocks
>   phy: rockchip-usb: add handler for usb-uart functionality
> 
>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   6 +-
>  Documentation/kernel-parameters.txt                |   6 +
>  arch/arm/boot/dts/rk3066a.dtsi                     |   2 +
>  arch/arm/boot/dts/rk3188.dtsi                      |   2 +
>  arch/arm/boot/dts/rk3288-veyron.dtsi               |   2 +-
>  arch/arm/boot/dts/rk3288.dtsi                      |   3 +
>  drivers/clk/rockchip/clk-rk3188.c                  |  11 +-
>  drivers/clk/rockchip/clk-rk3288.c                  |  16 +-
>  drivers/phy/phy-rockchip-usb.c                     | 458
> ++++++++++++++++++--- 9 files changed, 417 insertions(+), 89 deletions(-)

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 0/8] phy: rockchip-usb: correct pll handling and usb-uart
  2015-12-02 15:32   ` Heiko Stübner
  (?)
@ 2015-12-03  6:05     ` Kishon Vijay Abraham I
  -1 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-03  6:05 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: mturquette, sboyd, linux-arm-kernel, linux-kernel,
	linux-rockchip, dianders, romain.perier, arnd, hl

Hi,

On Wednesday 02 December 2015 09:02 PM, Heiko Stübner wrote:
> Hi Kishon,
> 
> Am Donnerstag, 19. November 2015, 22:22:21 schrieb Heiko Stuebner:
>> changes in v3:
>> - rebase on top of Julias of_node_put fix
>> - address comments from Kishon Vijay Abraham
>>   - position of the devm_action in the first patch
>>   - separate compatible-addition into separate patch
>>   - don't rephrase comment when moving stuff around
>> - address Doug's comment and keep clk-tree change and assigned-clocks
>>   setting together
>> - add Doug's review-tag to patches 5,6,7
>> changes in v2:
>> - add Doug's review-tag to patches 1 and 3
>> - address comment and add the missing transistional rk_phy->base
>>   assignment in patch2
> 
> do you have any further comments for this series?

Nope. However I'd like to have ACK from the clock maintainer (Mike turquette?)
for "phy: rockchip-usb: expose the phy-internal PLLs".

Thanks
Kishon
> 
> 
> Thanks
> Heiko
> 
>> Patch 1 might be nice to go in as fix together with Julia's patch?
>>
>> Patches 2-7 fix a long-standing issue with the clock-tree of Rockchip SoCs
>> namely our ignorance of the usbphy-internal pll that creates the needed
>> 480MHz but is also a supply-clock back to the core clock-controller in
>> Rockchip SoCs.
>>
>> Till now that was worked around using a virtual clock in the cru itself,
>> but that is of course ignorant of other parts then disabling the phy
>> behind the cru's back, thus breaking potential users of these clocks.
>>
>>
>> Patch 8, while not associated with the new pll handling, also builds
>> on the groundwork introduced there and adds support for the function
>> repurposing one of the phys as passthrough for uart-data. This enables
>> attaching a ttl converter to the D+ and D- pins of an usb cable to
>> receive uart data this way, when it is not really possible to attach
>> a regular serial console to a board.
>>
>> One point of critique in my first iteration [0] of this was, that
>> due to when the reconfiguration happens we may miss parts of the logs
>> when earlycon is enabled. So far early_initcall gets used as the
>> unflattened devicetree is necessary to set this up. Doing this for
>> example in the early_param directly would require parsing the flattened
>> devicetree to get needed nodes and properties.
>>
>> I still maintain that if you're working on anything before smp-bringup
>> you should use a real dev-board instead or try to solder uart cables
>> on hopefully available test-points :-) .
>>
>>
>> In any case, if patch 8 causes to much headache, it could be dropped
>> to not hinder the earlier 7 patches.
>>
>> [0] http://comments.gmane.org/gmane.linux.ports.arm.rockchip/715
>>
>> Heiko Stuebner (8):
>>   phy: rockchip-usb: fix clock get-put mismatch
>>   phy: rockchip-usb: introduce a common data-struct for the device
>>   phy: rockchip-usb: move per-phy init into a separate function
>>   phy: rockchip-usb: add compatible values for rk3066a and rk3188
>>   phy: rockchip-usb: expose the phy-internal PLLs
>>   ARM: dts: rockchip: add clock-cells for usb phy nodes
>>   clk: rockchip: fix usbphy-related clocks
>>   phy: rockchip-usb: add handler for usb-uart functionality
>>
>>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   6 +-
>>  Documentation/kernel-parameters.txt                |   6 +
>>  arch/arm/boot/dts/rk3066a.dtsi                     |   2 +
>>  arch/arm/boot/dts/rk3188.dtsi                      |   2 +
>>  arch/arm/boot/dts/rk3288-veyron.dtsi               |   2 +-
>>  arch/arm/boot/dts/rk3288.dtsi                      |   3 +
>>  drivers/clk/rockchip/clk-rk3188.c                  |  11 +-
>>  drivers/clk/rockchip/clk-rk3288.c                  |  16 +-
>>  drivers/phy/phy-rockchip-usb.c                     | 458
>> ++++++++++++++++++--- 9 files changed, 417 insertions(+), 89 deletions(-)
> 

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 0/8] phy: rockchip-usb: correct pll handling and usb-uart
@ 2015-12-03  6:05     ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-03  6:05 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: hl-TNX95d0MmH7DzftRWevZcw, arnd-r2nGTMty4D4,
	mturquette-rdvid1DuHRBWk0Htik3J/w, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	romain.perier-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi,

On Wednesday 02 December 2015 09:02 PM, Heiko Stübner wrote:
> Hi Kishon,
> 
> Am Donnerstag, 19. November 2015, 22:22:21 schrieb Heiko Stuebner:
>> changes in v3:
>> - rebase on top of Julias of_node_put fix
>> - address comments from Kishon Vijay Abraham
>>   - position of the devm_action in the first patch
>>   - separate compatible-addition into separate patch
>>   - don't rephrase comment when moving stuff around
>> - address Doug's comment and keep clk-tree change and assigned-clocks
>>   setting together
>> - add Doug's review-tag to patches 5,6,7
>> changes in v2:
>> - add Doug's review-tag to patches 1 and 3
>> - address comment and add the missing transistional rk_phy->base
>>   assignment in patch2
> 
> do you have any further comments for this series?

Nope. However I'd like to have ACK from the clock maintainer (Mike turquette?)
for "phy: rockchip-usb: expose the phy-internal PLLs".

Thanks
Kishon
> 
> 
> Thanks
> Heiko
> 
>> Patch 1 might be nice to go in as fix together with Julia's patch?
>>
>> Patches 2-7 fix a long-standing issue with the clock-tree of Rockchip SoCs
>> namely our ignorance of the usbphy-internal pll that creates the needed
>> 480MHz but is also a supply-clock back to the core clock-controller in
>> Rockchip SoCs.
>>
>> Till now that was worked around using a virtual clock in the cru itself,
>> but that is of course ignorant of other parts then disabling the phy
>> behind the cru's back, thus breaking potential users of these clocks.
>>
>>
>> Patch 8, while not associated with the new pll handling, also builds
>> on the groundwork introduced there and adds support for the function
>> repurposing one of the phys as passthrough for uart-data. This enables
>> attaching a ttl converter to the D+ and D- pins of an usb cable to
>> receive uart data this way, when it is not really possible to attach
>> a regular serial console to a board.
>>
>> One point of critique in my first iteration [0] of this was, that
>> due to when the reconfiguration happens we may miss parts of the logs
>> when earlycon is enabled. So far early_initcall gets used as the
>> unflattened devicetree is necessary to set this up. Doing this for
>> example in the early_param directly would require parsing the flattened
>> devicetree to get needed nodes and properties.
>>
>> I still maintain that if you're working on anything before smp-bringup
>> you should use a real dev-board instead or try to solder uart cables
>> on hopefully available test-points :-) .
>>
>>
>> In any case, if patch 8 causes to much headache, it could be dropped
>> to not hinder the earlier 7 patches.
>>
>> [0] http://comments.gmane.org/gmane.linux.ports.arm.rockchip/715
>>
>> Heiko Stuebner (8):
>>   phy: rockchip-usb: fix clock get-put mismatch
>>   phy: rockchip-usb: introduce a common data-struct for the device
>>   phy: rockchip-usb: move per-phy init into a separate function
>>   phy: rockchip-usb: add compatible values for rk3066a and rk3188
>>   phy: rockchip-usb: expose the phy-internal PLLs
>>   ARM: dts: rockchip: add clock-cells for usb phy nodes
>>   clk: rockchip: fix usbphy-related clocks
>>   phy: rockchip-usb: add handler for usb-uart functionality
>>
>>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   6 +-
>>  Documentation/kernel-parameters.txt                |   6 +
>>  arch/arm/boot/dts/rk3066a.dtsi                     |   2 +
>>  arch/arm/boot/dts/rk3188.dtsi                      |   2 +
>>  arch/arm/boot/dts/rk3288-veyron.dtsi               |   2 +-
>>  arch/arm/boot/dts/rk3288.dtsi                      |   3 +
>>  drivers/clk/rockchip/clk-rk3188.c                  |  11 +-
>>  drivers/clk/rockchip/clk-rk3288.c                  |  16 +-
>>  drivers/phy/phy-rockchip-usb.c                     | 458
>> ++++++++++++++++++--- 9 files changed, 417 insertions(+), 89 deletions(-)
> 

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 0/8] phy: rockchip-usb: correct pll handling and usb-uart
@ 2015-12-03  6:05     ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-03  6:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Wednesday 02 December 2015 09:02 PM, Heiko St?bner wrote:
> Hi Kishon,
> 
> Am Donnerstag, 19. November 2015, 22:22:21 schrieb Heiko Stuebner:
>> changes in v3:
>> - rebase on top of Julias of_node_put fix
>> - address comments from Kishon Vijay Abraham
>>   - position of the devm_action in the first patch
>>   - separate compatible-addition into separate patch
>>   - don't rephrase comment when moving stuff around
>> - address Doug's comment and keep clk-tree change and assigned-clocks
>>   setting together
>> - add Doug's review-tag to patches 5,6,7
>> changes in v2:
>> - add Doug's review-tag to patches 1 and 3
>> - address comment and add the missing transistional rk_phy->base
>>   assignment in patch2
> 
> do you have any further comments for this series?

Nope. However I'd like to have ACK from the clock maintainer (Mike turquette?)
for "phy: rockchip-usb: expose the phy-internal PLLs".

Thanks
Kishon
> 
> 
> Thanks
> Heiko
> 
>> Patch 1 might be nice to go in as fix together with Julia's patch?
>>
>> Patches 2-7 fix a long-standing issue with the clock-tree of Rockchip SoCs
>> namely our ignorance of the usbphy-internal pll that creates the needed
>> 480MHz but is also a supply-clock back to the core clock-controller in
>> Rockchip SoCs.
>>
>> Till now that was worked around using a virtual clock in the cru itself,
>> but that is of course ignorant of other parts then disabling the phy
>> behind the cru's back, thus breaking potential users of these clocks.
>>
>>
>> Patch 8, while not associated with the new pll handling, also builds
>> on the groundwork introduced there and adds support for the function
>> repurposing one of the phys as passthrough for uart-data. This enables
>> attaching a ttl converter to the D+ and D- pins of an usb cable to
>> receive uart data this way, when it is not really possible to attach
>> a regular serial console to a board.
>>
>> One point of critique in my first iteration [0] of this was, that
>> due to when the reconfiguration happens we may miss parts of the logs
>> when earlycon is enabled. So far early_initcall gets used as the
>> unflattened devicetree is necessary to set this up. Doing this for
>> example in the early_param directly would require parsing the flattened
>> devicetree to get needed nodes and properties.
>>
>> I still maintain that if you're working on anything before smp-bringup
>> you should use a real dev-board instead or try to solder uart cables
>> on hopefully available test-points :-) .
>>
>>
>> In any case, if patch 8 causes to much headache, it could be dropped
>> to not hinder the earlier 7 patches.
>>
>> [0] http://comments.gmane.org/gmane.linux.ports.arm.rockchip/715
>>
>> Heiko Stuebner (8):
>>   phy: rockchip-usb: fix clock get-put mismatch
>>   phy: rockchip-usb: introduce a common data-struct for the device
>>   phy: rockchip-usb: move per-phy init into a separate function
>>   phy: rockchip-usb: add compatible values for rk3066a and rk3188
>>   phy: rockchip-usb: expose the phy-internal PLLs
>>   ARM: dts: rockchip: add clock-cells for usb phy nodes
>>   clk: rockchip: fix usbphy-related clocks
>>   phy: rockchip-usb: add handler for usb-uart functionality
>>
>>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   6 +-
>>  Documentation/kernel-parameters.txt                |   6 +
>>  arch/arm/boot/dts/rk3066a.dtsi                     |   2 +
>>  arch/arm/boot/dts/rk3188.dtsi                      |   2 +
>>  arch/arm/boot/dts/rk3288-veyron.dtsi               |   2 +-
>>  arch/arm/boot/dts/rk3288.dtsi                      |   3 +
>>  drivers/clk/rockchip/clk-rk3188.c                  |  11 +-
>>  drivers/clk/rockchip/clk-rk3288.c                  |  16 +-
>>  drivers/phy/phy-rockchip-usb.c                     | 458
>> ++++++++++++++++++--- 9 files changed, 417 insertions(+), 89 deletions(-)
> 

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
@ 2015-12-15 10:52     ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-15 10:52 UTC (permalink / raw)
  To: Heiko Stuebner, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl

Hi Mike,

On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
> The otgphy clocks really only drive the phy blocks. These in turn
> contain plls that then generate the 480m clocks the clock controller
> uses to supply some other clocks like uart0, gpu or the video-codec.
> 
> So fix this structure to actually respect that hirarchy and removed
> that usb480m fixed-rate clock working as a placeholder till now, as
> this wouldn't even work if the supplying phy gets turned off while
> its pll-output gets used elsewhere.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>

I saw you've given your Acked-by in a previous version of this patch.
Do you want me to take this in linux-phy tree?

Thanks
Kishon
> ---
>  arch/arm/boot/dts/rk3288-veyron.dtsi |  2 +-
>  drivers/clk/rockchip/clk-rk3188.c    | 11 +++--------
>  drivers/clk/rockchip/clk-rk3288.c    | 16 +++++-----------
>  3 files changed, 9 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
> index 5e61f07..0a43e21 100644
> --- a/arch/arm/boot/dts/rk3288-veyron.dtsi
> +++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
> @@ -416,7 +416,7 @@
>  	status = "okay";
>  
>  	assigned-clocks = <&cru SCLK_USBPHY480M_SRC>;
> -	assigned-clock-parents = <&cru SCLK_OTGPHY0>;
> +	assigned-clock-parents = <&usbphy0>;
>  	dr_mode = "host";
>  };
>  
> diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
> index abb4760..7836a97 100644
> --- a/drivers/clk/rockchip/clk-rk3188.c
> +++ b/drivers/clk/rockchip/clk-rk3188.c
> @@ -319,9 +319,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
>  	 * the 480m are generated inside the usb block from these clocks,
>  	 * but they are also a source for the hsicphy clock.
>  	 */
> -	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
>  			RK2928_CLKGATE_CON(1), 5, GFLAGS),
> -	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
>  			RK2928_CLKGATE_CON(1), 6, GFLAGS),
>  
>  	COMPOSITE(0, "mac_src", mux_mac_p, 0,
> @@ -635,7 +635,7 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = {
>  	{ /* sentinel */ },
>  };
>  
> -PNAME(mux_hsicphy_p)		= { "sclk_otgphy0", "sclk_otgphy1",
> +PNAME(mux_hsicphy_p)		= { "sclk_otgphy0_480m", "sclk_otgphy1_480m",
>  				    "gpll", "cpll" };
>  
>  static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
> @@ -739,11 +739,6 @@ static void __init rk3188_common_clk_init(struct device_node *np)
>  		pr_warn("%s: could not register clock xin12m: %ld\n",
>  			__func__, PTR_ERR(clk));
>  
> -	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
> -	if (IS_ERR(clk))
> -		pr_warn("%s: could not register clock usb480m: %ld\n",
> -			__func__, PTR_ERR(clk));
> -
>  	rockchip_clk_register_branches(common_clk_branches,
>  				  ARRAY_SIZE(common_clk_branches));
>  
> diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
> index 9040878..7c8a3e9 100644
> --- a/drivers/clk/rockchip/clk-rk3288.c
> +++ b/drivers/clk/rockchip/clk-rk3288.c
> @@ -195,8 +195,8 @@ PNAME(mux_hsadcout_p)	= { "hsadc_src", "ext_hsadc" };
>  PNAME(mux_edp_24m_p)	= { "ext_edp_24m", "xin24m" };
>  PNAME(mux_tspout_p)	= { "cpll", "gpll", "npll", "xin27m" };
>  
> -PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1", "sclk_otgphy2",
> -				    "sclk_otgphy0" };
> +PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1_480m", "sclk_otgphy2_480m",
> +				    "sclk_otgphy0_480m" };
>  PNAME(mux_hsicphy480m_p)	= { "cpll", "gpll", "usbphy480m_src" };
>  PNAME(mux_hsicphy12m_p)		= { "hsicphy12m_xin12m", "hsicphy12m_usbphy" };
>  
> @@ -506,11 +506,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
>  			RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
>  			RK3288_CLKGATE_CON(4), 10, GFLAGS),
>  
> -	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 4, GFLAGS),
> -	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 5, GFLAGS),
> -	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "xin24m", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 6, GFLAGS),
>  	GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 7, GFLAGS),
> @@ -874,12 +874,6 @@ static void __init rk3288_clk_init(struct device_node *np)
>  		pr_warn("%s: could not register clock xin12m: %ld\n",
>  			__func__, PTR_ERR(clk));
>  
> -
> -	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
> -	if (IS_ERR(clk))
> -		pr_warn("%s: could not register clock usb480m: %ld\n",
> -			__func__, PTR_ERR(clk));
> -
>  	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
>  					"hclk_vcodec_pre_v", 0, 1, 4);
>  	if (IS_ERR(clk))
> 

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
@ 2015-12-15 10:52     ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-15 10:52 UTC (permalink / raw)
  To: Heiko Stuebner, mturquette-rdvid1DuHRBWk0Htik3J/w,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: hl-TNX95d0MmH7DzftRWevZcw, arnd-r2nGTMty4D4,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	romain.perier-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Mike,

On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
> The otgphy clocks really only drive the phy blocks. These in turn
> contain plls that then generate the 480m clocks the clock controller
> uses to supply some other clocks like uart0, gpu or the video-codec.
> 
> So fix this structure to actually respect that hirarchy and removed
> that usb480m fixed-rate clock working as a placeholder till now, as
> this wouldn't even work if the supplying phy gets turned off while
> its pll-output gets used elsewhere.
> 
> Signed-off-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
> Reviewed-by: Douglas Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

I saw you've given your Acked-by in a previous version of this patch.
Do you want me to take this in linux-phy tree?

Thanks
Kishon
> ---
>  arch/arm/boot/dts/rk3288-veyron.dtsi |  2 +-
>  drivers/clk/rockchip/clk-rk3188.c    | 11 +++--------
>  drivers/clk/rockchip/clk-rk3288.c    | 16 +++++-----------
>  3 files changed, 9 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
> index 5e61f07..0a43e21 100644
> --- a/arch/arm/boot/dts/rk3288-veyron.dtsi
> +++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
> @@ -416,7 +416,7 @@
>  	status = "okay";
>  
>  	assigned-clocks = <&cru SCLK_USBPHY480M_SRC>;
> -	assigned-clock-parents = <&cru SCLK_OTGPHY0>;
> +	assigned-clock-parents = <&usbphy0>;
>  	dr_mode = "host";
>  };
>  
> diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
> index abb4760..7836a97 100644
> --- a/drivers/clk/rockchip/clk-rk3188.c
> +++ b/drivers/clk/rockchip/clk-rk3188.c
> @@ -319,9 +319,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
>  	 * the 480m are generated inside the usb block from these clocks,
>  	 * but they are also a source for the hsicphy clock.
>  	 */
> -	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
>  			RK2928_CLKGATE_CON(1), 5, GFLAGS),
> -	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
>  			RK2928_CLKGATE_CON(1), 6, GFLAGS),
>  
>  	COMPOSITE(0, "mac_src", mux_mac_p, 0,
> @@ -635,7 +635,7 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = {
>  	{ /* sentinel */ },
>  };
>  
> -PNAME(mux_hsicphy_p)		= { "sclk_otgphy0", "sclk_otgphy1",
> +PNAME(mux_hsicphy_p)		= { "sclk_otgphy0_480m", "sclk_otgphy1_480m",
>  				    "gpll", "cpll" };
>  
>  static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
> @@ -739,11 +739,6 @@ static void __init rk3188_common_clk_init(struct device_node *np)
>  		pr_warn("%s: could not register clock xin12m: %ld\n",
>  			__func__, PTR_ERR(clk));
>  
> -	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
> -	if (IS_ERR(clk))
> -		pr_warn("%s: could not register clock usb480m: %ld\n",
> -			__func__, PTR_ERR(clk));
> -
>  	rockchip_clk_register_branches(common_clk_branches,
>  				  ARRAY_SIZE(common_clk_branches));
>  
> diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
> index 9040878..7c8a3e9 100644
> --- a/drivers/clk/rockchip/clk-rk3288.c
> +++ b/drivers/clk/rockchip/clk-rk3288.c
> @@ -195,8 +195,8 @@ PNAME(mux_hsadcout_p)	= { "hsadc_src", "ext_hsadc" };
>  PNAME(mux_edp_24m_p)	= { "ext_edp_24m", "xin24m" };
>  PNAME(mux_tspout_p)	= { "cpll", "gpll", "npll", "xin27m" };
>  
> -PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1", "sclk_otgphy2",
> -				    "sclk_otgphy0" };
> +PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1_480m", "sclk_otgphy2_480m",
> +				    "sclk_otgphy0_480m" };
>  PNAME(mux_hsicphy480m_p)	= { "cpll", "gpll", "usbphy480m_src" };
>  PNAME(mux_hsicphy12m_p)		= { "hsicphy12m_xin12m", "hsicphy12m_usbphy" };
>  
> @@ -506,11 +506,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
>  			RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
>  			RK3288_CLKGATE_CON(4), 10, GFLAGS),
>  
> -	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 4, GFLAGS),
> -	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 5, GFLAGS),
> -	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "xin24m", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 6, GFLAGS),
>  	GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 7, GFLAGS),
> @@ -874,12 +874,6 @@ static void __init rk3288_clk_init(struct device_node *np)
>  		pr_warn("%s: could not register clock xin12m: %ld\n",
>  			__func__, PTR_ERR(clk));
>  
> -
> -	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
> -	if (IS_ERR(clk))
> -		pr_warn("%s: could not register clock usb480m: %ld\n",
> -			__func__, PTR_ERR(clk));
> -
>  	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
>  					"hclk_vcodec_pre_v", 0, 1, 4);
>  	if (IS_ERR(clk))
> 

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
@ 2015-12-15 10:52     ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-15 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mike,

On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
> The otgphy clocks really only drive the phy blocks. These in turn
> contain plls that then generate the 480m clocks the clock controller
> uses to supply some other clocks like uart0, gpu or the video-codec.
> 
> So fix this structure to actually respect that hirarchy and removed
> that usb480m fixed-rate clock working as a placeholder till now, as
> this wouldn't even work if the supplying phy gets turned off while
> its pll-output gets used elsewhere.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>

I saw you've given your Acked-by in a previous version of this patch.
Do you want me to take this in linux-phy tree?

Thanks
Kishon
> ---
>  arch/arm/boot/dts/rk3288-veyron.dtsi |  2 +-
>  drivers/clk/rockchip/clk-rk3188.c    | 11 +++--------
>  drivers/clk/rockchip/clk-rk3288.c    | 16 +++++-----------
>  3 files changed, 9 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
> index 5e61f07..0a43e21 100644
> --- a/arch/arm/boot/dts/rk3288-veyron.dtsi
> +++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
> @@ -416,7 +416,7 @@
>  	status = "okay";
>  
>  	assigned-clocks = <&cru SCLK_USBPHY480M_SRC>;
> -	assigned-clock-parents = <&cru SCLK_OTGPHY0>;
> +	assigned-clock-parents = <&usbphy0>;
>  	dr_mode = "host";
>  };
>  
> diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
> index abb4760..7836a97 100644
> --- a/drivers/clk/rockchip/clk-rk3188.c
> +++ b/drivers/clk/rockchip/clk-rk3188.c
> @@ -319,9 +319,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
>  	 * the 480m are generated inside the usb block from these clocks,
>  	 * but they are also a source for the hsicphy clock.
>  	 */
> -	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
>  			RK2928_CLKGATE_CON(1), 5, GFLAGS),
> -	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
>  			RK2928_CLKGATE_CON(1), 6, GFLAGS),
>  
>  	COMPOSITE(0, "mac_src", mux_mac_p, 0,
> @@ -635,7 +635,7 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = {
>  	{ /* sentinel */ },
>  };
>  
> -PNAME(mux_hsicphy_p)		= { "sclk_otgphy0", "sclk_otgphy1",
> +PNAME(mux_hsicphy_p)		= { "sclk_otgphy0_480m", "sclk_otgphy1_480m",
>  				    "gpll", "cpll" };
>  
>  static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
> @@ -739,11 +739,6 @@ static void __init rk3188_common_clk_init(struct device_node *np)
>  		pr_warn("%s: could not register clock xin12m: %ld\n",
>  			__func__, PTR_ERR(clk));
>  
> -	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
> -	if (IS_ERR(clk))
> -		pr_warn("%s: could not register clock usb480m: %ld\n",
> -			__func__, PTR_ERR(clk));
> -
>  	rockchip_clk_register_branches(common_clk_branches,
>  				  ARRAY_SIZE(common_clk_branches));
>  
> diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
> index 9040878..7c8a3e9 100644
> --- a/drivers/clk/rockchip/clk-rk3288.c
> +++ b/drivers/clk/rockchip/clk-rk3288.c
> @@ -195,8 +195,8 @@ PNAME(mux_hsadcout_p)	= { "hsadc_src", "ext_hsadc" };
>  PNAME(mux_edp_24m_p)	= { "ext_edp_24m", "xin24m" };
>  PNAME(mux_tspout_p)	= { "cpll", "gpll", "npll", "xin27m" };
>  
> -PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1", "sclk_otgphy2",
> -				    "sclk_otgphy0" };
> +PNAME(mux_usbphy480m_p)		= { "sclk_otgphy1_480m", "sclk_otgphy2_480m",
> +				    "sclk_otgphy0_480m" };
>  PNAME(mux_hsicphy480m_p)	= { "cpll", "gpll", "usbphy480m_src" };
>  PNAME(mux_hsicphy12m_p)		= { "hsicphy12m_xin12m", "hsicphy12m_usbphy" };
>  
> @@ -506,11 +506,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
>  			RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
>  			RK3288_CLKGATE_CON(4), 10, GFLAGS),
>  
> -	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 4, GFLAGS),
> -	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 5, GFLAGS),
> -	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", CLK_IGNORE_UNUSED,
> +	GATE(SCLK_OTGPHY2, "sclk_otgphy2", "xin24m", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 6, GFLAGS),
>  	GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
>  			RK3288_CLKGATE_CON(13), 7, GFLAGS),
> @@ -874,12 +874,6 @@ static void __init rk3288_clk_init(struct device_node *np)
>  		pr_warn("%s: could not register clock xin12m: %ld\n",
>  			__func__, PTR_ERR(clk));
>  
> -
> -	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
> -	if (IS_ERR(clk))
> -		pr_warn("%s: could not register clock usb480m: %ld\n",
> -			__func__, PTR_ERR(clk));
> -
>  	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
>  					"hclk_vcodec_pre_v", 0, 1, 4);
>  	if (IS_ERR(clk))
> 

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 5/8] phy: rockchip-usb: expose the phy-internal PLLs
@ 2015-12-15 10:53     ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-15 10:53 UTC (permalink / raw)
  To: Heiko Stuebner, mturquette, sboyd
  Cc: linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl

Hi Mike,

On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
> The USB phys on Rockchip SoCs contain their own internal PLLs to create
> the 480MHz needed. Additionally this PLL output is also fed back into the
> core clock-controller as possible source for clocks like the GPU or others.
> 
> Until now this was modelled incorrectly with a "virtual" factor clock in
> the clock controller. The one big caveat is that if we turn off the usb phy
> via the siddq signal, all analog components get turned off, including the
> PLLs. It is therefore possible that a source clock gets disabled without
> the clock driver ever knowing, possibly making the system hang.
> 
> Therefore register the phy-plls as real clocks that the clock driver can
> then reference again normally, making the clock hirarchy finally reflect
> the actual hardware.
> 
> The phy-ops get converted to simply turning that new clock on and off
> which in turn controls the siddq signal of the phy.
> 
> Through this the driver gains handling for platform-specific data, to
> handle the phy->clock name association.

Are you okay with this patch/ Can you give your Acked-by?

Thanks
Kishon

> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>
> ---
>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   1 +
>  drivers/phy/phy-rockchip-usb.c                     | 188 ++++++++++++++++++---
>  2 files changed, 162 insertions(+), 27 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> index 9b37242..68498d5 100644
> --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> @@ -24,6 +24,7 @@ required properties:
>  Optional Properties:
>  - clocks : phandle + clock specifier for the phy clocks
>  - clock-names: string, clock name, must be "phyclk"
> +- #clock-cells: for users of the phy-pll, should be 0
>  
>  Example:
>  
> diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
> index 16cd533..33a80eb 100644
> --- a/drivers/phy/phy-rockchip-usb.c
> +++ b/drivers/phy/phy-rockchip-usb.c
> @@ -15,12 +15,14 @@
>   */
>  
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/io.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/of.h>
>  #include <linux/of_address.h>
> +#include <linux/of_platform.h>
>  #include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
> @@ -36,15 +38,28 @@
>  #define SIDDQ_ON		BIT(13)
>  #define SIDDQ_OFF		(0 << 13)
>  
> +struct rockchip_usb_phys {
> +	int reg;
> +	const char *pll_name;
> +};
> +
> +struct rockchip_usb_phy_pdata {
> +	struct rockchip_usb_phys *phys;
> +};
> +
>  struct rockchip_usb_phy_base {
>  	struct device *dev;
>  	struct regmap *reg_base;
> +	const struct rockchip_usb_phy_pdata *pdata;
>  };
>  
>  struct rockchip_usb_phy {
>  	struct rockchip_usb_phy_base *base;
> +	struct device_node *np;
>  	unsigned int	reg_offset;
>  	struct clk	*clk;
> +	struct clk      *clk480m;
> +	struct clk_hw	clk480m_hw;
>  	struct phy	*phy;
>  };
>  
> @@ -55,17 +70,59 @@ static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
>  			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
>  }
>  
> -static int rockchip_usb_phy_power_off(struct phy *_phy)
> +static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
> +						unsigned long parent_rate)
>  {
> -	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
> -	int ret = 0;
> +	return 480000000;
> +}
> +
> +static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
> +{
> +	struct rockchip_usb_phy *phy = container_of(hw,
> +						    struct rockchip_usb_phy,
> +						    clk480m_hw);
>  
>  	/* Power down usb phy analog blocks by set siddq 1 */
> -	ret = rockchip_usb_phy_power(phy, 1);
> -	if (ret)
> +	rockchip_usb_phy_power(phy, 1);
> +}
> +
> +static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
> +{
> +	struct rockchip_usb_phy *phy = container_of(hw,
> +						    struct rockchip_usb_phy,
> +						    clk480m_hw);
> +
> +	/* Power up usb phy analog blocks by set siddq 0 */
> +	return rockchip_usb_phy_power(phy, 0);
> +}
> +
> +static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
> +{
> +	struct rockchip_usb_phy *phy = container_of(hw,
> +						    struct rockchip_usb_phy,
> +						    clk480m_hw);
> +	int ret;
> +	u32 val;
> +
> +	ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
> +	if (ret < 0)
>  		return ret;
>  
> -	clk_disable_unprepare(phy->clk);
> +	return (val & SIDDQ_ON) ? 0 : 1;
> +}
> +
> +static const struct clk_ops rockchip_usb_phy480m_ops = {
> +	.enable = rockchip_usb_phy480m_enable,
> +	.disable = rockchip_usb_phy480m_disable,
> +	.is_enabled = rockchip_usb_phy480m_is_enabled,
> +	.recalc_rate = rockchip_usb_phy480m_recalc_rate,
> +};
> +
> +static int rockchip_usb_phy_power_off(struct phy *_phy)
> +{
> +	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
> +
> +	clk_disable_unprepare(phy->clk480m);
>  
>  	return 0;
>  }
> @@ -73,20 +130,8 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
>  static int rockchip_usb_phy_power_on(struct phy *_phy)
>  {
>  	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
> -	int ret = 0;
>  
> -	ret = clk_prepare_enable(phy->clk);
> -	if (ret)
> -		return ret;
> -
> -	/* Power up usb phy analog blocks by set siddq 0 */
> -	ret = rockchip_usb_phy_power(phy, 0);
> -	if (ret) {
> -		clk_disable_unprepare(phy->clk);
> -		return ret;
> -	}
> -
> -	return 0;
> +	return clk_prepare_enable(phy->clk480m);
>  }
>  
>  static const struct phy_ops ops = {
> @@ -99,6 +144,9 @@ static void rockchip_usb_phy_action(void *data)
>  {
>  	struct rockchip_usb_phy *rk_phy = data;
>  
> +	of_clk_del_provider(rk_phy->np);
> +	clk_unregister(rk_phy->clk480m);
> +
>  	if (rk_phy->clk)
>  		clk_put(rk_phy->clk);
>  }
> @@ -108,13 +156,16 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>  {
>  	struct rockchip_usb_phy *rk_phy;
>  	unsigned int reg_offset;
> -	int err;
> +	const char *clk_name;
> +	struct clk_init_data init;
> +	int err, i;
>  
>  	rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
>  	if (!rk_phy)
>  		return -ENOMEM;
>  
>  	rk_phy->base = base;
> +	rk_phy->np = child;
>  
>  	if (of_property_read_u32(child, "reg", &reg_offset)) {
>  		dev_err(base->dev, "missing reg property in node %s\n",
> @@ -124,14 +175,54 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>  
>  	rk_phy->reg_offset = reg_offset;
>  
> -	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
> -	if (err)
> -		return err;
> -
>  	rk_phy->clk = of_clk_get_by_name(child, "phyclk");
>  	if (IS_ERR(rk_phy->clk))
>  		rk_phy->clk = NULL;
>  
> +	i = 0;
> +	init.name = NULL;
> +	while (base->pdata->phys[i].reg) {
> +		if (base->pdata->phys[i].reg == reg_offset) {
> +			init.name = base->pdata->phys[i].pll_name;
> +			break;
> +		}
> +		i++;
> +	}
> +
> +	if (!init.name) {
> +		dev_err(base->dev, "phy data not found\n");
> +		return -EINVAL;
> +	}
> +
> +	if (rk_phy->clk) {
> +		clk_name = __clk_get_name(rk_phy->clk);
> +		init.flags = 0;
> +		init.parent_names = &clk_name;
> +		init.num_parents = 1;
> +	} else {
> +		init.flags = CLK_IS_ROOT;
> +		init.parent_names = NULL;
> +		init.num_parents = 0;
> +	}
> +
> +	init.ops = &rockchip_usb_phy480m_ops;
> +	rk_phy->clk480m_hw.init = &init;
> +
> +	rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
> +	if (IS_ERR(rk_phy->clk480m)) {
> +		err = PTR_ERR(rk_phy->clk480m);
> +		goto err_clk;
> +	}
> +
> +	err = of_clk_add_provider(child, of_clk_src_simple_get,
> +				  rk_phy->clk480m);
> +	if (err < 0)
> +		goto err_clk_prov;
> +
> +	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
> +	if (err)
> +		goto err_devm_action;
> +
>  	rk_phy->phy = devm_phy_create(base->dev, child, &ops);
>  	if (IS_ERR(rk_phy->phy)) {
>  		dev_err(base->dev, "failed to create PHY\n");
> @@ -141,13 +232,48 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>  
>  	/* only power up usb phy when it use, so disable it when init*/
>  	return rockchip_usb_phy_power(rk_phy, 1);
> +
> +err_devm_action:
> +	of_clk_del_provider(child);
> +err_clk_prov:
> +	clk_unregister(rk_phy->clk480m);
> +err_clk:
> +	if (rk_phy->clk)
> +		clk_put(rk_phy->clk);
> +	return err;
>  }
>  
> +static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
> +	.phys = (struct rockchip_usb_phys[]){
> +		{ .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
> +		{ .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
> +		{ /* sentinel */ }
> +	},
> +};
> +
> +static const struct rockchip_usb_phy_pdata rk3188_pdata = {
> +	.phys = (struct rockchip_usb_phys[]){
> +		{ .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
> +		{ .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
> +		{ /* sentinel */ }
> +	},
> +};
> +
> +static const struct rockchip_usb_phy_pdata rk3288_pdata = {
> +	.phys = (struct rockchip_usb_phys[]){
> +		{ .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
> +		{ .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
> +		{ .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
> +		{ /* sentinel */ }
> +	},
> +};
> +
>  static int rockchip_usb_phy_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
>  	struct rockchip_usb_phy_base *phy_base;
>  	struct phy_provider *phy_provider;
> +	const struct of_device_id *match;
>  	struct device_node *child;
>  	int err;
>  
> @@ -155,6 +281,14 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>  	if (!phy_base)
>  		return -ENOMEM;
>  
> +	match = of_match_device(dev->driver->of_match_table, dev);
> +	if (!match || !match->data) {
> +		dev_err(dev, "missing phy data\n");
> +		return -EINVAL;
> +	}
> +
> +	phy_base->pdata = match->data;
> +
>  	phy_base->dev = dev;
>  	phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
>  							     "rockchip,grf");
> @@ -176,9 +310,9 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>  }
>  
>  static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
> -	{ .compatible = "rockchip,rk3066a-usb-phy" },
> -	{ .compatible = "rockchip,rk3188-usb-phy" },
> -	{ .compatible = "rockchip,rk3288-usb-phy" },
> +	{ .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
> +	{ .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
> +	{ .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
>  	{}
>  };
>  
> 

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 5/8] phy: rockchip-usb: expose the phy-internal PLLs
@ 2015-12-15 10:53     ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-15 10:53 UTC (permalink / raw)
  To: Heiko Stuebner, mturquette-rdvid1DuHRBWk0Htik3J/w,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: hl-TNX95d0MmH7DzftRWevZcw, arnd-r2nGTMty4D4,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	romain.perier-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Mike,

On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
> The USB phys on Rockchip SoCs contain their own internal PLLs to create
> the 480MHz needed. Additionally this PLL output is also fed back into the
> core clock-controller as possible source for clocks like the GPU or others.
> 
> Until now this was modelled incorrectly with a "virtual" factor clock in
> the clock controller. The one big caveat is that if we turn off the usb phy
> via the siddq signal, all analog components get turned off, including the
> PLLs. It is therefore possible that a source clock gets disabled without
> the clock driver ever knowing, possibly making the system hang.
> 
> Therefore register the phy-plls as real clocks that the clock driver can
> then reference again normally, making the clock hirarchy finally reflect
> the actual hardware.
> 
> The phy-ops get converted to simply turning that new clock on and off
> which in turn controls the siddq signal of the phy.
> 
> Through this the driver gains handling for platform-specific data, to
> handle the phy->clock name association.

Are you okay with this patch/ Can you give your Acked-by?

Thanks
Kishon

> 
> Signed-off-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
> Reviewed-by: Douglas Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> ---
>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   1 +
>  drivers/phy/phy-rockchip-usb.c                     | 188 ++++++++++++++++++---
>  2 files changed, 162 insertions(+), 27 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> index 9b37242..68498d5 100644
> --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> @@ -24,6 +24,7 @@ required properties:
>  Optional Properties:
>  - clocks : phandle + clock specifier for the phy clocks
>  - clock-names: string, clock name, must be "phyclk"
> +- #clock-cells: for users of the phy-pll, should be 0
>  
>  Example:
>  
> diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
> index 16cd533..33a80eb 100644
> --- a/drivers/phy/phy-rockchip-usb.c
> +++ b/drivers/phy/phy-rockchip-usb.c
> @@ -15,12 +15,14 @@
>   */
>  
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/io.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/of.h>
>  #include <linux/of_address.h>
> +#include <linux/of_platform.h>
>  #include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
> @@ -36,15 +38,28 @@
>  #define SIDDQ_ON		BIT(13)
>  #define SIDDQ_OFF		(0 << 13)
>  
> +struct rockchip_usb_phys {
> +	int reg;
> +	const char *pll_name;
> +};
> +
> +struct rockchip_usb_phy_pdata {
> +	struct rockchip_usb_phys *phys;
> +};
> +
>  struct rockchip_usb_phy_base {
>  	struct device *dev;
>  	struct regmap *reg_base;
> +	const struct rockchip_usb_phy_pdata *pdata;
>  };
>  
>  struct rockchip_usb_phy {
>  	struct rockchip_usb_phy_base *base;
> +	struct device_node *np;
>  	unsigned int	reg_offset;
>  	struct clk	*clk;
> +	struct clk      *clk480m;
> +	struct clk_hw	clk480m_hw;
>  	struct phy	*phy;
>  };
>  
> @@ -55,17 +70,59 @@ static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
>  			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
>  }
>  
> -static int rockchip_usb_phy_power_off(struct phy *_phy)
> +static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
> +						unsigned long parent_rate)
>  {
> -	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
> -	int ret = 0;
> +	return 480000000;
> +}
> +
> +static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
> +{
> +	struct rockchip_usb_phy *phy = container_of(hw,
> +						    struct rockchip_usb_phy,
> +						    clk480m_hw);
>  
>  	/* Power down usb phy analog blocks by set siddq 1 */
> -	ret = rockchip_usb_phy_power(phy, 1);
> -	if (ret)
> +	rockchip_usb_phy_power(phy, 1);
> +}
> +
> +static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
> +{
> +	struct rockchip_usb_phy *phy = container_of(hw,
> +						    struct rockchip_usb_phy,
> +						    clk480m_hw);
> +
> +	/* Power up usb phy analog blocks by set siddq 0 */
> +	return rockchip_usb_phy_power(phy, 0);
> +}
> +
> +static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
> +{
> +	struct rockchip_usb_phy *phy = container_of(hw,
> +						    struct rockchip_usb_phy,
> +						    clk480m_hw);
> +	int ret;
> +	u32 val;
> +
> +	ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
> +	if (ret < 0)
>  		return ret;
>  
> -	clk_disable_unprepare(phy->clk);
> +	return (val & SIDDQ_ON) ? 0 : 1;
> +}
> +
> +static const struct clk_ops rockchip_usb_phy480m_ops = {
> +	.enable = rockchip_usb_phy480m_enable,
> +	.disable = rockchip_usb_phy480m_disable,
> +	.is_enabled = rockchip_usb_phy480m_is_enabled,
> +	.recalc_rate = rockchip_usb_phy480m_recalc_rate,
> +};
> +
> +static int rockchip_usb_phy_power_off(struct phy *_phy)
> +{
> +	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
> +
> +	clk_disable_unprepare(phy->clk480m);
>  
>  	return 0;
>  }
> @@ -73,20 +130,8 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
>  static int rockchip_usb_phy_power_on(struct phy *_phy)
>  {
>  	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
> -	int ret = 0;
>  
> -	ret = clk_prepare_enable(phy->clk);
> -	if (ret)
> -		return ret;
> -
> -	/* Power up usb phy analog blocks by set siddq 0 */
> -	ret = rockchip_usb_phy_power(phy, 0);
> -	if (ret) {
> -		clk_disable_unprepare(phy->clk);
> -		return ret;
> -	}
> -
> -	return 0;
> +	return clk_prepare_enable(phy->clk480m);
>  }
>  
>  static const struct phy_ops ops = {
> @@ -99,6 +144,9 @@ static void rockchip_usb_phy_action(void *data)
>  {
>  	struct rockchip_usb_phy *rk_phy = data;
>  
> +	of_clk_del_provider(rk_phy->np);
> +	clk_unregister(rk_phy->clk480m);
> +
>  	if (rk_phy->clk)
>  		clk_put(rk_phy->clk);
>  }
> @@ -108,13 +156,16 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>  {
>  	struct rockchip_usb_phy *rk_phy;
>  	unsigned int reg_offset;
> -	int err;
> +	const char *clk_name;
> +	struct clk_init_data init;
> +	int err, i;
>  
>  	rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
>  	if (!rk_phy)
>  		return -ENOMEM;
>  
>  	rk_phy->base = base;
> +	rk_phy->np = child;
>  
>  	if (of_property_read_u32(child, "reg", &reg_offset)) {
>  		dev_err(base->dev, "missing reg property in node %s\n",
> @@ -124,14 +175,54 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>  
>  	rk_phy->reg_offset = reg_offset;
>  
> -	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
> -	if (err)
> -		return err;
> -
>  	rk_phy->clk = of_clk_get_by_name(child, "phyclk");
>  	if (IS_ERR(rk_phy->clk))
>  		rk_phy->clk = NULL;
>  
> +	i = 0;
> +	init.name = NULL;
> +	while (base->pdata->phys[i].reg) {
> +		if (base->pdata->phys[i].reg == reg_offset) {
> +			init.name = base->pdata->phys[i].pll_name;
> +			break;
> +		}
> +		i++;
> +	}
> +
> +	if (!init.name) {
> +		dev_err(base->dev, "phy data not found\n");
> +		return -EINVAL;
> +	}
> +
> +	if (rk_phy->clk) {
> +		clk_name = __clk_get_name(rk_phy->clk);
> +		init.flags = 0;
> +		init.parent_names = &clk_name;
> +		init.num_parents = 1;
> +	} else {
> +		init.flags = CLK_IS_ROOT;
> +		init.parent_names = NULL;
> +		init.num_parents = 0;
> +	}
> +
> +	init.ops = &rockchip_usb_phy480m_ops;
> +	rk_phy->clk480m_hw.init = &init;
> +
> +	rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
> +	if (IS_ERR(rk_phy->clk480m)) {
> +		err = PTR_ERR(rk_phy->clk480m);
> +		goto err_clk;
> +	}
> +
> +	err = of_clk_add_provider(child, of_clk_src_simple_get,
> +				  rk_phy->clk480m);
> +	if (err < 0)
> +		goto err_clk_prov;
> +
> +	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
> +	if (err)
> +		goto err_devm_action;
> +
>  	rk_phy->phy = devm_phy_create(base->dev, child, &ops);
>  	if (IS_ERR(rk_phy->phy)) {
>  		dev_err(base->dev, "failed to create PHY\n");
> @@ -141,13 +232,48 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>  
>  	/* only power up usb phy when it use, so disable it when init*/
>  	return rockchip_usb_phy_power(rk_phy, 1);
> +
> +err_devm_action:
> +	of_clk_del_provider(child);
> +err_clk_prov:
> +	clk_unregister(rk_phy->clk480m);
> +err_clk:
> +	if (rk_phy->clk)
> +		clk_put(rk_phy->clk);
> +	return err;
>  }
>  
> +static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
> +	.phys = (struct rockchip_usb_phys[]){
> +		{ .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
> +		{ .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
> +		{ /* sentinel */ }
> +	},
> +};
> +
> +static const struct rockchip_usb_phy_pdata rk3188_pdata = {
> +	.phys = (struct rockchip_usb_phys[]){
> +		{ .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
> +		{ .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
> +		{ /* sentinel */ }
> +	},
> +};
> +
> +static const struct rockchip_usb_phy_pdata rk3288_pdata = {
> +	.phys = (struct rockchip_usb_phys[]){
> +		{ .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
> +		{ .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
> +		{ .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
> +		{ /* sentinel */ }
> +	},
> +};
> +
>  static int rockchip_usb_phy_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
>  	struct rockchip_usb_phy_base *phy_base;
>  	struct phy_provider *phy_provider;
> +	const struct of_device_id *match;
>  	struct device_node *child;
>  	int err;
>  
> @@ -155,6 +281,14 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>  	if (!phy_base)
>  		return -ENOMEM;
>  
> +	match = of_match_device(dev->driver->of_match_table, dev);
> +	if (!match || !match->data) {
> +		dev_err(dev, "missing phy data\n");
> +		return -EINVAL;
> +	}
> +
> +	phy_base->pdata = match->data;
> +
>  	phy_base->dev = dev;
>  	phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
>  							     "rockchip,grf");
> @@ -176,9 +310,9 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>  }
>  
>  static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
> -	{ .compatible = "rockchip,rk3066a-usb-phy" },
> -	{ .compatible = "rockchip,rk3188-usb-phy" },
> -	{ .compatible = "rockchip,rk3288-usb-phy" },
> +	{ .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
> +	{ .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
> +	{ .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
>  	{}
>  };
>  
> 

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 5/8] phy: rockchip-usb: expose the phy-internal PLLs
@ 2015-12-15 10:53     ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-15 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mike,

On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
> The USB phys on Rockchip SoCs contain their own internal PLLs to create
> the 480MHz needed. Additionally this PLL output is also fed back into the
> core clock-controller as possible source for clocks like the GPU or others.
> 
> Until now this was modelled incorrectly with a "virtual" factor clock in
> the clock controller. The one big caveat is that if we turn off the usb phy
> via the siddq signal, all analog components get turned off, including the
> PLLs. It is therefore possible that a source clock gets disabled without
> the clock driver ever knowing, possibly making the system hang.
> 
> Therefore register the phy-plls as real clocks that the clock driver can
> then reference again normally, making the clock hirarchy finally reflect
> the actual hardware.
> 
> The phy-ops get converted to simply turning that new clock on and off
> which in turn controls the siddq signal of the phy.
> 
> Through this the driver gains handling for platform-specific data, to
> handle the phy->clock name association.

Are you okay with this patch/ Can you give your Acked-by?

Thanks
Kishon

> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>
> ---
>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   1 +
>  drivers/phy/phy-rockchip-usb.c                     | 188 ++++++++++++++++++---
>  2 files changed, 162 insertions(+), 27 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> index 9b37242..68498d5 100644
> --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
> @@ -24,6 +24,7 @@ required properties:
>  Optional Properties:
>  - clocks : phandle + clock specifier for the phy clocks
>  - clock-names: string, clock name, must be "phyclk"
> +- #clock-cells: for users of the phy-pll, should be 0
>  
>  Example:
>  
> diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
> index 16cd533..33a80eb 100644
> --- a/drivers/phy/phy-rockchip-usb.c
> +++ b/drivers/phy/phy-rockchip-usb.c
> @@ -15,12 +15,14 @@
>   */
>  
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/io.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/of.h>
>  #include <linux/of_address.h>
> +#include <linux/of_platform.h>
>  #include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
> @@ -36,15 +38,28 @@
>  #define SIDDQ_ON		BIT(13)
>  #define SIDDQ_OFF		(0 << 13)
>  
> +struct rockchip_usb_phys {
> +	int reg;
> +	const char *pll_name;
> +};
> +
> +struct rockchip_usb_phy_pdata {
> +	struct rockchip_usb_phys *phys;
> +};
> +
>  struct rockchip_usb_phy_base {
>  	struct device *dev;
>  	struct regmap *reg_base;
> +	const struct rockchip_usb_phy_pdata *pdata;
>  };
>  
>  struct rockchip_usb_phy {
>  	struct rockchip_usb_phy_base *base;
> +	struct device_node *np;
>  	unsigned int	reg_offset;
>  	struct clk	*clk;
> +	struct clk      *clk480m;
> +	struct clk_hw	clk480m_hw;
>  	struct phy	*phy;
>  };
>  
> @@ -55,17 +70,59 @@ static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
>  			    SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
>  }
>  
> -static int rockchip_usb_phy_power_off(struct phy *_phy)
> +static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
> +						unsigned long parent_rate)
>  {
> -	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
> -	int ret = 0;
> +	return 480000000;
> +}
> +
> +static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
> +{
> +	struct rockchip_usb_phy *phy = container_of(hw,
> +						    struct rockchip_usb_phy,
> +						    clk480m_hw);
>  
>  	/* Power down usb phy analog blocks by set siddq 1 */
> -	ret = rockchip_usb_phy_power(phy, 1);
> -	if (ret)
> +	rockchip_usb_phy_power(phy, 1);
> +}
> +
> +static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
> +{
> +	struct rockchip_usb_phy *phy = container_of(hw,
> +						    struct rockchip_usb_phy,
> +						    clk480m_hw);
> +
> +	/* Power up usb phy analog blocks by set siddq 0 */
> +	return rockchip_usb_phy_power(phy, 0);
> +}
> +
> +static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
> +{
> +	struct rockchip_usb_phy *phy = container_of(hw,
> +						    struct rockchip_usb_phy,
> +						    clk480m_hw);
> +	int ret;
> +	u32 val;
> +
> +	ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
> +	if (ret < 0)
>  		return ret;
>  
> -	clk_disable_unprepare(phy->clk);
> +	return (val & SIDDQ_ON) ? 0 : 1;
> +}
> +
> +static const struct clk_ops rockchip_usb_phy480m_ops = {
> +	.enable = rockchip_usb_phy480m_enable,
> +	.disable = rockchip_usb_phy480m_disable,
> +	.is_enabled = rockchip_usb_phy480m_is_enabled,
> +	.recalc_rate = rockchip_usb_phy480m_recalc_rate,
> +};
> +
> +static int rockchip_usb_phy_power_off(struct phy *_phy)
> +{
> +	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
> +
> +	clk_disable_unprepare(phy->clk480m);
>  
>  	return 0;
>  }
> @@ -73,20 +130,8 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
>  static int rockchip_usb_phy_power_on(struct phy *_phy)
>  {
>  	struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
> -	int ret = 0;
>  
> -	ret = clk_prepare_enable(phy->clk);
> -	if (ret)
> -		return ret;
> -
> -	/* Power up usb phy analog blocks by set siddq 0 */
> -	ret = rockchip_usb_phy_power(phy, 0);
> -	if (ret) {
> -		clk_disable_unprepare(phy->clk);
> -		return ret;
> -	}
> -
> -	return 0;
> +	return clk_prepare_enable(phy->clk480m);
>  }
>  
>  static const struct phy_ops ops = {
> @@ -99,6 +144,9 @@ static void rockchip_usb_phy_action(void *data)
>  {
>  	struct rockchip_usb_phy *rk_phy = data;
>  
> +	of_clk_del_provider(rk_phy->np);
> +	clk_unregister(rk_phy->clk480m);
> +
>  	if (rk_phy->clk)
>  		clk_put(rk_phy->clk);
>  }
> @@ -108,13 +156,16 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>  {
>  	struct rockchip_usb_phy *rk_phy;
>  	unsigned int reg_offset;
> -	int err;
> +	const char *clk_name;
> +	struct clk_init_data init;
> +	int err, i;
>  
>  	rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
>  	if (!rk_phy)
>  		return -ENOMEM;
>  
>  	rk_phy->base = base;
> +	rk_phy->np = child;
>  
>  	if (of_property_read_u32(child, "reg", &reg_offset)) {
>  		dev_err(base->dev, "missing reg property in node %s\n",
> @@ -124,14 +175,54 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>  
>  	rk_phy->reg_offset = reg_offset;
>  
> -	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
> -	if (err)
> -		return err;
> -
>  	rk_phy->clk = of_clk_get_by_name(child, "phyclk");
>  	if (IS_ERR(rk_phy->clk))
>  		rk_phy->clk = NULL;
>  
> +	i = 0;
> +	init.name = NULL;
> +	while (base->pdata->phys[i].reg) {
> +		if (base->pdata->phys[i].reg == reg_offset) {
> +			init.name = base->pdata->phys[i].pll_name;
> +			break;
> +		}
> +		i++;
> +	}
> +
> +	if (!init.name) {
> +		dev_err(base->dev, "phy data not found\n");
> +		return -EINVAL;
> +	}
> +
> +	if (rk_phy->clk) {
> +		clk_name = __clk_get_name(rk_phy->clk);
> +		init.flags = 0;
> +		init.parent_names = &clk_name;
> +		init.num_parents = 1;
> +	} else {
> +		init.flags = CLK_IS_ROOT;
> +		init.parent_names = NULL;
> +		init.num_parents = 0;
> +	}
> +
> +	init.ops = &rockchip_usb_phy480m_ops;
> +	rk_phy->clk480m_hw.init = &init;
> +
> +	rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
> +	if (IS_ERR(rk_phy->clk480m)) {
> +		err = PTR_ERR(rk_phy->clk480m);
> +		goto err_clk;
> +	}
> +
> +	err = of_clk_add_provider(child, of_clk_src_simple_get,
> +				  rk_phy->clk480m);
> +	if (err < 0)
> +		goto err_clk_prov;
> +
> +	err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
> +	if (err)
> +		goto err_devm_action;
> +
>  	rk_phy->phy = devm_phy_create(base->dev, child, &ops);
>  	if (IS_ERR(rk_phy->phy)) {
>  		dev_err(base->dev, "failed to create PHY\n");
> @@ -141,13 +232,48 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>  
>  	/* only power up usb phy when it use, so disable it when init*/
>  	return rockchip_usb_phy_power(rk_phy, 1);
> +
> +err_devm_action:
> +	of_clk_del_provider(child);
> +err_clk_prov:
> +	clk_unregister(rk_phy->clk480m);
> +err_clk:
> +	if (rk_phy->clk)
> +		clk_put(rk_phy->clk);
> +	return err;
>  }
>  
> +static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
> +	.phys = (struct rockchip_usb_phys[]){
> +		{ .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
> +		{ .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
> +		{ /* sentinel */ }
> +	},
> +};
> +
> +static const struct rockchip_usb_phy_pdata rk3188_pdata = {
> +	.phys = (struct rockchip_usb_phys[]){
> +		{ .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
> +		{ .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
> +		{ /* sentinel */ }
> +	},
> +};
> +
> +static const struct rockchip_usb_phy_pdata rk3288_pdata = {
> +	.phys = (struct rockchip_usb_phys[]){
> +		{ .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
> +		{ .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
> +		{ .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
> +		{ /* sentinel */ }
> +	},
> +};
> +
>  static int rockchip_usb_phy_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
>  	struct rockchip_usb_phy_base *phy_base;
>  	struct phy_provider *phy_provider;
> +	const struct of_device_id *match;
>  	struct device_node *child;
>  	int err;
>  
> @@ -155,6 +281,14 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>  	if (!phy_base)
>  		return -ENOMEM;
>  
> +	match = of_match_device(dev->driver->of_match_table, dev);
> +	if (!match || !match->data) {
> +		dev_err(dev, "missing phy data\n");
> +		return -EINVAL;
> +	}
> +
> +	phy_base->pdata = match->data;
> +
>  	phy_base->dev = dev;
>  	phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
>  							     "rockchip,grf");
> @@ -176,9 +310,9 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>  }
>  
>  static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
> -	{ .compatible = "rockchip,rk3066a-usb-phy" },
> -	{ .compatible = "rockchip,rk3188-usb-phy" },
> -	{ .compatible = "rockchip,rk3288-usb-phy" },
> +	{ .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
> +	{ .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
> +	{ .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
>  	{}
>  };
>  
> 

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
  2015-12-15 10:52     ` Kishon Vijay Abraham I
@ 2015-12-19 17:21       ` Heiko Stübner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2015-12-19 17:21 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: mturquette, sboyd, linux-arm-kernel, linux-kernel,
	linux-rockchip, dianders, romain.perier, arnd, hl

Hi Kishon,

Am Dienstag, 15. Dezember 2015, 16:22:32 schrieb Kishon Vijay Abraham I:
> On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
> > The otgphy clocks really only drive the phy blocks. These in turn
> > contain plls that then generate the 480m clocks the clock controller
> > uses to supply some other clocks like uart0, gpu or the video-codec.
> > 
> > So fix this structure to actually respect that hirarchy and removed
> > that usb480m fixed-rate clock working as a placeholder till now, as
> > this wouldn't even work if the supplying phy gets turned off while
> > its pll-output gets used elsewhere.
> > 
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > Reviewed-by: Douglas Anderson <dianders@chromium.org>
> 
> I saw you've given your Acked-by in a previous version of this patch.
> Do you want me to take this in linux-phy tree?

from my POV, this series should probably go through your tree in one go, as 
this patch depends on the newly exposed clocks from the previous patch. So to 
keep bisectability, it should most likely stay together.


Heiko

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
@ 2015-12-19 17:21       ` Heiko Stübner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2015-12-19 17:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kishon,

Am Dienstag, 15. Dezember 2015, 16:22:32 schrieb Kishon Vijay Abraham I:
> On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
> > The otgphy clocks really only drive the phy blocks. These in turn
> > contain plls that then generate the 480m clocks the clock controller
> > uses to supply some other clocks like uart0, gpu or the video-codec.
> > 
> > So fix this structure to actually respect that hirarchy and removed
> > that usb480m fixed-rate clock working as a placeholder till now, as
> > this wouldn't even work if the supplying phy gets turned off while
> > its pll-output gets used elsewhere.
> > 
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > Reviewed-by: Douglas Anderson <dianders@chromium.org>
> 
> I saw you've given your Acked-by in a previous version of this patch.
> Do you want me to take this in linux-phy tree?

from my POV, this series should probably go through your tree in one go, as 
this patch depends on the newly exposed clocks from the previous patch. So to 
keep bisectability, it should most likely stay together.


Heiko

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
  2015-12-19 17:21       ` Heiko Stübner
  (?)
@ 2015-12-20  9:09         ` Kishon Vijay Abraham I
  -1 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-20  9:09 UTC (permalink / raw)
  To: Heiko Stübner, mturquette
  Cc: sboyd, linux-arm-kernel, linux-kernel, linux-rockchip, dianders,
	romain.perier, arnd, hl

Hi,

On Saturday 19 December 2015 10:51 PM, Heiko Stübner wrote:
> Hi Kishon,
> 
> Am Dienstag, 15. Dezember 2015, 16:22:32 schrieb Kishon Vijay Abraham I:
>> On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
>>> The otgphy clocks really only drive the phy blocks. These in turn
>>> contain plls that then generate the 480m clocks the clock controller
>>> uses to supply some other clocks like uart0, gpu or the video-codec.
>>>
>>> So fix this structure to actually respect that hirarchy and removed
>>> that usb480m fixed-rate clock working as a placeholder till now, as
>>> this wouldn't even work if the supplying phy gets turned off while
>>> its pll-output gets used elsewhere.
>>>
>>> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>>> Reviewed-by: Douglas Anderson <dianders@chromium.org>
>>
>> I saw you've given your Acked-by in a previous version of this patch.
>> Do you want me to take this in linux-phy tree?
> 
> from my POV, this series should probably go through your tree in one go, as 
> this patch depends on the newly exposed clocks from the previous patch. So to 
> keep bisectability, it should most likely stay together.

I agree. But I can't take another subsystem patch without getting a clear nod
from the maintainer. I'll wait till tomorrow for Turquette to give his Acked-by.

Thanks
Kishon

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
@ 2015-12-20  9:09         ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-20  9:09 UTC (permalink / raw)
  To: Heiko Stübner, mturquette-rdvid1DuHRBWk0Htik3J/w
  Cc: hl-TNX95d0MmH7DzftRWevZcw, arnd-r2nGTMty4D4,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dianders-F7+t8E8rja9g9hUCZPvPmw,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	romain.perier-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi,

On Saturday 19 December 2015 10:51 PM, Heiko Stübner wrote:
> Hi Kishon,
> 
> Am Dienstag, 15. Dezember 2015, 16:22:32 schrieb Kishon Vijay Abraham I:
>> On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
>>> The otgphy clocks really only drive the phy blocks. These in turn
>>> contain plls that then generate the 480m clocks the clock controller
>>> uses to supply some other clocks like uart0, gpu or the video-codec.
>>>
>>> So fix this structure to actually respect that hirarchy and removed
>>> that usb480m fixed-rate clock working as a placeholder till now, as
>>> this wouldn't even work if the supplying phy gets turned off while
>>> its pll-output gets used elsewhere.
>>>
>>> Signed-off-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
>>> Reviewed-by: Douglas Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
>>
>> I saw you've given your Acked-by in a previous version of this patch.
>> Do you want me to take this in linux-phy tree?
> 
> from my POV, this series should probably go through your tree in one go, as 
> this patch depends on the newly exposed clocks from the previous patch. So to 
> keep bisectability, it should most likely stay together.

I agree. But I can't take another subsystem patch without getting a clear nod
from the maintainer. I'll wait till tomorrow for Turquette to give his Acked-by.

Thanks
Kishon

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
@ 2015-12-20  9:09         ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 67+ messages in thread
From: Kishon Vijay Abraham I @ 2015-12-20  9:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Saturday 19 December 2015 10:51 PM, Heiko St?bner wrote:
> Hi Kishon,
> 
> Am Dienstag, 15. Dezember 2015, 16:22:32 schrieb Kishon Vijay Abraham I:
>> On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
>>> The otgphy clocks really only drive the phy blocks. These in turn
>>> contain plls that then generate the 480m clocks the clock controller
>>> uses to supply some other clocks like uart0, gpu or the video-codec.
>>>
>>> So fix this structure to actually respect that hirarchy and removed
>>> that usb480m fixed-rate clock working as a placeholder till now, as
>>> this wouldn't even work if the supplying phy gets turned off while
>>> its pll-output gets used elsewhere.
>>>
>>> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>>> Reviewed-by: Douglas Anderson <dianders@chromium.org>
>>
>> I saw you've given your Acked-by in a previous version of this patch.
>> Do you want me to take this in linux-phy tree?
> 
> from my POV, this series should probably go through your tree in one go, as 
> this patch depends on the newly exposed clocks from the previous patch. So to 
> keep bisectability, it should most likely stay together.

I agree. But I can't take another subsystem patch without getting a clear nod
from the maintainer. I'll wait till tomorrow for Turquette to give his Acked-by.

Thanks
Kishon

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 5/8] phy: rockchip-usb: expose the phy-internal PLLs
  2015-12-15 10:53     ` Kishon Vijay Abraham I
  (?)
@ 2015-12-21 20:00       ` Michael Turquette
  -1 siblings, 0 replies; 67+ messages in thread
From: Michael Turquette @ 2015-12-21 20:00 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: Heiko Stuebner, Stephen Boyd,
	Stephen Boyd <sboyd@codeaurora.org>,
	Emilio Lopez <emilio@elopez.com.ar>,
	Hans de Goede <hdegoede@redhat.com>,
	linux-clk <linux-clk@vger.kernel.org>,
	linux-arm-kernel, Linux Kernel Mailing List,
	open list:ARM/Rockchip SoC...,
	Doug Anderson, Romain Perier, Arnd Bergmann, Lin Huang

Kishon & Heiko,

On Tue, Dec 15, 2015 at 2:53 AM, Kishon Vijay Abraham I <kishon@ti.com> wrote:
> Hi Mike,
>
> On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
>> The USB phys on Rockchip SoCs contain their own internal PLLs to create
>> the 480MHz needed. Additionally this PLL output is also fed back into the
>> core clock-controller as possible source for clocks like the GPU or others.
>>
>> Until now this was modelled incorrectly with a "virtual" factor clock in
>> the clock controller. The one big caveat is that if we turn off the usb phy
>> via the siddq signal, all analog components get turned off, including the
>> PLLs. It is therefore possible that a source clock gets disabled without
>> the clock driver ever knowing, possibly making the system hang.
>>
>> Therefore register the phy-plls as real clocks that the clock driver can
>> then reference again normally, making the clock hirarchy finally reflect
>> the actual hardware.
>>
>> The phy-ops get converted to simply turning that new clock on and off
>> which in turn controls the siddq signal of the phy.
>>
>> Through this the driver gains handling for platform-specific data, to
>> handle the phy->clock name association.
>
> Are you okay with this patch/ Can you give your Acked-by?

Acked-by: Michael Turquette <mturquette@baylibre.com>

>
> Thanks
> Kishon
>
>>
>> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> Reviewed-by: Douglas Anderson <dianders@chromium.org>
>> ---
>>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   1 +
>>  drivers/phy/phy-rockchip-usb.c                     | 188 ++++++++++++++++++---
>>  2 files changed, 162 insertions(+), 27 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> index 9b37242..68498d5 100644
>> --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> @@ -24,6 +24,7 @@ required properties:
>>  Optional Properties:
>>  - clocks : phandle + clock specifier for the phy clocks
>>  - clock-names: string, clock name, must be "phyclk"
>> +- #clock-cells: for users of the phy-pll, should be 0
>>
>>  Example:
>>
>> diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
>> index 16cd533..33a80eb 100644
>> --- a/drivers/phy/phy-rockchip-usb.c
>> +++ b/drivers/phy/phy-rockchip-usb.c
>> @@ -15,12 +15,14 @@
>>   */
>>
>>  #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>  #include <linux/io.h>
>>  #include <linux/kernel.h>
>>  #include <linux/module.h>
>>  #include <linux/mutex.h>
>>  #include <linux/of.h>
>>  #include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>>  #include <linux/phy/phy.h>
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>> @@ -36,15 +38,28 @@
>>  #define SIDDQ_ON             BIT(13)
>>  #define SIDDQ_OFF            (0 << 13)
>>
>> +struct rockchip_usb_phys {
>> +     int reg;
>> +     const char *pll_name;
>> +};
>> +
>> +struct rockchip_usb_phy_pdata {
>> +     struct rockchip_usb_phys *phys;
>> +};
>> +
>>  struct rockchip_usb_phy_base {
>>       struct device *dev;
>>       struct regmap *reg_base;
>> +     const struct rockchip_usb_phy_pdata *pdata;
>>  };
>>
>>  struct rockchip_usb_phy {
>>       struct rockchip_usb_phy_base *base;
>> +     struct device_node *np;
>>       unsigned int    reg_offset;
>>       struct clk      *clk;
>> +     struct clk      *clk480m;
>> +     struct clk_hw   clk480m_hw;
>>       struct phy      *phy;
>>  };
>>
>> @@ -55,17 +70,59 @@ static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
>>                           SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
>>  }
>>
>> -static int rockchip_usb_phy_power_off(struct phy *_phy)
>> +static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
>> +                                             unsigned long parent_rate)
>>  {
>> -     struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
>> -     int ret = 0;
>> +     return 480000000;
>> +}
>> +
>> +static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
>> +{
>> +     struct rockchip_usb_phy *phy = container_of(hw,
>> +                                                 struct rockchip_usb_phy,
>> +                                                 clk480m_hw);
>>
>>       /* Power down usb phy analog blocks by set siddq 1 */
>> -     ret = rockchip_usb_phy_power(phy, 1);
>> -     if (ret)
>> +     rockchip_usb_phy_power(phy, 1);
>> +}
>> +
>> +static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
>> +{
>> +     struct rockchip_usb_phy *phy = container_of(hw,
>> +                                                 struct rockchip_usb_phy,
>> +                                                 clk480m_hw);
>> +
>> +     /* Power up usb phy analog blocks by set siddq 0 */
>> +     return rockchip_usb_phy_power(phy, 0);
>> +}
>> +
>> +static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
>> +{
>> +     struct rockchip_usb_phy *phy = container_of(hw,
>> +                                                 struct rockchip_usb_phy,
>> +                                                 clk480m_hw);
>> +     int ret;
>> +     u32 val;
>> +
>> +     ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
>> +     if (ret < 0)
>>               return ret;
>>
>> -     clk_disable_unprepare(phy->clk);
>> +     return (val & SIDDQ_ON) ? 0 : 1;
>> +}
>> +
>> +static const struct clk_ops rockchip_usb_phy480m_ops = {
>> +     .enable = rockchip_usb_phy480m_enable,
>> +     .disable = rockchip_usb_phy480m_disable,
>> +     .is_enabled = rockchip_usb_phy480m_is_enabled,
>> +     .recalc_rate = rockchip_usb_phy480m_recalc_rate,
>> +};
>> +
>> +static int rockchip_usb_phy_power_off(struct phy *_phy)
>> +{
>> +     struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
>> +
>> +     clk_disable_unprepare(phy->clk480m);
>>
>>       return 0;
>>  }
>> @@ -73,20 +130,8 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
>>  static int rockchip_usb_phy_power_on(struct phy *_phy)
>>  {
>>       struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
>> -     int ret = 0;
>>
>> -     ret = clk_prepare_enable(phy->clk);
>> -     if (ret)
>> -             return ret;
>> -
>> -     /* Power up usb phy analog blocks by set siddq 0 */
>> -     ret = rockchip_usb_phy_power(phy, 0);
>> -     if (ret) {
>> -             clk_disable_unprepare(phy->clk);
>> -             return ret;
>> -     }
>> -
>> -     return 0;
>> +     return clk_prepare_enable(phy->clk480m);
>>  }
>>
>>  static const struct phy_ops ops = {
>> @@ -99,6 +144,9 @@ static void rockchip_usb_phy_action(void *data)
>>  {
>>       struct rockchip_usb_phy *rk_phy = data;
>>
>> +     of_clk_del_provider(rk_phy->np);
>> +     clk_unregister(rk_phy->clk480m);
>> +
>>       if (rk_phy->clk)
>>               clk_put(rk_phy->clk);
>>  }
>> @@ -108,13 +156,16 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>>  {
>>       struct rockchip_usb_phy *rk_phy;
>>       unsigned int reg_offset;
>> -     int err;
>> +     const char *clk_name;
>> +     struct clk_init_data init;
>> +     int err, i;
>>
>>       rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
>>       if (!rk_phy)
>>               return -ENOMEM;
>>
>>       rk_phy->base = base;
>> +     rk_phy->np = child;
>>
>>       if (of_property_read_u32(child, "reg", &reg_offset)) {
>>               dev_err(base->dev, "missing reg property in node %s\n",
>> @@ -124,14 +175,54 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>>
>>       rk_phy->reg_offset = reg_offset;
>>
>> -     err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
>> -     if (err)
>> -             return err;
>> -
>>       rk_phy->clk = of_clk_get_by_name(child, "phyclk");
>>       if (IS_ERR(rk_phy->clk))
>>               rk_phy->clk = NULL;
>>
>> +     i = 0;
>> +     init.name = NULL;
>> +     while (base->pdata->phys[i].reg) {
>> +             if (base->pdata->phys[i].reg == reg_offset) {
>> +                     init.name = base->pdata->phys[i].pll_name;
>> +                     break;
>> +             }
>> +             i++;
>> +     }
>> +
>> +     if (!init.name) {
>> +             dev_err(base->dev, "phy data not found\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     if (rk_phy->clk) {
>> +             clk_name = __clk_get_name(rk_phy->clk);
>> +             init.flags = 0;
>> +             init.parent_names = &clk_name;
>> +             init.num_parents = 1;
>> +     } else {
>> +             init.flags = CLK_IS_ROOT;
>> +             init.parent_names = NULL;
>> +             init.num_parents = 0;
>> +     }
>> +
>> +     init.ops = &rockchip_usb_phy480m_ops;
>> +     rk_phy->clk480m_hw.init = &init;
>> +
>> +     rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
>> +     if (IS_ERR(rk_phy->clk480m)) {
>> +             err = PTR_ERR(rk_phy->clk480m);
>> +             goto err_clk;
>> +     }
>> +
>> +     err = of_clk_add_provider(child, of_clk_src_simple_get,
>> +                               rk_phy->clk480m);
>> +     if (err < 0)
>> +             goto err_clk_prov;
>> +
>> +     err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
>> +     if (err)
>> +             goto err_devm_action;
>> +
>>       rk_phy->phy = devm_phy_create(base->dev, child, &ops);
>>       if (IS_ERR(rk_phy->phy)) {
>>               dev_err(base->dev, "failed to create PHY\n");
>> @@ -141,13 +232,48 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>>
>>       /* only power up usb phy when it use, so disable it when init*/
>>       return rockchip_usb_phy_power(rk_phy, 1);
>> +
>> +err_devm_action:
>> +     of_clk_del_provider(child);
>> +err_clk_prov:
>> +     clk_unregister(rk_phy->clk480m);
>> +err_clk:
>> +     if (rk_phy->clk)
>> +             clk_put(rk_phy->clk);
>> +     return err;
>>  }
>>
>> +static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
>> +     .phys = (struct rockchip_usb_phys[]){
>> +             { .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
>> +             { .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
>> +             { /* sentinel */ }
>> +     },
>> +};
>> +
>> +static const struct rockchip_usb_phy_pdata rk3188_pdata = {
>> +     .phys = (struct rockchip_usb_phys[]){
>> +             { .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
>> +             { .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
>> +             { /* sentinel */ }
>> +     },
>> +};
>> +
>> +static const struct rockchip_usb_phy_pdata rk3288_pdata = {
>> +     .phys = (struct rockchip_usb_phys[]){
>> +             { .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
>> +             { .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
>> +             { .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
>> +             { /* sentinel */ }
>> +     },
>> +};
>> +
>>  static int rockchip_usb_phy_probe(struct platform_device *pdev)
>>  {
>>       struct device *dev = &pdev->dev;
>>       struct rockchip_usb_phy_base *phy_base;
>>       struct phy_provider *phy_provider;
>> +     const struct of_device_id *match;
>>       struct device_node *child;
>>       int err;
>>
>> @@ -155,6 +281,14 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>>       if (!phy_base)
>>               return -ENOMEM;
>>
>> +     match = of_match_device(dev->driver->of_match_table, dev);
>> +     if (!match || !match->data) {
>> +             dev_err(dev, "missing phy data\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     phy_base->pdata = match->data;
>> +
>>       phy_base->dev = dev;
>>       phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
>>                                                            "rockchip,grf");
>> @@ -176,9 +310,9 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>>  }
>>
>>  static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
>> -     { .compatible = "rockchip,rk3066a-usb-phy" },
>> -     { .compatible = "rockchip,rk3188-usb-phy" },
>> -     { .compatible = "rockchip,rk3288-usb-phy" },
>> +     { .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
>> +     { .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
>> +     { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
>>       {}
>>  };
>>
>>



-- 
Michael Turquette
CEO
BayLibre - At the Heart of Embedded Linux
http://baylibre.com/

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 5/8] phy: rockchip-usb: expose the phy-internal PLLs
@ 2015-12-21 20:00       ` Michael Turquette
  0 siblings, 0 replies; 67+ messages in thread
From: Michael Turquette @ 2015-12-21 20:00 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: Heiko Stuebner, Stephen Boyd,
	Stephen Boyd <sboyd@codeaurora.org>,
	Emilio Lopez <emilio@elopez.com.ar>,
	Hans de Goede <hdegoede@redhat.com>,
	linux-clk <linux-clk@vger.kernel.org>,
	linux-arm-kernel, Linux Kernel Mailing List,
	open list:ARM/Rockchip SoC...,
	Doug Anderson, Romain Perier, Arnd Bergmann, Lin Huang

Kishon & Heiko,

On Tue, Dec 15, 2015 at 2:53 AM, Kishon Vijay Abraham I <kishon@ti.com> wrote:
> Hi Mike,
>
> On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
>> The USB phys on Rockchip SoCs contain their own internal PLLs to create
>> the 480MHz needed. Additionally this PLL output is also fed back into the
>> core clock-controller as possible source for clocks like the GPU or others.
>>
>> Until now this was modelled incorrectly with a "virtual" factor clock in
>> the clock controller. The one big caveat is that if we turn off the usb phy
>> via the siddq signal, all analog components get turned off, including the
>> PLLs. It is therefore possible that a source clock gets disabled without
>> the clock driver ever knowing, possibly making the system hang.
>>
>> Therefore register the phy-plls as real clocks that the clock driver can
>> then reference again normally, making the clock hirarchy finally reflect
>> the actual hardware.
>>
>> The phy-ops get converted to simply turning that new clock on and off
>> which in turn controls the siddq signal of the phy.
>>
>> Through this the driver gains handling for platform-specific data, to
>> handle the phy->clock name association.
>
> Are you okay with this patch/ Can you give your Acked-by?

Acked-by: Michael Turquette <mturquette@baylibre.com>

>
> Thanks
> Kishon
>
>>
>> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> Reviewed-by: Douglas Anderson <dianders@chromium.org>
>> ---
>>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   1 +
>>  drivers/phy/phy-rockchip-usb.c                     | 188 ++++++++++++++++++---
>>  2 files changed, 162 insertions(+), 27 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> index 9b37242..68498d5 100644
>> --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> @@ -24,6 +24,7 @@ required properties:
>>  Optional Properties:
>>  - clocks : phandle + clock specifier for the phy clocks
>>  - clock-names: string, clock name, must be "phyclk"
>> +- #clock-cells: for users of the phy-pll, should be 0
>>
>>  Example:
>>
>> diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
>> index 16cd533..33a80eb 100644
>> --- a/drivers/phy/phy-rockchip-usb.c
>> +++ b/drivers/phy/phy-rockchip-usb.c
>> @@ -15,12 +15,14 @@
>>   */
>>
>>  #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>  #include <linux/io.h>
>>  #include <linux/kernel.h>
>>  #include <linux/module.h>
>>  #include <linux/mutex.h>
>>  #include <linux/of.h>
>>  #include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>>  #include <linux/phy/phy.h>
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>> @@ -36,15 +38,28 @@
>>  #define SIDDQ_ON             BIT(13)
>>  #define SIDDQ_OFF            (0 << 13)
>>
>> +struct rockchip_usb_phys {
>> +     int reg;
>> +     const char *pll_name;
>> +};
>> +
>> +struct rockchip_usb_phy_pdata {
>> +     struct rockchip_usb_phys *phys;
>> +};
>> +
>>  struct rockchip_usb_phy_base {
>>       struct device *dev;
>>       struct regmap *reg_base;
>> +     const struct rockchip_usb_phy_pdata *pdata;
>>  };
>>
>>  struct rockchip_usb_phy {
>>       struct rockchip_usb_phy_base *base;
>> +     struct device_node *np;
>>       unsigned int    reg_offset;
>>       struct clk      *clk;
>> +     struct clk      *clk480m;
>> +     struct clk_hw   clk480m_hw;
>>       struct phy      *phy;
>>  };
>>
>> @@ -55,17 +70,59 @@ static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
>>                           SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
>>  }
>>
>> -static int rockchip_usb_phy_power_off(struct phy *_phy)
>> +static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
>> +                                             unsigned long parent_rate)
>>  {
>> -     struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
>> -     int ret = 0;
>> +     return 480000000;
>> +}
>> +
>> +static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
>> +{
>> +     struct rockchip_usb_phy *phy = container_of(hw,
>> +                                                 struct rockchip_usb_phy,
>> +                                                 clk480m_hw);
>>
>>       /* Power down usb phy analog blocks by set siddq 1 */
>> -     ret = rockchip_usb_phy_power(phy, 1);
>> -     if (ret)
>> +     rockchip_usb_phy_power(phy, 1);
>> +}
>> +
>> +static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
>> +{
>> +     struct rockchip_usb_phy *phy = container_of(hw,
>> +                                                 struct rockchip_usb_phy,
>> +                                                 clk480m_hw);
>> +
>> +     /* Power up usb phy analog blocks by set siddq 0 */
>> +     return rockchip_usb_phy_power(phy, 0);
>> +}
>> +
>> +static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
>> +{
>> +     struct rockchip_usb_phy *phy = container_of(hw,
>> +                                                 struct rockchip_usb_phy,
>> +                                                 clk480m_hw);
>> +     int ret;
>> +     u32 val;
>> +
>> +     ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
>> +     if (ret < 0)
>>               return ret;
>>
>> -     clk_disable_unprepare(phy->clk);
>> +     return (val & SIDDQ_ON) ? 0 : 1;
>> +}
>> +
>> +static const struct clk_ops rockchip_usb_phy480m_ops = {
>> +     .enable = rockchip_usb_phy480m_enable,
>> +     .disable = rockchip_usb_phy480m_disable,
>> +     .is_enabled = rockchip_usb_phy480m_is_enabled,
>> +     .recalc_rate = rockchip_usb_phy480m_recalc_rate,
>> +};
>> +
>> +static int rockchip_usb_phy_power_off(struct phy *_phy)
>> +{
>> +     struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
>> +
>> +     clk_disable_unprepare(phy->clk480m);
>>
>>       return 0;
>>  }
>> @@ -73,20 +130,8 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
>>  static int rockchip_usb_phy_power_on(struct phy *_phy)
>>  {
>>       struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
>> -     int ret = 0;
>>
>> -     ret = clk_prepare_enable(phy->clk);
>> -     if (ret)
>> -             return ret;
>> -
>> -     /* Power up usb phy analog blocks by set siddq 0 */
>> -     ret = rockchip_usb_phy_power(phy, 0);
>> -     if (ret) {
>> -             clk_disable_unprepare(phy->clk);
>> -             return ret;
>> -     }
>> -
>> -     return 0;
>> +     return clk_prepare_enable(phy->clk480m);
>>  }
>>
>>  static const struct phy_ops ops = {
>> @@ -99,6 +144,9 @@ static void rockchip_usb_phy_action(void *data)
>>  {
>>       struct rockchip_usb_phy *rk_phy = data;
>>
>> +     of_clk_del_provider(rk_phy->np);
>> +     clk_unregister(rk_phy->clk480m);
>> +
>>       if (rk_phy->clk)
>>               clk_put(rk_phy->clk);
>>  }
>> @@ -108,13 +156,16 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>>  {
>>       struct rockchip_usb_phy *rk_phy;
>>       unsigned int reg_offset;
>> -     int err;
>> +     const char *clk_name;
>> +     struct clk_init_data init;
>> +     int err, i;
>>
>>       rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
>>       if (!rk_phy)
>>               return -ENOMEM;
>>
>>       rk_phy->base = base;
>> +     rk_phy->np = child;
>>
>>       if (of_property_read_u32(child, "reg", &reg_offset)) {
>>               dev_err(base->dev, "missing reg property in node %s\n",
>> @@ -124,14 +175,54 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>>
>>       rk_phy->reg_offset = reg_offset;
>>
>> -     err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
>> -     if (err)
>> -             return err;
>> -
>>       rk_phy->clk = of_clk_get_by_name(child, "phyclk");
>>       if (IS_ERR(rk_phy->clk))
>>               rk_phy->clk = NULL;
>>
>> +     i = 0;
>> +     init.name = NULL;
>> +     while (base->pdata->phys[i].reg) {
>> +             if (base->pdata->phys[i].reg == reg_offset) {
>> +                     init.name = base->pdata->phys[i].pll_name;
>> +                     break;
>> +             }
>> +             i++;
>> +     }
>> +
>> +     if (!init.name) {
>> +             dev_err(base->dev, "phy data not found\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     if (rk_phy->clk) {
>> +             clk_name = __clk_get_name(rk_phy->clk);
>> +             init.flags = 0;
>> +             init.parent_names = &clk_name;
>> +             init.num_parents = 1;
>> +     } else {
>> +             init.flags = CLK_IS_ROOT;
>> +             init.parent_names = NULL;
>> +             init.num_parents = 0;
>> +     }
>> +
>> +     init.ops = &rockchip_usb_phy480m_ops;
>> +     rk_phy->clk480m_hw.init = &init;
>> +
>> +     rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
>> +     if (IS_ERR(rk_phy->clk480m)) {
>> +             err = PTR_ERR(rk_phy->clk480m);
>> +             goto err_clk;
>> +     }
>> +
>> +     err = of_clk_add_provider(child, of_clk_src_simple_get,
>> +                               rk_phy->clk480m);
>> +     if (err < 0)
>> +             goto err_clk_prov;
>> +
>> +     err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
>> +     if (err)
>> +             goto err_devm_action;
>> +
>>       rk_phy->phy = devm_phy_create(base->dev, child, &ops);
>>       if (IS_ERR(rk_phy->phy)) {
>>               dev_err(base->dev, "failed to create PHY\n");
>> @@ -141,13 +232,48 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>>
>>       /* only power up usb phy when it use, so disable it when init*/
>>       return rockchip_usb_phy_power(rk_phy, 1);
>> +
>> +err_devm_action:
>> +     of_clk_del_provider(child);
>> +err_clk_prov:
>> +     clk_unregister(rk_phy->clk480m);
>> +err_clk:
>> +     if (rk_phy->clk)
>> +             clk_put(rk_phy->clk);
>> +     return err;
>>  }
>>
>> +static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
>> +     .phys = (struct rockchip_usb_phys[]){
>> +             { .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
>> +             { .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
>> +             { /* sentinel */ }
>> +     },
>> +};
>> +
>> +static const struct rockchip_usb_phy_pdata rk3188_pdata = {
>> +     .phys = (struct rockchip_usb_phys[]){
>> +             { .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
>> +             { .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
>> +             { /* sentinel */ }
>> +     },
>> +};
>> +
>> +static const struct rockchip_usb_phy_pdata rk3288_pdata = {
>> +     .phys = (struct rockchip_usb_phys[]){
>> +             { .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
>> +             { .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
>> +             { .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
>> +             { /* sentinel */ }
>> +     },
>> +};
>> +
>>  static int rockchip_usb_phy_probe(struct platform_device *pdev)
>>  {
>>       struct device *dev = &pdev->dev;
>>       struct rockchip_usb_phy_base *phy_base;
>>       struct phy_provider *phy_provider;
>> +     const struct of_device_id *match;
>>       struct device_node *child;
>>       int err;
>>
>> @@ -155,6 +281,14 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>>       if (!phy_base)
>>               return -ENOMEM;
>>
>> +     match = of_match_device(dev->driver->of_match_table, dev);
>> +     if (!match || !match->data) {
>> +             dev_err(dev, "missing phy data\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     phy_base->pdata = match->data;
>> +
>>       phy_base->dev = dev;
>>       phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
>>                                                            "rockchip,grf");
>> @@ -176,9 +310,9 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>>  }
>>
>>  static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
>> -     { .compatible = "rockchip,rk3066a-usb-phy" },
>> -     { .compatible = "rockchip,rk3188-usb-phy" },
>> -     { .compatible = "rockchip,rk3288-usb-phy" },
>> +     { .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
>> +     { .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
>> +     { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
>>       {}
>>  };
>>
>>



-- 
Michael Turquette
CEO
BayLibre - At the Heart of Embedded Linux
http://baylibre.com/

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 5/8] phy: rockchip-usb: expose the phy-internal PLLs
@ 2015-12-21 20:00       ` Michael Turquette
  0 siblings, 0 replies; 67+ messages in thread
From: Michael Turquette @ 2015-12-21 20:00 UTC (permalink / raw)
  To: linux-arm-kernel

Kishon & Heiko,

On Tue, Dec 15, 2015 at 2:53 AM, Kishon Vijay Abraham I <kishon@ti.com> wrote:
> Hi Mike,
>
> On Friday 20 November 2015 02:52 AM, Heiko Stuebner wrote:
>> The USB phys on Rockchip SoCs contain their own internal PLLs to create
>> the 480MHz needed. Additionally this PLL output is also fed back into the
>> core clock-controller as possible source for clocks like the GPU or others.
>>
>> Until now this was modelled incorrectly with a "virtual" factor clock in
>> the clock controller. The one big caveat is that if we turn off the usb phy
>> via the siddq signal, all analog components get turned off, including the
>> PLLs. It is therefore possible that a source clock gets disabled without
>> the clock driver ever knowing, possibly making the system hang.
>>
>> Therefore register the phy-plls as real clocks that the clock driver can
>> then reference again normally, making the clock hirarchy finally reflect
>> the actual hardware.
>>
>> The phy-ops get converted to simply turning that new clock on and off
>> which in turn controls the siddq signal of the phy.
>>
>> Through this the driver gains handling for platform-specific data, to
>> handle the phy->clock name association.
>
> Are you okay with this patch/ Can you give your Acked-by?

Acked-by: Michael Turquette <mturquette@baylibre.com>

>
> Thanks
> Kishon
>
>>
>> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> Reviewed-by: Douglas Anderson <dianders@chromium.org>
>> ---
>>  .../devicetree/bindings/phy/rockchip-usb-phy.txt   |   1 +
>>  drivers/phy/phy-rockchip-usb.c                     | 188 ++++++++++++++++++---
>>  2 files changed, 162 insertions(+), 27 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> index 9b37242..68498d5 100644
>> --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
>> @@ -24,6 +24,7 @@ required properties:
>>  Optional Properties:
>>  - clocks : phandle + clock specifier for the phy clocks
>>  - clock-names: string, clock name, must be "phyclk"
>> +- #clock-cells: for users of the phy-pll, should be 0
>>
>>  Example:
>>
>> diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
>> index 16cd533..33a80eb 100644
>> --- a/drivers/phy/phy-rockchip-usb.c
>> +++ b/drivers/phy/phy-rockchip-usb.c
>> @@ -15,12 +15,14 @@
>>   */
>>
>>  #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>  #include <linux/io.h>
>>  #include <linux/kernel.h>
>>  #include <linux/module.h>
>>  #include <linux/mutex.h>
>>  #include <linux/of.h>
>>  #include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>>  #include <linux/phy/phy.h>
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>> @@ -36,15 +38,28 @@
>>  #define SIDDQ_ON             BIT(13)
>>  #define SIDDQ_OFF            (0 << 13)
>>
>> +struct rockchip_usb_phys {
>> +     int reg;
>> +     const char *pll_name;
>> +};
>> +
>> +struct rockchip_usb_phy_pdata {
>> +     struct rockchip_usb_phys *phys;
>> +};
>> +
>>  struct rockchip_usb_phy_base {
>>       struct device *dev;
>>       struct regmap *reg_base;
>> +     const struct rockchip_usb_phy_pdata *pdata;
>>  };
>>
>>  struct rockchip_usb_phy {
>>       struct rockchip_usb_phy_base *base;
>> +     struct device_node *np;
>>       unsigned int    reg_offset;
>>       struct clk      *clk;
>> +     struct clk      *clk480m;
>> +     struct clk_hw   clk480m_hw;
>>       struct phy      *phy;
>>  };
>>
>> @@ -55,17 +70,59 @@ static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
>>                           SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
>>  }
>>
>> -static int rockchip_usb_phy_power_off(struct phy *_phy)
>> +static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
>> +                                             unsigned long parent_rate)
>>  {
>> -     struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
>> -     int ret = 0;
>> +     return 480000000;
>> +}
>> +
>> +static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
>> +{
>> +     struct rockchip_usb_phy *phy = container_of(hw,
>> +                                                 struct rockchip_usb_phy,
>> +                                                 clk480m_hw);
>>
>>       /* Power down usb phy analog blocks by set siddq 1 */
>> -     ret = rockchip_usb_phy_power(phy, 1);
>> -     if (ret)
>> +     rockchip_usb_phy_power(phy, 1);
>> +}
>> +
>> +static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
>> +{
>> +     struct rockchip_usb_phy *phy = container_of(hw,
>> +                                                 struct rockchip_usb_phy,
>> +                                                 clk480m_hw);
>> +
>> +     /* Power up usb phy analog blocks by set siddq 0 */
>> +     return rockchip_usb_phy_power(phy, 0);
>> +}
>> +
>> +static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
>> +{
>> +     struct rockchip_usb_phy *phy = container_of(hw,
>> +                                                 struct rockchip_usb_phy,
>> +                                                 clk480m_hw);
>> +     int ret;
>> +     u32 val;
>> +
>> +     ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
>> +     if (ret < 0)
>>               return ret;
>>
>> -     clk_disable_unprepare(phy->clk);
>> +     return (val & SIDDQ_ON) ? 0 : 1;
>> +}
>> +
>> +static const struct clk_ops rockchip_usb_phy480m_ops = {
>> +     .enable = rockchip_usb_phy480m_enable,
>> +     .disable = rockchip_usb_phy480m_disable,
>> +     .is_enabled = rockchip_usb_phy480m_is_enabled,
>> +     .recalc_rate = rockchip_usb_phy480m_recalc_rate,
>> +};
>> +
>> +static int rockchip_usb_phy_power_off(struct phy *_phy)
>> +{
>> +     struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
>> +
>> +     clk_disable_unprepare(phy->clk480m);
>>
>>       return 0;
>>  }
>> @@ -73,20 +130,8 @@ static int rockchip_usb_phy_power_off(struct phy *_phy)
>>  static int rockchip_usb_phy_power_on(struct phy *_phy)
>>  {
>>       struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
>> -     int ret = 0;
>>
>> -     ret = clk_prepare_enable(phy->clk);
>> -     if (ret)
>> -             return ret;
>> -
>> -     /* Power up usb phy analog blocks by set siddq 0 */
>> -     ret = rockchip_usb_phy_power(phy, 0);
>> -     if (ret) {
>> -             clk_disable_unprepare(phy->clk);
>> -             return ret;
>> -     }
>> -
>> -     return 0;
>> +     return clk_prepare_enable(phy->clk480m);
>>  }
>>
>>  static const struct phy_ops ops = {
>> @@ -99,6 +144,9 @@ static void rockchip_usb_phy_action(void *data)
>>  {
>>       struct rockchip_usb_phy *rk_phy = data;
>>
>> +     of_clk_del_provider(rk_phy->np);
>> +     clk_unregister(rk_phy->clk480m);
>> +
>>       if (rk_phy->clk)
>>               clk_put(rk_phy->clk);
>>  }
>> @@ -108,13 +156,16 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>>  {
>>       struct rockchip_usb_phy *rk_phy;
>>       unsigned int reg_offset;
>> -     int err;
>> +     const char *clk_name;
>> +     struct clk_init_data init;
>> +     int err, i;
>>
>>       rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
>>       if (!rk_phy)
>>               return -ENOMEM;
>>
>>       rk_phy->base = base;
>> +     rk_phy->np = child;
>>
>>       if (of_property_read_u32(child, "reg", &reg_offset)) {
>>               dev_err(base->dev, "missing reg property in node %s\n",
>> @@ -124,14 +175,54 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>>
>>       rk_phy->reg_offset = reg_offset;
>>
>> -     err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
>> -     if (err)
>> -             return err;
>> -
>>       rk_phy->clk = of_clk_get_by_name(child, "phyclk");
>>       if (IS_ERR(rk_phy->clk))
>>               rk_phy->clk = NULL;
>>
>> +     i = 0;
>> +     init.name = NULL;
>> +     while (base->pdata->phys[i].reg) {
>> +             if (base->pdata->phys[i].reg == reg_offset) {
>> +                     init.name = base->pdata->phys[i].pll_name;
>> +                     break;
>> +             }
>> +             i++;
>> +     }
>> +
>> +     if (!init.name) {
>> +             dev_err(base->dev, "phy data not found\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     if (rk_phy->clk) {
>> +             clk_name = __clk_get_name(rk_phy->clk);
>> +             init.flags = 0;
>> +             init.parent_names = &clk_name;
>> +             init.num_parents = 1;
>> +     } else {
>> +             init.flags = CLK_IS_ROOT;
>> +             init.parent_names = NULL;
>> +             init.num_parents = 0;
>> +     }
>> +
>> +     init.ops = &rockchip_usb_phy480m_ops;
>> +     rk_phy->clk480m_hw.init = &init;
>> +
>> +     rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
>> +     if (IS_ERR(rk_phy->clk480m)) {
>> +             err = PTR_ERR(rk_phy->clk480m);
>> +             goto err_clk;
>> +     }
>> +
>> +     err = of_clk_add_provider(child, of_clk_src_simple_get,
>> +                               rk_phy->clk480m);
>> +     if (err < 0)
>> +             goto err_clk_prov;
>> +
>> +     err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy);
>> +     if (err)
>> +             goto err_devm_action;
>> +
>>       rk_phy->phy = devm_phy_create(base->dev, child, &ops);
>>       if (IS_ERR(rk_phy->phy)) {
>>               dev_err(base->dev, "failed to create PHY\n");
>> @@ -141,13 +232,48 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
>>
>>       /* only power up usb phy when it use, so disable it when init*/
>>       return rockchip_usb_phy_power(rk_phy, 1);
>> +
>> +err_devm_action:
>> +     of_clk_del_provider(child);
>> +err_clk_prov:
>> +     clk_unregister(rk_phy->clk480m);
>> +err_clk:
>> +     if (rk_phy->clk)
>> +             clk_put(rk_phy->clk);
>> +     return err;
>>  }
>>
>> +static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
>> +     .phys = (struct rockchip_usb_phys[]){
>> +             { .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
>> +             { .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
>> +             { /* sentinel */ }
>> +     },
>> +};
>> +
>> +static const struct rockchip_usb_phy_pdata rk3188_pdata = {
>> +     .phys = (struct rockchip_usb_phys[]){
>> +             { .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
>> +             { .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
>> +             { /* sentinel */ }
>> +     },
>> +};
>> +
>> +static const struct rockchip_usb_phy_pdata rk3288_pdata = {
>> +     .phys = (struct rockchip_usb_phys[]){
>> +             { .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
>> +             { .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
>> +             { .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
>> +             { /* sentinel */ }
>> +     },
>> +};
>> +
>>  static int rockchip_usb_phy_probe(struct platform_device *pdev)
>>  {
>>       struct device *dev = &pdev->dev;
>>       struct rockchip_usb_phy_base *phy_base;
>>       struct phy_provider *phy_provider;
>> +     const struct of_device_id *match;
>>       struct device_node *child;
>>       int err;
>>
>> @@ -155,6 +281,14 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>>       if (!phy_base)
>>               return -ENOMEM;
>>
>> +     match = of_match_device(dev->driver->of_match_table, dev);
>> +     if (!match || !match->data) {
>> +             dev_err(dev, "missing phy data\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     phy_base->pdata = match->data;
>> +
>>       phy_base->dev = dev;
>>       phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
>>                                                            "rockchip,grf");
>> @@ -176,9 +310,9 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
>>  }
>>
>>  static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
>> -     { .compatible = "rockchip,rk3066a-usb-phy" },
>> -     { .compatible = "rockchip,rk3188-usb-phy" },
>> -     { .compatible = "rockchip,rk3288-usb-phy" },
>> +     { .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
>> +     { .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
>> +     { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
>>       {}
>>  };
>>
>>



-- 
Michael Turquette
CEO
BayLibre - At the Heart of Embedded Linux
http://baylibre.com/

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
  2015-11-19 21:22   ` Heiko Stuebner
@ 2016-01-25 14:04     ` Heiko Stübner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2016-01-25 14:04 UTC (permalink / raw)
  To: kishon
  Cc: mturquette, sboyd, linux-arm-kernel, linux-kernel,
	linux-rockchip, dianders, romain.perier, arnd, hl

Kishon,

Am Donnerstag, 19. November 2015, 22:22:28 schrieb Heiko Stuebner:
> The otgphy clocks really only drive the phy blocks. These in turn
> contain plls that then generate the 480m clocks the clock controller
> uses to supply some other clocks like uart0, gpu or the video-codec.
> 
> So fix this structure to actually respect that hirarchy and removed
> that usb480m fixed-rate clock working as a placeholder till now, as
> this wouldn't even work if the supplying phy gets turned off while
> its pll-output gets used elsewhere.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>

it looks like this patch didn't make your cutoff time for sending your stuff 
to Greg. As the core phy series up to patch 5 is in mainline now, I've just 
applied this patch to my clk-branch for 4.6.


Heiko

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks
@ 2016-01-25 14:04     ` Heiko Stübner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2016-01-25 14:04 UTC (permalink / raw)
  To: linux-arm-kernel

Kishon,

Am Donnerstag, 19. November 2015, 22:22:28 schrieb Heiko Stuebner:
> The otgphy clocks really only drive the phy blocks. These in turn
> contain plls that then generate the 480m clocks the clock controller
> uses to supply some other clocks like uart0, gpu or the video-codec.
> 
> So fix this structure to actually respect that hirarchy and removed
> that usb480m fixed-rate clock working as a placeholder till now, as
> this wouldn't even work if the supplying phy gets turned off while
> its pll-output gets used elsewhere.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>

it looks like this patch didn't make your cutoff time for sending your stuff 
to Greg. As the core phy series up to patch 5 is in mainline now, I've just 
applied this patch to my clk-branch for 4.6.


Heiko

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 6/8] ARM: dts: rockchip: add clock-cells for usb phy nodes
  2015-11-19 21:22   ` Heiko Stuebner
@ 2016-01-25 14:06     ` Heiko Stübner
  -1 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2016-01-25 14:06 UTC (permalink / raw)
  To: kishon
  Cc: mturquette, sboyd, linux-arm-kernel, linux-kernel,
	linux-rockchip, dianders, romain.perier, arnd, hl

Am Donnerstag, 19. November 2015, 22:22:27 schrieb Heiko Stuebner:
> Add the #clock-cells properties for the usbphy nodes as they
> provide the pll-clocks now.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>

applied to my dts32 branch for 4.6 with Mike's Review-tag from v1

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 6/8] ARM: dts: rockchip: add clock-cells for usb phy nodes
@ 2016-01-25 14:06     ` Heiko Stübner
  0 siblings, 0 replies; 67+ messages in thread
From: Heiko Stübner @ 2016-01-25 14:06 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, 19. November 2015, 22:22:27 schrieb Heiko Stuebner:
> Add the #clock-cells properties for the usbphy nodes as they
> provide the pll-clocks now.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>

applied to my dts32 branch for 4.6 with Mike's Review-tag from v1

^ permalink raw reply	[flat|nested] 67+ messages in thread

end of thread, other threads:[~2016-01-25 14:07 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-19 21:22 [PATCH v3 0/8] phy: rockchip-usb: correct pll handling and usb-uart Heiko Stuebner
2015-11-19 21:22 ` Heiko Stuebner
2015-11-19 21:22 ` Heiko Stuebner
2015-11-19 21:22 ` [PATCH v3 1/8] phy: rockchip-usb: fix clock get-put mismatch Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-19 21:22 ` [PATCH v3 2/8] phy: rockchip-usb: introduce a common data-struct for the device Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-20  0:38   ` Doug Anderson
2015-11-20  0:38     ` Doug Anderson
2015-11-20  0:38     ` Doug Anderson
2015-11-19 21:22 ` [PATCH v3 3/8] phy: rockchip-usb: move per-phy init into a separate function Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-19 21:22 ` [PATCH v3 4/8] phy: rockchip-usb: add compatible values for rk3066a and rk3188 Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-20  0:32   ` Doug Anderson
2015-11-20  0:32     ` Doug Anderson
2015-11-20  0:32     ` Doug Anderson
2015-11-22 19:49     ` Heiko Stuebner
2015-11-22 19:49       ` Heiko Stuebner
2015-11-22 19:49       ` Heiko Stuebner
2015-11-25 17:04       ` Doug Anderson
2015-11-25 17:04         ` Doug Anderson
2015-11-25 17:04         ` Doug Anderson
2015-11-25 18:24         ` Heiko Stübner
2015-11-25 18:24           ` Heiko Stübner
2015-11-25 18:24           ` Heiko Stübner
2015-11-25 18:35           ` Doug Anderson
2015-11-25 18:35             ` Doug Anderson
2015-11-25 18:35             ` Doug Anderson
2015-11-19 21:22 ` [PATCH v3 5/8] phy: rockchip-usb: expose the phy-internal PLLs Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-12-15 10:53   ` Kishon Vijay Abraham I
2015-12-15 10:53     ` Kishon Vijay Abraham I
2015-12-15 10:53     ` Kishon Vijay Abraham I
2015-12-21 20:00     ` Michael Turquette
2015-12-21 20:00       ` Michael Turquette
2015-12-21 20:00       ` Michael Turquette
2015-11-19 21:22 ` [PATCH v3 6/8] ARM: dts: rockchip: add clock-cells for usb phy nodes Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2016-01-25 14:06   ` Heiko Stübner
2016-01-25 14:06     ` Heiko Stübner
2015-11-19 21:22 ` [PATCH v3 7/8] clk: rockchip: fix usbphy-related clocks Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-12-15 10:52   ` Kishon Vijay Abraham I
2015-12-15 10:52     ` Kishon Vijay Abraham I
2015-12-15 10:52     ` Kishon Vijay Abraham I
2015-12-19 17:21     ` Heiko Stübner
2015-12-19 17:21       ` Heiko Stübner
2015-12-20  9:09       ` Kishon Vijay Abraham I
2015-12-20  9:09         ` Kishon Vijay Abraham I
2015-12-20  9:09         ` Kishon Vijay Abraham I
2016-01-25 14:04   ` Heiko Stübner
2016-01-25 14:04     ` Heiko Stübner
2015-11-19 21:22 ` [PATCH v3 8/8] phy: rockchip-usb: add handler for usb-uart functionality Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-11-19 21:22   ` Heiko Stuebner
2015-12-02 15:32 ` [PATCH v3 0/8] phy: rockchip-usb: correct pll handling and usb-uart Heiko Stübner
2015-12-02 15:32   ` Heiko Stübner
2015-12-03  6:05   ` Kishon Vijay Abraham I
2015-12-03  6:05     ` Kishon Vijay Abraham I
2015-12-03  6:05     ` Kishon Vijay Abraham I

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.