[PATCH 6/6] USB: s3c-hsotg: Add regulator support

Joonyoung Shim jy0922.shim at samsung.com
Wed Dec 28 02:03:27 EST 2011


The HSOTG hardware block needs two power sources and they can be
controlled using regulator.

Signed-off-by: Joonyoung Shim <jy0922.shim at samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
 drivers/usb/gadget/s3c-hsotg.c |   64 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 2665bf5..51b3ea2 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -27,6 +27,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -155,6 +156,11 @@ struct s3c_hsotg {
 	int			irq;
 	struct clk		*clk;
 
+	struct regulator	*reg_vusb_a;
+	struct regulator	*reg_vusb_d;
+	struct mutex		mutex_lock;
+	bool			enabled;
+
 	unsigned int		dedicated_fifos:1;
 
 	struct dentry		*debug_root;
@@ -184,6 +190,36 @@ struct s3c_hsotg_req {
 	unsigned char		mapped;
 };
 
+static void s3c_hsotg_regulator_enable(struct s3c_hsotg *hsotg)
+{
+	mutex_lock(&hsotg->mutex_lock);
+	if (!hsotg->enabled) {
+		if (hsotg->reg_vusb_d)
+			regulator_enable(hsotg->reg_vusb_d);
+
+		if (hsotg->reg_vusb_a)
+			regulator_enable(hsotg->reg_vusb_a);
+
+			hsotg->enabled = true;
+	}
+	mutex_unlock(&hsotg->mutex_lock);
+}
+
+static void s3c_hsotg_regulator_disable(struct s3c_hsotg *hsotg)
+{
+	mutex_lock(&hsotg->mutex_lock);
+	if (hsotg->enabled) {
+		if (hsotg->reg_vusb_a)
+			regulator_disable(hsotg->reg_vusb_a);
+
+		if (hsotg->reg_vusb_d)
+			regulator_disable(hsotg->reg_vusb_d);
+
+		hsotg->enabled = false;
+	}
+	mutex_unlock(&hsotg->mutex_lock);
+}
+
 /* conversion functions */
 static inline struct s3c_hsotg_req *our_req(struct usb_request *req)
 {
@@ -3317,6 +3353,26 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 
 	clk_enable(hsotg->clk);
 
+	mutex_init(&hsotg->mutex_lock);
+
+	hsotg->reg_vusb_d = regulator_get(dev, "vusb_d");
+	if (IS_ERR(hsotg->reg_vusb_d)) {
+		ret = PTR_ERR(hsotg->reg_vusb_d);
+		dev_err(dev, "failed to get %s regulator (%d)\n",
+				"vusb_d", ret);
+		hsotg->reg_vusb_d = NULL;
+	}
+
+	hsotg->reg_vusb_a = regulator_get(dev, "vusb_a");
+	if (IS_ERR(hsotg->reg_vusb_a)) {
+		ret = PTR_ERR(hsotg->reg_vusb_a);
+		dev_err(dev, "failed to get %s regulator (%d)\n",
+				"vusb_a", ret);
+		hsotg->reg_vusb_a = NULL;
+	}
+
+	s3c_hsotg_regulator_enable(hsotg);
+
 	if (plat->phy_init)
 		plat->phy_init(pdev, S5P_USB_PHY_DEVICE);
 
@@ -3341,6 +3397,9 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 err_add_udc:
 	if (plat->phy_exit)
 		plat->phy_exit(pdev, S5P_USB_PHY_DEVICE);
+	s3c_hsotg_regulator_disable(hsotg);
+	regulator_put(hsotg->reg_vusb_a);
+	regulator_put(hsotg->reg_vusb_d);
 
 	clk_disable(hsotg->clk);
 	clk_put(hsotg->clk);
@@ -3378,6 +3437,11 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
 	if (plat->phy_exit)
 		plat->phy_exit(pdev, S5P_USB_PHY_DEVICE);
 
+	s3c_hsotg_regulator_disable(hsotg);
+
+	regulator_put(hsotg->reg_vusb_a);
+	regulator_put(hsotg->reg_vusb_d);
+
 	clk_disable(hsotg->clk);
 	clk_put(hsotg->clk);
 
-- 
1.7.5.4




More information about the linux-arm-kernel mailing list