2014-12-12 15:00:53

by Yunzhi Li

[permalink] [raw]
Subject: [PATCH v7 0/5] Patches to add support for Rockchip usb PHYs.


Patches to add support for Rockchip usb phys.Add a new Rockchip
usb phy driver and modify dwc2 controller driver to make dwc2
platform devices support a generic PHY framework driver. This
patch set has been tested on my rk3288-evb and power off the usb
phys would reduce about 60mW power budget in total during sustem
suspend.

Changes in v7:
- Update bindings doc
- Accept Kishon's comments to use phandle args to find a phy
struct directly and get rid of using a custom of_xlate
function.
- Update dtsi for new usb phy driver.

Changes in v6:
- Rename SIDDQ_MSK to SIDDQ_WRITE_ENA.

Changes in v5:
- Adjust entry order of example devicetree node in document.
- reorder the phy dt node to a correct position.

Changes in v4:
- Updata description for phy device tree subnode.
- Get number of PHYs from device tree.
- Model each PHY as subnode of the phy provider node.
- Add phy subnodes.

Changes in v3:
- Use BIT macro instead of bit shift ops.
- Rename the config entry to PHY_ROCKCHIP_USB.
- Fix coding style: both branches of the if() which only one
branch of the conditional statement is a single statement
should have braces.
- No need to test dwc2->phy for NULL before calling generic phy
APIs.

Yunzhi Li (5):
Documentation: bindings: add dt documentation for Rockchip usb PHY
phy: add a driver for the Rockchip SoC internal USB2.0 PHY
usb: dwc2: add generic PHY framework support for dwc2 usb controler
platform driver.
ARM: dts: rockchip: add rk3288 usb PHY
ARM: dts: rockchip: Enable usb PHY on rk3288-evb board

.../devicetree/bindings/phy/rockchip-usb-phy.txt | 37 +++++
arch/arm/boot/dts/rk3288-evb.dtsi | 4 +
arch/arm/boot/dts/rk3288.dtsi | 35 +++++
drivers/phy/Kconfig | 7 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-rockchip-usb.c | 158 +++++++++++++++++++++
drivers/usb/dwc2/gadget.c | 33 ++---
drivers/usb/dwc2/platform.c | 36 ++++-
8 files changed, 288 insertions(+), 23 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
create mode 100644 drivers/phy/phy-rockchip-usb.c

--
2.0.0


2014-12-12 15:01:24

by Yunzhi Li

[permalink] [raw]
Subject: [PATCH v7 1/5] Documentation: bindings: add dt documentation for Rockchip usb PHY

This patch adds a binding that describes the Rockchip usb PHYs
found on Rockchip SoCs usb interface.

Signed-off-by: Yunzhi Li <[email protected]>

---

Changes in v7:
- Update bindings doc

Changes in v6: None
Changes in v5:
- Adjust entry order of example devicetree node in document.

Changes in v4:
- Updata description for phy device tree subnode.

Changes in v3: None

.../devicetree/bindings/phy/rockchip-usb-phy.txt | 37 ++++++++++++++++++++++
1 file changed, 37 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt

diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
new file mode 100644
index 0000000..826454a
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
@@ -0,0 +1,37 @@
+ROCKCHIP USB2 PHY
+
+Required properties:
+ - compatible: rockchip,rk3288-usb-phy
+ - rockchip,grf : phandle to the syscon managing the "general
+ register files"
+ - #address-cells: should be 1
+ - #size-cells: should be 0
+
+Sub-nodes:
+Each PHY should be represented as a sub-node.
+
+Sub-nodes
+required properties:
+- #phy-cells: should be 0
+- reg: PHY configure reg address offset in GRF
+ "0x320" - for PHY attach to OTG controller
+ "0x334" - for PHY attach to HOST0 controller
+ "0x348" - for PHY attach to HOST1 controller
+
+Optional Properties:
+- clocks : phandle + clock specifier for the phy clocks
+- clock-names: string, clock name, must be "phyclk"
+
+Example:
+
+usbphy: phy {
+ compatible = "rockchip,rk3288-usb-phy";
+ rockchip,grf = <&grf>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usbphy0: usb-phy0 {
+ #phy-cells = <0>;
+ reg = <0x320>;
+ };
+};
--
2.0.0

2014-12-12 15:08:20

