@@ -63,6 +63,10 @@ Required properties:
port 2 is HSIC phy1
- phys: from the *Generic PHY* bindings, specifying phy used by port.
+Optional properties:
+ - vdd33-supply: handle to 3.3V Vdd supply regulator for the controller.
+ - vdd10-supply: handle to 1.0V Vdd supply regulator for the controller.
+
Example:
usb@12120000 {
compatible = "samsung,exynos4210-ohci";
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/phy/phy.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
@@ -36,6 +37,8 @@ static struct hc_driver __read_mostly exynos_ohci_hc_driver;
struct exynos_ohci_hcd {
struct clk *clk;
struct phy *phy[PHY_NUMBER];
+ struct regulator *vdd33;
+ struct regulator *vdd10;
};
static int exynos_ohci_get_phy(struct device *dev,
@@ -139,7 +142,27 @@ static int exynos_ohci_probe(struct platform_device *pdev)
err = exynos_ohci_get_phy(&pdev->dev, exynos_ohci);
if (err)
- goto fail_clk;
+ goto fail_regulator1;
+
+ exynos_ohci->vdd33 = devm_regulator_get_optional(&pdev->dev, "vdd33");
+ if (!IS_ERR(exynos_ohci->vdd33)) {
+ err = regulator_enable(exynos_ohci->vdd33);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to enable 3.3V Vdd supply\n");
+ goto fail_regulator1;
+ }
+ }
+
+ exynos_ohci->vdd10 = devm_regulator_get_optional(&pdev->dev, "vdd10");
+ if (!IS_ERR(exynos_ohci->vdd10)) {
+ err = regulator_enable(exynos_ohci->vdd10);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to enable 1.0V Vdd supply\n");
+ goto fail_regulator2;
+ }
+ }
skip_phy:
exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
@@ -191,6 +214,10 @@ fail_add_hcd:
fail_io:
clk_disable_unprepare(exynos_ohci->clk);
fail_clk:
+ regulator_disable(exynos_ohci->vdd10);
+fail_regulator2:
+ regulator_disable(exynos_ohci->vdd33);
+fail_regulator1:
usb_put_hcd(hcd);
return err;
}
@@ -206,6 +233,11 @@ static int exynos_ohci_remove(struct platform_device *pdev)
clk_disable_unprepare(exynos_ohci->clk);
+ if (!IS_ERR(exynos_ohci->vdd33))
+ regulator_disable(exynos_ohci->vdd33);
+ if (!IS_ERR(exynos_ohci->vdd10))
+ regulator_disable(exynos_ohci->vdd10);
+
usb_put_hcd(hcd);
return 0;
@@ -234,6 +266,11 @@ static int exynos_ohci_suspend(struct device *dev)
clk_disable_unprepare(exynos_ohci->clk);
+ if (!IS_ERR(exynos_ohci->vdd33))
+ regulator_disable(exynos_ohci->vdd33);
+ if (!IS_ERR(exynos_ohci->vdd10))
+ regulator_disable(exynos_ohci->vdd10);
+
return 0;
}
@@ -243,6 +280,22 @@ static int exynos_ohci_resume(struct device *dev)
struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
int ret;
+ if (!IS_ERR(exynos_ohci->vdd33)) {
+ ret = regulator_enable(exynos_ohci->vdd33);
+ if (ret) {
+ dev_err(dev, "Failed to enable 3.3V Vdd supply\n");
+ return ret;
+ }
+ }
+
+ if (!IS_ERR(exynos_ohci->vdd10)) {
+ ret = regulator_enable(exynos_ohci->vdd10);
+ if (ret) {
+ dev_err(dev, "Failed to enable 1.0V Vdd supply\n");
+ return ret;
+ }
+ }
+
clk_prepare_enable(exynos_ohci->clk);
ret = exynos_ohci_phy_enable(dev);