diff options
author | Anji jonnala <anjir@codeaurora.org> | 2011-05-04 00:49:48 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-05-06 21:27:48 -0400 |
commit | 11aa5c478e743712228ff2da881b85100800c1ee (patch) | |
tree | 3f9db60dfa9421b42d5dd234578cf092f515d211 | |
parent | d860852e087eed7eadbea64f1a8db9a231c5e9b3 (diff) |
USB: OTG: msm: Configure PHY Analog and Digital voltage domains
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/otg/msm_otg.c | 189 |
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 | |||
63 | static struct regulator *hsusb_3p3; | ||
64 | static struct regulator *hsusb_1p8; | ||
65 | static struct regulator *hsusb_vddcx; | ||
66 | |||
67 | static 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 | |||
111 | static 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); | ||
157 | put_1p8: | ||
158 | regulator_put(hsusb_1p8); | ||
159 | disable_3p3: | ||
160 | regulator_disable(hsusb_3p3); | ||
161 | put_3p3: | ||
162 | regulator_put(hsusb_3p3); | ||
163 | return rc; | ||
164 | } | ||
165 | |||
166 | static 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 | |||
48 | static int ulpi_read(struct otg_transceiver *otg, u32 reg) | 214 | static 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: | |||
1345 | disable_clks: | 1529 | disable_clks: |
1346 | clk_disable(motg->pclk); | 1530 | clk_disable(motg->pclk); |
1347 | clk_disable(motg->clk); | 1531 | clk_disable(motg->clk); |
1532 | ldo_exit: | ||
1533 | msm_hsusb_ldo_init(motg, 0); | ||
1534 | vddcx_exit: | ||
1535 | msm_hsusb_init_vddcx(motg, 0); | ||
1348 | free_regs: | 1536 | free_regs: |
1349 | iounmap(motg->regs); | 1537 | iounmap(motg->regs); |
1350 | put_core_clk: | 1538 | put_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); |