by Yunzhi Li

[permalink] [raw]
Subject: [PATCH v7 2/5] phy: add a driver for the Rockchip SoC internal USB2.0 PHY

This patch to add a generic PHY driver for ROCKCHIP usb PHYs,
currently this driver can support RK3288. The RK3288 SoC have
three independent USB PHY IPs which are all configured through a
set of registers located in the GRF (general register files)
module.

Signed-off-by: Yunzhi Li <[email protected]>

---

Changes in v7:
- Accept Kishon's comments to use phandle args to find a phy
struct directly and get rid of using a custom of_xlate
function.

Changes in v6:
- Rename SIDDQ_MSK to SIDDQ_WRITE_ENA.

Changes in v5: None
Changes in v4:
- Get number of PHYs from device tree.
- Model each PHY as subnode of the phy provider node.

Changes in v3:
- Use BIT macro instead of bit shift ops.
- Rename the config entry to PHY_ROCKCHIP_USB.

drivers/phy/Kconfig | 7 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-rockchip-usb.c | 158 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 166 insertions(+)
create mode 100644 drivers/phy/phy-rockchip-usb.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index ccad880..b24500a 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -239,6 +239,13 @@ config PHY_QCOM_IPQ806X_SATA
depends on OF
select GENERIC_PHY

+config PHY_ROCKCHIP_USB
+ tristate "Rockchip USB2 PHY Driver"
+ depends on ARCH_ROCKCHIP && OF
+ select GENERIC_PHY
+ help
+ Enable this to support the Rockchip USB 2.0 PHY.
+
config PHY_ST_SPEAR1310_MIPHY
tristate "ST SPEAR1310-MIPHY driver"
select GENERIC_PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index aa74f96..48bf5a1 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -28,6 +28,7 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
+obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o
obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
new file mode 100644
index 0000000..22011c3
--- /dev/null
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -0,0 +1,158 @@
+/*
+ * Rockchip usb PHY driver
+ *
+ * Copyright (C) 2014 Yunzhi Li <[email protected]>
+ * Copyright (C) 2014 ROCKCHIP, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.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/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#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)
+
+struct rockchip_usb_phy {
+ unsigned int reg_offset;
+ struct regmap *reg_base;
+ struct clk *clk;
+ struct phy *phy;
+};
+
+static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
+ bool siddq)
+{
+ return regmap_write(phy->reg_base, phy->reg_offset,
+ SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
+}
+
+static int rockchip_usb_phy_power_off(struct phy *_phy)
+{
+ struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
+ int ret = 0;
+
+ /* Power down usb phy analog blocks by set siddq 1 */
+ ret = rockchip_usb_phy_power(phy, 1);
+ if (ret)
+ return ret;
+
+ clk_disable_unprepare(phy->clk);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+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)
+ return ret;
+
+ return 0;
+}
+
+static struct phy_ops ops = {
+ .power_on = rockchip_usb_phy_power_on,
+ .power_off = rockchip_usb_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int rockchip_usb_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rockchip_usb_phy *rk_phy;
+ struct phy_provider *phy_provider;
+ struct device_node *child;
+ struct regmap *grf;
+ unsigned int reg_offset;
+
+ grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
+ if (IS_ERR(grf)) {
+ dev_err(&pdev->dev, "Missing rockchip,grf property\n");
+ return PTR_ERR(grf);
+ }
+
+ for_each_available_child_of_node(dev->of_node, child) {
+ rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
+ if (!rk_phy)
+ return -ENOMEM;
+
+ if (of_property_read_u32(child, "reg", &reg_offset)) {
+ dev_err(dev, "missing reg property in node %s\n",
+ child->name);
+ return -EINVAL;
+ }
+
+ rk_phy->reg_offset = reg_offset;
+ rk_phy->reg_base = grf;
+
+ 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");
+ return PTR_ERR(rk_phy->phy);
+ }
+ phy_set_drvdata(rk_phy->phy, rk_phy);
+ }
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
+ { .compatible = "rockchip,rk3288-usb-phy" },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, rockchip_usb_phy_dt_ids);
+
+static struct platform_driver rockchip_usb_driver = {
+ .probe = rockchip_usb_phy_probe,
+ .driver = {
+ .name = "rockchip-usb-phy",
+ .owner = THIS_MODULE,
+ .of_match_table = rockchip_usb_phy_dt_ids,
+ },
+};
+
+module_platform_driver(rockchip_usb_driver);
+
+MODULE_AUTHOR("Yunzhi Li <[email protected]>");
+MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");
+MODULE_LICENSE("GPL v2");
--
2.0.0

