aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/otg/msm_otg.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 854b7e3413dd..628ba7d943da 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -38,6 +38,7 @@
38#include <linux/usb/hcd.h> 38#include <linux/usb/hcd.h>
39#include <linux/usb/msm_hsusb.h> 39#include <linux/usb/msm_hsusb.h>
40#include <linux/usb/msm_hsusb_hw.h> 40#include <linux/usb/msm_hsusb_hw.h>
41#include <linux/regulator/consumer.h>
41 42
42#include <mach/clk.h> 43#include <mach/clk.h>
43 44
@@ -45,6 +46,171 @@
45#define DRIVER_NAME "msm_otg" 46#define DRIVER_NAME "msm_otg"
46 47
47#define ULPI_IO_TIMEOUT_USEC (10 * 1000) 48#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
49
50#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
51#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
52#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
53#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
54
55#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
56#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
57#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
58#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
59
60#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
61#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
62
63static struct regulator *hsusb_3p3;
64static struct regulator *hsusb_1p8;
65static struct regulator *hsusb_vddcx;
66
67static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
68{
69 int ret = 0;
70
71 if (init) {
72 hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
73 if (IS_ERR(hsusb_vddcx)) {
74 dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
75 return PTR_ERR(hsusb_vddcx);
76 }
77
78 ret = regulator_set_voltage(hsusb_vddcx,
79 USB_PHY_VDD_DIG_VOL_MIN,
80 USB_PHY_VDD_DIG_VOL_MAX);
81 if (ret) {
82 dev_err(motg->otg.dev, "unable to set the voltage "
83 "for hsusb vddcx\n");
84 regulator_put(hsusb_vddcx);
85 return ret;
86 }
87
88 ret = regulator_enable(hsusb_vddcx);
89 if (ret) {
90 dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n");
91 regulator_put(hsusb_vddcx);
92 }
93 } else {
94 ret = regulator_set_voltage(hsusb_vddcx, 0,
95 USB_PHY_VDD_DIG_VOL_MIN);
96 if (ret) {
97 dev_err(motg->otg.dev, "unable to set the voltage "
98 "for hsusb vddcx\n");
99 return ret;
100 }
101 ret = regulator_disable(hsusb_vddcx);
102 if (ret)
103 dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
104
105 regulator_put(hsusb_vddcx);
106 }
107
108 return ret;
109}
110
111static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
112{
113 int rc = 0;
114
115 if (init) {
116 hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
117 if (IS_ERR(hsusb_3p3)) {
118 dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
119 return PTR_ERR(hsusb_3p3);
120 }
121
122 rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
123 USB_PHY_3P3_VOL_MAX);
124 if (rc) {
125 dev_err(motg->otg.dev, "unable to set voltage level "
126 "for hsusb 3p3\n");
127 goto put_3p3;
128 }
129 rc = regulator_enable(hsusb_3p3);
130 if (rc) {
131 dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n");
132 goto put_3p3;
133 }
134 hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
135 if (IS_ERR(hsusb_1p8)) {
136 dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
137 rc = PTR_ERR(hsusb_1p8);
138 goto disable_3p3;
139 }
140 rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
141 USB_PHY_1P8_VOL_MAX);
142 if (rc) {
143 dev_err(motg->otg.dev, "unable to set voltage level "
144 "for hsusb 1p8\n");
145 goto put_1p8;
146 }
147 rc = regulator_enable(hsusb_1p8);
148 if (rc) {
149 dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n");
150 goto put_1p8;
151 }
152
153 return 0;
154 }
155
156 regulator_disable(hsusb_1p8);
157put_1p8:
158 regulator_put(hsusb_1p8);
159disable_3p3:
160 regulator_disable(hsusb_3p3);
161put_3p3:
162 regulator_put(hsusb_3p3);
163 return rc;
164}
165
166static int msm_hsusb_ldo_set_mode(int on)
167{
168 int ret = 0;
169
170 if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
171 pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
172 return -ENODEV;
173 }
174
175 if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
176 pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
177 return -ENODEV;
178 }
179
180 if (on) {
181 ret = regulator_set_optimum_mode(hsusb_1p8,
182 USB_PHY_1P8_HPM_LOAD);
183 if (ret < 0) {
184 pr_err("%s: Unable to set HPM of the regulator "
185 "HSUSB_1p8\n", __func__);
186 return ret;
187 }
188 ret = regulator_set_optimum_mode(hsusb_3p3,
189 USB_PHY_3P3_HPM_LOAD);
190 if (ret < 0) {
191 pr_err("%s: Unable to set HPM of the regulator "
192 "HSUSB_3p3\n", __func__);
193 regulator_set_optimum_mode(hsusb_1p8,
194 USB_PHY_1P8_LPM_LOAD);
195 return ret;
196 }
197 } else {
198 ret = regulator_set_optimum_mode(hsusb_1p8,
199 USB_PHY_1P8_LPM_LOAD);
200 if (ret < 0)
201 pr_err("%s: Unable to set LPM of the regulator "
202 "HSUSB_1p8\n", __func__);
203 ret = regulator_set_optimum_mode(hsusb_3p3,
204 USB_PHY_3P3_LPM_LOAD);
205 if (ret < 0)
206 pr_err("%s: Unable to set LPM of the regulator "
207 "HSUSB_3p3\n", __func__);
208 }
209
210 pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
211 return ret < 0 ? ret : 0;
212}
213
48static int ulpi_read(struct otg_transceiver *otg, u32 reg) 214static int ulpi_read(struct otg_transceiver *otg, u32 reg)
49{ 215{
50 struct msm_otg *motg = container_of(otg, struct msm_otg, otg); 216 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -1297,6 +1463,24 @@ static int __init msm_otg_probe(struct platform_device *pdev)
1297 1463
1298 clk_enable(motg->clk); 1464 clk_enable(motg->clk);
1299 clk_enable(motg->pclk); 1465 clk_enable(motg->pclk);
1466
1467 ret = msm_hsusb_init_vddcx(motg, 1);
1468 if (ret) {
1469 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
1470 goto free_regs;
1471 }
1472
1473 ret = msm_hsusb_ldo_init(motg, 1);
1474 if (ret) {
1475 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
1476 goto vddcx_exit;
1477 }
1478 ret = msm_hsusb_ldo_set_mode(1);
1479 if (ret) {
1480 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
1481 goto ldo_exit;
1482 }
1483
1300 if (motg->core_clk) 1484 if (motg->core_clk)
1301 clk_enable(motg->core_clk); 1485 clk_enable(motg->core_clk);
1302 1486
@@ -1345,6 +1529,10 @@ free_irq:
1345disable_clks: 1529disable_clks:
1346 clk_disable(motg->pclk); 1530 clk_disable(motg->pclk);
1347 clk_disable(motg->clk); 1531 clk_disable(motg->clk);
1532ldo_exit:
1533 msm_hsusb_ldo_init(motg, 0);
1534vddcx_exit:
1535 msm_hsusb_init_vddcx(motg, 0);
1348free_regs: 1536free_regs:
1349 iounmap(motg->regs); 1537 iounmap(motg->regs);
1350put_core_clk: 1538put_core_clk:
@@ -1410,6 +1598,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
1410 clk_disable(motg->pclk_src); 1598 clk_disable(motg->pclk_src);
1411 clk_put(motg->pclk_src); 1599 clk_put(motg->pclk_src);
1412 } 1600 }
1601 msm_hsusb_ldo_init(motg, 0);
1413 1602
1414 iounmap(motg->regs); 1603 iounmap(motg->regs);
1415 pm_runtime_set_suspended(&pdev->dev); 1604 pm_runtime_set_suspended(&pdev->dev);