2014-12-12 15:10:09

by Yunzhi Li

[permalink] [raw]
Subject: [PATCH v7 3/5] usb: dwc2: add generic PHY framework support for dwc2 usb controler platform driver.

Get PHY parameters from devicetree and power off usb PHY during
system suspend.

Signed-off-by: Yunzhi Li <[email protected]>
Acked-by: Paul Zimmerman <[email protected]>

---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
- Fix coding style: both branches of the if() which only one
branch of the conditional statement is a single statement
should have braces.
- No need to test dwc2->phy for NULL before calling generic phy
APIs.

drivers/usb/dwc2/gadget.c | 33 ++++++++++++---------------------
drivers/usb/dwc2/platform.c | 36 ++++++++++++++++++++++++++++++++++--
2 files changed, 46 insertions(+), 23 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 200168e..2601c61 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3410,8 +3410,6 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{
struct device *dev = hsotg->dev;
struct s3c_hsotg_plat *plat = dev->platform_data;
- struct phy *phy;
- struct usb_phy *uphy;
struct s3c_hsotg_ep *eps;
int epnum;
int ret;
@@ -3421,30 +3419,23 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
hsotg->phyif = GUSBCFG_PHYIF16;

/*
- * Attempt to find a generic PHY, then look for an old style
- * USB PHY, finally fall back to pdata
+ * If platform probe couldn't find a generic PHY or an old style
+ * USB PHY, fall back to pdata
*/
- phy = devm_phy_get(dev, "usb2-phy");
- if (IS_ERR(phy)) {
- uphy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
- if (IS_ERR(uphy)) {
- /* Fallback for pdata */
- plat = dev_get_platdata(dev);
- if (!plat) {
- dev_err(dev,
- "no platform data or transceiver defined\n");
- return -EPROBE_DEFER;
- }
- hsotg->plat = plat;
- } else
- hsotg->uphy = uphy;
- } else {
- hsotg->phy = phy;
+ if (IS_ERR_OR_NULL(hsotg->phy) && IS_ERR_OR_NULL(hsotg->uphy)) {
+ plat = dev_get_platdata(dev);
+ if (!plat) {
+ dev_err(dev,
+ "no platform data or transceiver defined\n");
+ return -EPROBE_DEFER;
+ }
+ hsotg->plat = plat;
+ } else if (hsotg->phy) {
/*
* If using the generic PHY framework, check if the PHY bus
* width is 8-bit and set the phyif appropriately.
*/
- if (phy_get_bus_width(phy) == 8)
+ if (phy_get_bus_width(hsotg->phy) == 8)
hsotg->phyif = GUSBCFG_PHYIF8;
}

diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 6a795aa..ae095f0 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -155,6 +155,8 @@ static int dwc2_driver_probe(struct platform_device *dev)
struct dwc2_core_params defparams;
struct dwc2_hsotg *hsotg;
struct resource *res;
+ struct phy *phy;
+ struct usb_phy *uphy;
int retval;
int irq;

@@ -212,6 +214,24 @@ static int dwc2_driver_probe(struct platform_device *dev)

hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node);

+ /*
+ * Attempt to find a generic PHY, then look for an old style
+ * USB PHY
+ */
+ phy = devm_phy_get(&dev->dev, "usb2-phy");
+ if (IS_ERR(phy)) {
+ hsotg->phy = NULL;
+ uphy = devm_usb_get_phy(&dev->dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR(uphy))
+ hsotg->uphy = NULL;
+ else
+ hsotg->uphy = uphy;
+ } else {
+ hsotg->phy = phy;
+ phy_power_on(hsotg->phy);
+ phy_init(hsotg->phy);
+ }
+
spin_lock_init(&hsotg->lock);
mutex_init(&hsotg->init_mutex);
retval = dwc2_gadget_init(hsotg, irq);
@@ -231,8 +251,15 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
int ret = 0;

- if (dwc2_is_device_mode(dwc2))
+ if (dwc2_is_device_mode(dwc2)) {
ret = s3c_hsotg_suspend(dwc2);
+ } else {
+ if (dwc2->lx_state == DWC2_L0)
+ return 0;
+ phy_exit(dwc2->phy);
+ phy_power_off(dwc2->phy);
+
+ }
return ret;
}

@@ -241,8 +268,13 @@ static int __maybe_unused dwc2_resume(struct device *dev)
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
int ret = 0;

- if (dwc2_is_device_mode(dwc2))
+ if (dwc2_is_device_mode(dwc2)) {
ret = s3c_hsotg_resume(dwc2);
+ } else {
+ phy_power_on(dwc2->phy);
+ phy_init(dwc2->phy);
+
+ }
return ret;
}

--
2.0.0

2014-12-12 15:12:52

by Yunzhi Li

[permalink] [raw]
Subject: [PATCH v7 4/5] ARM: dts: rockchip: add rk3288 usb PHY

This patch adds a device_node for RK3288 SoC usb phy. It also
defines the phy to be used by three usb controllers: usb_host0/1
and usb_otg.

Signed-off-by: Yunzhi Li <[email protected]>

---

Changes in v7:
- Update dtsi for new usb phy driver.

Changes in v6: None
Changes in v5:
- reorder the phy dt node to a correct position.

Changes in v4:
- Add phy subnodes.

Changes in v3: None

arch/arm/boot/dts/rk3288.dtsi | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 874e66d..2a9a029 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -335,6 +335,8 @@
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru HCLK_USBHOST0>;
clock-names = "usbhost";
+ phys = <&usbphy1>;
+ phy-names = "usb";
status = "disabled";
};

@@ -347,6 +349,8 @@
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru HCLK_USBHOST1>;
clock-names = "otg";
+ phys = <&usbphy2>;
+ phy-names = "usb2-phy";
status = "disabled";
};

@@ -357,6 +361,8 @@
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru HCLK_OTG0>;
clock-names = "otg";
+ phys = <&usbphy0>;
+ phy-names = "usb2-phy";
status = "disabled";
};

@@ -497,6 +503,35 @@
interrupts = <GIC_PPI 9 0xf04>;
};

+ usbphy: phy {
+ compatible = "rockchip,rk3288-usb-phy";
+ rockchip,grf = <&grf>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ usbphy0: usb-phy0 {
+ #phy-cells = <0>;
+ reg = <0x320>;
+ clocks = <&cru SCLK_OTGPHY0>;
+ clock-names = "phyclk";
+ };
+
+ usbphy1: usb-phy1 {
+ #phy-cells = <0>;
+ reg = <0x334>;
+ clocks = <&cru SCLK_OTGPHY1>;
+ clock-names = "phyclk";
+ };
+
+ usbphy2: usb-phy2 {
+ #phy-cells = <0>;
+ reg = <0x348>;
+ clocks = <&cru SCLK_OTGPHY2>;
+ clock-names = "phyclk";
+ };
+ };
+
pinctrl: pinctrl {
compatible = "rockchip,rk3288-pinctrl";
rockchip,grf = <&grf>;
--
2.0.0

2014-12-12 15:17:32

by Yunzhi Li

[permalink] [raw]
Subject: [PATCH v7 5/5] ARM: dts: rockchip: Enable usb PHY on rk3288-evb board

Enable usb PHY for all usb ports on rk3288-evb.

Signed-off-by: Yunzhi Li <[email protected]>

---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None

arch/arm/boot/dts/rk3288-evb.dtsi | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
index cb83cea..992f323 100644
--- a/arch/arm/boot/dts/rk3288-evb.dtsi
+++ b/arch/arm/boot/dts/rk3288-evb.dtsi
@@ -174,6 +174,10 @@
};
};

+&usbphy {
+ status = "okay";
+};
+
&usb_host0_ehci {
status = "okay";
};
--
2.0.0

2014-12-13 00:19:54

by Doug Anderson

[permalink] [raw]
Subject: Re: [PATCH v7 2/5] phy: add a driver for the Rockchip SoC internal USB2.0 PHY

Yunzhi,

On Fri, Dec 12, 2014 at 7:07 AM, Yunzhi Li <[email protected]> wrote:
> This patch to add a generic PHY driver for ROCKCHIP usb PHYs,
> currently this driver can support RK3288. The RK3288 SoC have
> three independent USB PHY IPs which are all configured through a
> set of registers located in the GRF (general register files)
> module.
>
> Signed-off-by: Yunzhi Li <[email protected]>
>
> ---
>
> Changes in v7:
> - Accept Kishon's comments to use phandle args to find a phy
> struct directly and get rid of using a custom of_xlate
> function.

I'm going to assume you didn't test this version, since it doesn't
work for me. At suspend time power is high and my printouts in the
powerup/powerdown code aren't called...


> + for_each_available_child_of_node(dev->of_node, child) {
> + rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
> + if (!rk_phy)
> + return -ENOMEM;
> +
> + if (of_property_read_u32(child, "reg", &reg_offset)) {
> + dev_err(dev, "missing reg property in node %s\n",
> + child->name);
> + return -EINVAL;
> + }
> +
> + rk_phy->reg_offset = reg_offset;
> + rk_phy->reg_base = grf;
> +
> + 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");
> + return PTR_ERR(rk_phy->phy);
> + }
> + phy_set_drvdata(rk_phy->phy, rk_phy);
> + }
> +
> + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);

I think your bug is here. I think you now need to register 3 phy
providers, not just one.

I'll continue to assert my utter noviceness with this code, but my
attempt at a solution (which works) can be found at:

https://chromium-review.googlesource.com/235456

-Doug

2014-12-13 07:27:01

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH v7 2/5] phy: add a driver for the Rockchip SoC internal USB2.0 PHY

hi,

On Saturday 13 December 2014 05:49 AM, Doug Anderson wrote:
> Yunzhi,
>
> On Fri, Dec 12, 2014 at 7:07 AM, Yunzhi Li <[email protected]> wrote:
>> This patch to add a generic PHY driver for ROCKCHIP usb PHYs,
>> currently this driver can support RK3288. The RK3288 SoC have
>> three independent USB PHY IPs which are all configured through a
>> set of registers located in the GRF (general register files)
>> module.
>>
>> Signed-off-by: Yunzhi Li <[email protected]>
>>
>> ---
>>
>> Changes in v7:
>> - Accept Kishon's comments to use phandle args to find a phy
>> struct directly and get rid of using a custom of_xlate
>> function.
>
> I'm going to assume you didn't test this version, since it doesn't
> work for me. At suspend time power is high and my printouts in the
> powerup/powerdown code aren't called...
>
>
>> + for_each_available_child_of_node(dev->of_node, child) {
>> + rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
>> + if (!rk_phy)
>> + return -ENOMEM;
>> +
>> + if (of_property_read_u32(child, "reg", &reg_offset)) {
>> + dev_err(dev, "missing reg property in node %s\n",
>> + child->name);
>> + return -EINVAL;
>> + }
>> +
>> + rk_phy->reg_offset = reg_offset;
>> + rk_phy->reg_base = grf;
>> +
>> + 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");
>> + return PTR_ERR(rk_phy->phy);
>> + }
>> + phy_set_drvdata(rk_phy->phy, rk_phy);
>> + }
>> +
>> + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
>
> I think your bug is here. I think you now need to register 3 phy
> providers, not just one.

No there should be only one phy provider. It means the bug is elsewhere.

Thanks
Kishon

2014-12-13 23:12:15

by Doug Anderson

[permalink] [raw]
Subject: Re: [PATCH v7 2/5] phy: add a driver for the Rockchip SoC internal USB2.0 PHY

Hi,

On Fri, Dec 12, 2014 at 11:24 PM, Kishon Vijay Abraham I <[email protected]> wrote:
> hi,
>
> On Saturday 13 December 2014 05:49 AM, Doug Anderson wrote:
>> Yunzhi,
>>
>> On Fri, Dec 12, 2014 at 7:07 AM, Yunzhi Li <[email protected]> wrote:
>>> This patch to add a generic PHY driver for ROCKCHIP usb PHYs,
>>> currently this driver can support RK3288. The RK3288 SoC have
>>> three independent USB PHY IPs which are all configured through a
>>> set of registers located in the GRF (general register files)
>>> module.
>>>
>>> Signed-off-by: Yunzhi Li <[email protected]>
>>>
>>> ---
>>>
>>> Changes in v7:
>>> - Accept Kishon's comments to use phandle args to find a phy
>>> struct directly and get rid of using a custom of_xlate
>>> function.
>>
>> I'm going to assume you didn't test this version, since it doesn't
>> work for me. At suspend time power is high and my printouts in the
>> powerup/powerdown code aren't called...
>>
>>
>>> + for_each_available_child_of_node(dev->of_node, child) {
>>> + rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
>>> + if (!rk_phy)
>>> + return -ENOMEM;
>>> +
>>> + if (of_property_read_u32(child, "reg", &reg_offset)) {
>>> + dev_err(dev, "missing reg property in node %s\n",
>>> + child->name);
>>> + return -EINVAL;
>>> + }
>>> +
>>> + rk_phy->reg_offset = reg_offset;
>>> + rk_phy->reg_base = grf;
>>> +
>>> + 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");
>>> + return PTR_ERR(rk_phy->phy);
>>> + }
>>> + phy_set_drvdata(rk_phy->phy, rk_phy);
>>> + }
>>> +
>>> + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
>>
>> I think your bug is here. I think you now need to register 3 phy
>> providers, not just one.
>
> No there should be only one phy provider. It means the bug is elsewhere.

Ah. That's what I get for testing on a backported kernel. I bet it's
because I'm missing:

2a4c370 phy: core: Fix of_phy_provider_lookup to return PHY provider
for sub node

Hrm, that made things better, but I still only got one printout when I
expected 3 (one for each user of the PHY). I bet there are more picks
I need then... :-/ Ah, yup. When I pick the whole load of PHY
related stuff then I get all 3. :)

I'll do more testing when I have more time and post up a Tested-by, then...

-Doug

2014-12-15 18:12:24

by Doug Anderson

[permalink] [raw]
Subject: Re: [PATCH v7 2/5] phy: add a driver for the Rockchip SoC internal USB2.0 PHY

Yunzhi,

On Fri, Dec 12, 2014 at 7:07 AM, Yunzhi Li <[email protected]> wrote:
> This patch to add a generic PHY driver for ROCKCHIP usb PHYs,
> currently this driver can support RK3288. The RK3288 SoC have
> three independent USB PHY IPs which are all configured through a
> set of registers located in the GRF (general register files)
> module.
>
> Signed-off-by: Yunzhi Li <[email protected]>
>
> ---
>
> Changes in v7:
> - Accept Kishon's comments to use phandle args to find a phy
> struct directly and get rid of using a custom of_xlate
> function.
>
> Changes in v6:
> - Rename SIDDQ_MSK to SIDDQ_WRITE_ENA.
>
> Changes in v5: None
> Changes in v4:
> - Get number of PHYs from device tree.
> - Model each PHY as subnode of the phy provider node.
>
> Changes in v3:
> - Use BIT macro instead of bit shift ops.
> - Rename the config entry to PHY_ROCKCHIP_USB.
>
> drivers/phy/Kconfig | 7 ++
> drivers/phy/Makefile | 1 +
> drivers/phy/phy-rockchip-usb.c | 158 +++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 166 insertions(+)
> create mode 100644 drivers/phy/phy-rockchip-usb.c

On rk3288-pinky (on a 3.14 tree with backports), I can confirm that
this properly gets us into low power at suspend time.

Tested-by: Doug Anderson <[email protected]>

2014-12-15 18:13:14

by Doug Anderson

[permalink] [raw]
Subject: Re: [PATCH v7 3/5] usb: dwc2: add generic PHY framework support for dwc2 usb controler platform driver.

Yunzhi,

On Fri, Dec 12, 2014 at 7:09 AM, Yunzhi Li <[email protected]> wrote:
> Get PHY parameters from devicetree and power off usb PHY during
> system suspend.
>
> Signed-off-by: Yunzhi Li <[email protected]>
> Acked-by: Paul Zimmerman <[email protected]>
>
> ---
>
> Changes in v7: None
> Changes in v6: None
> Changes in v5: None
> Changes in v4: None
> Changes in v3:
> - Fix coding style: both branches of the if() which only one
> branch of the conditional statement is a single statement
> should have braces.
> - No need to test dwc2->phy for NULL before calling generic phy
> APIs.
>
> drivers/usb/dwc2/gadget.c | 33 ++++++++++++---------------------
> drivers/usb/dwc2/platform.c | 36 ++++++++++++++++++++++++++++++++++--
> 2 files changed, 46 insertions(+), 23 deletions(-)

On rk3288-pinky (on a 3.14 tree with backports), I can confirm that
this properly gets us into low power at suspend time.

Tested-by: Doug Anderson <[email protected]>

2014-12-15 18:14:21

by Doug Anderson

[permalink] [raw]
Subject: Re: [PATCH v7 4/5] ARM: dts: rockchip: add rk3288 usb PHY

Yunzhi,

On Fri, Dec 12, 2014 at 7:12 AM, Yunzhi Li <[email protected]> wrote:
> This patch adds a device_node for RK3288 SoC usb phy. It also
> defines the phy to be used by three usb controllers: usb_host0/1
> and usb_otg.
>
> Signed-off-by: Yunzhi Li <[email protected]>
>
> ---
>
> Changes in v7:
> - Update dtsi for new usb phy driver.
>
> Changes in v6: None
> Changes in v5:
> - reorder the phy dt node to a correct position.
>
> Changes in v4:
> - Add phy subnodes.
>
> Changes in v3: None
>
> arch/arm/boot/dts/rk3288.dtsi | 35 +++++++++++++++++++++++++++++++++++
> 1 file changed, 35 insertions(+)

On rk3288-pinky (on a 3.14 tree with backports), I can confirm that
this properly gets us into low power at suspend time.

Tested-by: Doug Anderson <[email protected]>


This looks reasonable to me:

Reviewed-by: Doug Anderson <[email protected]>

2014-12-15 18:15:41

by Doug Anderson

[permalink] [raw]
Subject: Re: [PATCH v7 5/5] ARM: dts: rockchip: Enable usb PHY on rk3288-evb board

Yunzhi,

On Fri, Dec 12, 2014 at 7:17 AM, Yunzhi Li <[email protected]> wrote:
> Enable usb PHY for all usb ports on rk3288-evb.
>
> Signed-off-by: Yunzhi Li <[email protected]>
>
> ---
>
> Changes in v7: None
> Changes in v6: None
> Changes in v5: None
> Changes in v4: None
> Changes in v3: None
>
> arch/arm/boot/dts/rk3288-evb.dtsi | 4 ++++
> 1 file changed, 4 insertions(+)

I have tested a similar change on rk3288-pinky (on a 3.14 tree with
backports). There I can confirm that this properly gets us into low
power at suspend time. I have not tested on EVB itself though, so
leaving off my tested tag.

This does look reasonable to me, though:

Reviewed-by: Doug Anderson <[email protected]>

2015-02-19 22:30:51

by Heiko Stübner

[permalink] [raw]
Subject: Re: [PATCH v7 0/5] Patches to add support for Rockchip usb PHYs.

Am Freitag, 12. Dezember 2014, 23:00:08 schrieb Yunzhi Li:
> Patches to add support for Rockchip usb phys.Add a new Rockchip
> usb phy driver and modify dwc2 controller driver to make dwc2
> platform devices support a generic PHY framework driver. This
> patch set has been tested on my rk3288-evb and power off the usb
> phys would reduce about 60mW power budget in total during sustem
> suspend.

it seems I missed a mail stating that the phy driver was applied and just
found it in the main tree during the merge window.

I've therefore applied the two dts patches for 3.21 and put the following
on top, so that the firefly board also gets phy support


Heiko

---------- 8< --------------
From: Heiko Stuebner <[email protected]>
Date: Thu, 19 Feb 2015 22:46:45 +0100
Subject: [PATCH] ARM: dts: rockchip: enable usbphy on rk3288-firefly

Enable the usb phys on the firefly board.

Signed-off-by: Heiko Stuebner <[email protected]>
---
arch/arm/boot/dts/rk3288-firefly.dtsi | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-firefly.dtsi b/arch/arm/boot/dts/rk3288-firefly.dtsi
index e6f873a..b9dda41 100644
--- a/arch/arm/boot/dts/rk3288-firefly.dtsi
+++ b/arch/arm/boot/dts/rk3288-firefly.dtsi
@@ -459,6 +459,10 @@
status = "okay";
};

+&usbphy {
+ status = "okay";
+};
+
&usb_host1 {
pinctrl-names = "default";
pinctrl-0 = <&usbhub_rst>;
--
2.1.4