blob: 9d1cef7ed635c414a4430ade32a576d7c7c651a4 [file] [log] [blame]
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301/* ehci-msm-hsic.c - HSUSB Host Controller Driver Implementation
2 *
Manu Gautam5143b252012-01-05 19:25:23 -08003 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05304 *
5 * Partly derived from ehci-fsl.c and ehci-hcd.c
6 * Copyright (c) 2000-2004 by David Brownell
7 * Copyright (c) 2005 MontaVista Software
8 *
9 * All source code in this file is licensed under the following license except
10 * where indicated.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published
14 * by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * See the GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, you can find it at http://www.fsf.org
23 */
24
25#include <linux/platform_device.h>
26#include <linux/clk.h>
27#include <linux/err.h>
28#include <linux/wakelock.h>
29#include <linux/pm_runtime.h>
30#include <linux/regulator/consumer.h>
31
32#include <linux/usb/msm_hsusb_hw.h>
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +053033#include <linux/usb/msm_hsusb.h>
34#include <linux/gpio.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053035#include <mach/clk.h>
36#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053037#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080038#include <linux/spinlock.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053039
40#define MSM_USB_BASE (hcd->regs)
41
42struct msm_hsic_hcd {
43 struct ehci_hcd ehci;
44 struct device *dev;
45 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080046 struct clk *core_clk;
47 struct clk *alt_core_clk;
48 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053049 struct clk *cal_clk;
50 struct regulator *hsic_vddcx;
51 bool async_int;
52 atomic_t in_lpm;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053053 struct msm_xo_voter *xo_handle;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053054 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080055 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080056 int wakeup_irq;
Jack Phamfe441ea2012-03-23 17:03:15 -070057 bool wakeup_irq_enabled;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053058};
59
60static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
61{
62 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
63}
64
65static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
66{
67 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
68}
69
70#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
71
Vamsi Krishna45d88fa2011-11-02 13:28:42 -070072#define USB_PHY_VDD_DIG_VOL_SUSP_MIN 500000 /* uV */
73#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
74#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
75#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053076
Lena Salman8c8ba382012-02-14 15:59:31 +020077#define HSIC_DBG1_REG 0x38
78
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053079static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
80{
81 int ret = 0;
82
83 if (!init)
84 goto disable_reg;
85
Mayank Rana189ac052012-03-24 04:35:02 +053086 mehci->hsic_vddcx = devm_regulator_get(mehci->dev, "HSIC_VDDCX");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053087 if (IS_ERR(mehci->hsic_vddcx)) {
88 dev_err(mehci->dev, "unable to get hsic vddcx\n");
89 return PTR_ERR(mehci->hsic_vddcx);
90 }
91
92 ret = regulator_set_voltage(mehci->hsic_vddcx,
93 USB_PHY_VDD_DIG_VOL_MIN,
94 USB_PHY_VDD_DIG_VOL_MAX);
95 if (ret) {
96 dev_err(mehci->dev, "unable to set the voltage"
97 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +053098 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053099 }
100
101 ret = regulator_set_optimum_mode(mehci->hsic_vddcx,
102 USB_PHY_VDD_DIG_LOAD);
103 if (ret < 0) {
104 pr_err("%s: Unable to set optimum mode of the regulator:"
105 "VDDCX\n", __func__);
106 goto reg_optimum_mode_err;
107 }
108
109 ret = regulator_enable(mehci->hsic_vddcx);
110 if (ret) {
111 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
112 goto reg_enable_err;
113 }
114
115 return 0;
116
117disable_reg:
118 regulator_disable(mehci->hsic_vddcx);
119reg_enable_err:
120 regulator_set_optimum_mode(mehci->hsic_vddcx, 0);
121reg_optimum_mode_err:
122 regulator_set_voltage(mehci->hsic_vddcx, 0,
123 USB_PHY_VDD_DIG_VOL_MIN);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530124 return ret;
125
126}
127
128static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
129{
130 struct usb_hcd *hcd = hsic_to_hcd(mehci);
131 int cnt = 0;
132
133 /* initiate write operation */
134 writel_relaxed(ULPI_RUN | ULPI_WRITE |
135 ULPI_ADDR(reg) | ULPI_DATA(val),
136 USB_ULPI_VIEWPORT);
137
138 /* wait for completion */
139 while (cnt < ULPI_IO_TIMEOUT_USEC) {
140 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
141 break;
142 udelay(1);
143 cnt++;
144 }
145
146 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
147 dev_err(mehci->dev, "ulpi_write: timeout\n");
148 return -ETIMEDOUT;
149 }
150
151 return 0;
152}
153
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530154#define HSIC_HUB_VDD_VOL_MIN 1650000 /* uV */
155#define HSIC_HUB_VDD_VOL_MAX 1950000 /* uV */
156#define HSIC_HUB_VDD_LOAD 36000 /* uA */
157static int msm_hsic_config_hub(struct msm_hsic_hcd *mehci, int init)
158{
159 int ret = 0;
160 struct msm_hsic_host_platform_data *pdata;
161 static struct regulator *hsic_hub_reg;
162
163 pdata = mehci->dev->platform_data;
Lena Salman8c8ba382012-02-14 15:59:31 +0200164 if (!pdata || !pdata->hub_reset)
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530165 return ret;
166
167 if (!init)
168 goto disable_reg;
169
Mayank Rana189ac052012-03-24 04:35:02 +0530170 hsic_hub_reg = devm_regulator_get(mehci->dev, "EXT_HUB_VDDIO");
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530171 if (IS_ERR(hsic_hub_reg)) {
172 dev_err(mehci->dev, "unable to get ext hub vddcx\n");
173 return PTR_ERR(hsic_hub_reg);
174 }
175
176 ret = gpio_request(pdata->hub_reset, "HSIC_HUB_RESET_GPIO");
177 if (ret < 0) {
178 dev_err(mehci->dev, "gpio request failed for GPIO%d\n",
179 pdata->hub_reset);
Mayank Rana189ac052012-03-24 04:35:02 +0530180 return ret;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530181 }
182
183 ret = regulator_set_voltage(hsic_hub_reg,
184 HSIC_HUB_VDD_VOL_MIN,
185 HSIC_HUB_VDD_VOL_MAX);
186 if (ret) {
187 dev_err(mehci->dev, "unable to set the voltage"
188 "for hsic hub reg\n");
189 goto reg_set_voltage_fail;
190 }
191
192 ret = regulator_set_optimum_mode(hsic_hub_reg,
193 HSIC_HUB_VDD_LOAD);
194 if (ret < 0) {
195 pr_err("%s: Unable to set optimum mode of the regulator:"
196 "VDDCX\n", __func__);
197 goto reg_optimum_mode_fail;
198 }
199
200 ret = regulator_enable(hsic_hub_reg);
201 if (ret) {
202 dev_err(mehci->dev, "unable to enable ext hub vddcx\n");
203 goto reg_enable_fail;
204 }
205
206 gpio_direction_output(pdata->hub_reset, 0);
207 /* Hub reset should be asserted for minimum 2usec before deasserting */
208 udelay(5);
209 gpio_direction_output(pdata->hub_reset, 1);
210
211 return 0;
212
213disable_reg:
214 regulator_disable(hsic_hub_reg);
215reg_enable_fail:
216 regulator_set_optimum_mode(hsic_hub_reg, 0);
217reg_optimum_mode_fail:
218 regulator_set_voltage(hsic_hub_reg, 0,
219 HSIC_HUB_VDD_VOL_MIN);
220reg_set_voltage_fail:
221 gpio_free(pdata->hub_reset);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530222
223 return ret;
224
225}
226
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530227static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
228{
229 int rc = 0;
230 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800231 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530232
233 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800234
Lena Salman8c8ba382012-02-14 15:59:31 +0200235 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530236 return rc;
237
Vamsi Krishna34f01582011-12-14 19:54:42 -0800238 if (gpio_status == gpio_en)
239 return 0;
240
241 gpio_status = gpio_en;
242
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530243 if (!gpio_en)
244 goto free_gpio;
245
246 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
247 if (rc < 0) {
248 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
249 return rc;
250 }
251
252 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
253 if (rc < 0) {
254 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
255 goto free_strobe;
256 }
257
258 return 0;
259
260free_gpio:
261 gpio_free(pdata->data);
262free_strobe:
263 gpio_free(pdata->strobe);
264
265 return rc;
266}
267
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530268static int msm_hsic_phy_clk_reset(struct msm_hsic_hcd *mehci)
269{
270 int ret;
271
Manu Gautam28b1bac2012-01-30 16:43:06 +0530272 clk_prepare_enable(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530273
Manu Gautam5143b252012-01-05 19:25:23 -0800274 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530275 if (ret) {
Manu Gautam28b1bac2012-01-30 16:43:06 +0530276 clk_disable_unprepare(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530277 dev_err(mehci->dev, "usb phy clk assert failed\n");
278 return ret;
279 }
280 usleep_range(10000, 12000);
Manu Gautam28b1bac2012-01-30 16:43:06 +0530281 clk_disable_unprepare(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530282
Manu Gautam5143b252012-01-05 19:25:23 -0800283 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530284 if (ret)
285 dev_err(mehci->dev, "usb phy clk deassert failed\n");
286
287 return ret;
288}
289
290static int msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
291{
292 struct usb_hcd *hcd = hsic_to_hcd(mehci);
293 u32 val;
294 int ret;
295
296 ret = msm_hsic_phy_clk_reset(mehci);
297 if (ret)
298 return ret;
299
300 val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
301 writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);
302
303 /* Ensure that RESET operation is completed before turning off clock */
304 mb();
305 dev_dbg(mehci->dev, "phy_reset: success\n");
306
307 return 0;
308}
309
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530310#define HSIC_GPIO150_PAD_CTL (MSM_TLMM_BASE+0x20C0)
311#define HSIC_GPIO151_PAD_CTL (MSM_TLMM_BASE+0x20C4)
312#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
313#define HSIC_LV_MODE 0x04
314#define HSIC_PAD_CALIBRATION 0xA8
315#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530316#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
317static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
318{
319 struct usb_hcd *hcd = hsic_to_hcd(mehci);
320 int cnt = 0;
321 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200322 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530323
324 ret = msm_hsic_phy_reset(mehci);
325 if (ret) {
326 dev_err(mehci->dev, "phy_reset failed\n");
327 return ret;
328 }
329
330 writel_relaxed(USBCMD_RESET, USB_USBCMD);
331 while (cnt < LINK_RESET_TIMEOUT_USEC) {
332 if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
333 break;
334 udelay(1);
335 cnt++;
336 }
337 if (cnt >= LINK_RESET_TIMEOUT_USEC)
338 return -ETIMEDOUT;
339
Lena Salman8c8ba382012-02-14 15:59:31 +0200340 /* Reset PORTSC and select ULPI phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530341 writel_relaxed(0x80000000, USB_PORTSC);
342
343 /* TODO: Need to confirm if HSIC PHY also requires delay after RESET */
344 msleep(100);
345
346 /* HSIC PHY Initialization */
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530347
Lena Salman8c8ba382012-02-14 15:59:31 +0200348 /* HSIC init sequence when HSIC signals (Strobe/Data) are
349 routed via GPIOs */
350 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530351
Lena Salman8c8ba382012-02-14 15:59:31 +0200352 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
353 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530354
Lena Salman8c8ba382012-02-14 15:59:31 +0200355 /*set periodic calibration interval to ~2.048sec in
356 HSIC_IO_CAL_REG */
357 ulpi_write(mehci, 0xFF, 0x33);
358
359 /* Enable periodic IO calibration in HSIC_CFG register */
360 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
361
362 /* Configure GPIO 150/151 pins for HSIC functionality mode */
363 ret = msm_hsic_config_gpios(mehci, 1);
364 if (ret) {
365 dev_err(mehci->dev, " gpio configuarion failed\n");
366 return ret;
367 }
368 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL
369 register */
370 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
371 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
372 /* Enable HSIC mode in HSIC_CFG register */
373 ulpi_write(mehci, 0x01, 0x31);
374 } else {
375 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
376 via dedicated I/O */
377
378 /* programmable length of connect signaling (33.2ns) */
379 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
380 if (ret) {
381 pr_err("%s: Unable to program length of connect "
382 "signaling\n", __func__);
383 }
384
385 /*set periodic calibration interval to ~2.048sec in
386 HSIC_IO_CAL_REG */
387 ulpi_write(mehci, 0xFF, 0x33);
388
389 /* Enable HSIC mode in HSIC_CFG register */
390 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530391 }
392
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530393 return 0;
394}
395
396#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
397#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
398
399#ifdef CONFIG_PM_SLEEP
400static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
401{
402 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530403 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530404 u32 val;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530405 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530406
407 if (atomic_read(&mehci->in_lpm)) {
408 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
409 return 0;
410 }
411
412 disable_irq(hcd->irq);
413 /*
414 * PHY may take some time or even fail to enter into low power
415 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
416 * in failure case.
417 */
418 val = readl_relaxed(USB_PORTSC) | PORTSC_PHCD;
419 writel_relaxed(val, USB_PORTSC);
420 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
421 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
422 break;
423 udelay(1);
424 cnt++;
425 }
426
427 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
428 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530429 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530430 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530431 }
432
433 /*
434 * PHY has capability to generate interrupt asynchronously in low
435 * power mode (LPM). This interrupt is level triggered. So USB IRQ
436 * line must be disabled till async interrupt enable bit is cleared
437 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
438 * block data communication from PHY.
439 */
440 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
441 ULPI_STP_CTRL, USB_USBCMD);
442
443 /*
444 * Ensure that hardware is put in low power mode before
445 * clocks are turned OFF and VDD is allowed to minimize.
446 */
447 mb();
448
Manu Gautam28b1bac2012-01-30 16:43:06 +0530449 clk_disable_unprepare(mehci->core_clk);
450 clk_disable_unprepare(mehci->phy_clk);
451 clk_disable_unprepare(mehci->cal_clk);
452 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530453 pdata = mehci->dev->platform_data;
Lena Salman8c8ba382012-02-14 15:59:31 +0200454 if (pdata && pdata->hub_reset) {
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530455 ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_OFF);
456 if (ret)
457 pr_err("%s failed to devote for"
458 "TCXO D1 buffer%d\n", __func__, ret);
459 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530460
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700461 ret = regulator_set_voltage(mehci->hsic_vddcx,
462 USB_PHY_VDD_DIG_VOL_SUSP_MIN,
463 USB_PHY_VDD_DIG_VOL_MAX);
464 if (ret < 0)
465 dev_err(mehci->dev, "unable to set vddcx voltage: min:0.5v max:1.3v\n");
466
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530467 atomic_set(&mehci->in_lpm, 1);
468 enable_irq(hcd->irq);
469 wake_unlock(&mehci->wlock);
470
471 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
472
473 return 0;
474}
475
476static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
477{
478 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530479 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530480 unsigned temp;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530481 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530482
483 if (!atomic_read(&mehci->in_lpm)) {
484 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
485 return 0;
486 }
487
488 wake_lock(&mehci->wlock);
489
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700490 ret = regulator_set_voltage(mehci->hsic_vddcx,
491 USB_PHY_VDD_DIG_VOL_MIN,
492 USB_PHY_VDD_DIG_VOL_MAX);
493 if (ret < 0)
494 dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
495
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530496 pdata = mehci->dev->platform_data;
Lena Salman8c8ba382012-02-14 15:59:31 +0200497 if (pdata && pdata->hub_reset) {
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530498 ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_ON);
499 if (ret)
500 pr_err("%s failed to vote for"
501 "TCXO D1 buffer%d\n", __func__, ret);
502 }
Manu Gautam28b1bac2012-01-30 16:43:06 +0530503 clk_prepare_enable(mehci->core_clk);
504 clk_prepare_enable(mehci->phy_clk);
505 clk_prepare_enable(mehci->cal_clk);
506 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530507
508 temp = readl_relaxed(USB_USBCMD);
509 temp &= ~ASYNC_INTR_CTRL;
510 temp &= ~ULPI_STP_CTRL;
511 writel_relaxed(temp, USB_USBCMD);
512
513 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
514 goto skip_phy_resume;
515
516 temp = readl_relaxed(USB_PORTSC) & ~PORTSC_PHCD;
517 writel_relaxed(temp, USB_PORTSC);
518 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
519 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
520 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
521 break;
522 udelay(1);
523 cnt++;
524 }
525
526 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
527 /*
528 * This is a fatal error. Reset the link and
529 * PHY to make hsic working.
530 */
531 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530532 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530533 msm_hsic_reset(mehci);
534 }
535
536skip_phy_resume:
537
538 atomic_set(&mehci->in_lpm, 0);
539
540 if (mehci->async_int) {
541 mehci->async_int = false;
542 pm_runtime_put_noidle(mehci->dev);
543 enable_irq(hcd->irq);
544 }
545
546 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
547
548 return 0;
549}
550#endif
551
552static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
553{
554 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
555
556 if (atomic_read(&mehci->in_lpm)) {
557 disable_irq_nosync(hcd->irq);
558 mehci->async_int = true;
559 pm_runtime_get(mehci->dev);
560 return IRQ_HANDLED;
561 }
562
563 return ehci_irq(hcd);
564}
565
566static int ehci_hsic_reset(struct usb_hcd *hcd)
567{
568 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
569 int retval;
570
571 ehci->caps = USB_CAPLENGTH;
572 ehci->regs = USB_CAPLENGTH +
573 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
574 dbg_hcs_params(ehci, "reset");
575 dbg_hcc_params(ehci, "reset");
576
577 /* cache the data to minimize the chip reads*/
578 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
579
580 hcd->has_tt = 1;
581 ehci->sbrn = HCD_USB2;
582
583 retval = ehci_halt(ehci);
584 if (retval)
585 return retval;
586
587 /* data structure init */
588 retval = ehci_init(hcd);
589 if (retval)
590 return retval;
591
592 retval = ehci_reset(ehci);
593 if (retval)
594 return retval;
595
596 /* bursts of unspecified length. */
597 writel_relaxed(0, USB_AHBBURST);
598 /* Use the AHB transactor */
599 writel_relaxed(0, USB_AHBMODE);
600 /* Disable streaming mode and select host mode */
601 writel_relaxed(0x13, USB_USBMODE);
602
603 ehci_port_power(ehci, 1);
604 return 0;
605}
606
607static struct hc_driver msm_hsic_driver = {
608 .description = hcd_name,
609 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
610 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
611
612 /*
613 * generic hardware linkage
614 */
615 .irq = msm_hsic_irq,
616 .flags = HCD_USB2 | HCD_MEMORY,
617
618 .reset = ehci_hsic_reset,
619 .start = ehci_run,
620
621 .stop = ehci_stop,
622 .shutdown = ehci_shutdown,
623
624 /*
625 * managing i/o requests and associated device resources
626 */
627 .urb_enqueue = ehci_urb_enqueue,
628 .urb_dequeue = ehci_urb_dequeue,
629 .endpoint_disable = ehci_endpoint_disable,
630 .endpoint_reset = ehci_endpoint_reset,
631 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
632
633 /*
634 * scheduling support
635 */
636 .get_frame_number = ehci_get_frame,
637
638 /*
639 * root hub support
640 */
641 .hub_status_data = ehci_hub_status_data,
642 .hub_control = ehci_hub_control,
643 .relinquish_port = ehci_relinquish_port,
644 .port_handed_over = ehci_port_handed_over,
645
646 /*
647 * PM support
648 */
649 .bus_suspend = ehci_bus_suspend,
650 .bus_resume = ehci_bus_resume,
651};
652
653static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
654{
655 int ret = 0;
656
657 if (!init)
658 goto put_clocks;
659
Lena Salman8c8ba382012-02-14 15:59:31 +0200660 /*core_clk is required for LINK protocol engine
661 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800662 mehci->core_clk = clk_get(mehci->dev, "core_clk");
663 if (IS_ERR(mehci->core_clk)) {
664 dev_err(mehci->dev, "failed to get core_clk\n");
665 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530666 return ret;
667 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530668
Lena Salman8c8ba382012-02-14 15:59:31 +0200669 /* alt_core_clk is for LINK to be used during PHY RESET
670 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800671 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
672 if (IS_ERR(mehci->alt_core_clk)) {
673 dev_err(mehci->dev, "failed to core_clk\n");
674 ret = PTR_ERR(mehci->alt_core_clk);
675 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530676 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530677
Lena Salman8c8ba382012-02-14 15:59:31 +0200678 /* phy_clk is required for HSIC PHY operation
679 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800680 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
681 if (IS_ERR(mehci->phy_clk)) {
682 dev_err(mehci->dev, "failed to get phy_clk\n");
683 ret = PTR_ERR(mehci->phy_clk);
684 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530685 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530686
687 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -0800688 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530689 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800690 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530691 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800692 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530693 }
694 clk_set_rate(mehci->cal_clk, 10000000);
695
696 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -0800697 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530698 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800699 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530700 ret = PTR_ERR(mehci->ahb_clk);
701 goto put_cal_clk;
702 }
703
Manu Gautam28b1bac2012-01-30 16:43:06 +0530704 clk_prepare_enable(mehci->core_clk);
705 clk_prepare_enable(mehci->phy_clk);
706 clk_prepare_enable(mehci->cal_clk);
707 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530708
709 return 0;
710
711put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -0800712 if (!atomic_read(&mehci->in_lpm)) {
713 clk_disable_unprepare(mehci->core_clk);
714 clk_disable_unprepare(mehci->phy_clk);
715 clk_disable_unprepare(mehci->cal_clk);
716 clk_disable_unprepare(mehci->ahb_clk);
717 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530718 clk_put(mehci->ahb_clk);
719put_cal_clk:
720 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800721put_phy_clk:
722 clk_put(mehci->phy_clk);
723put_alt_core_clk:
724 clk_put(mehci->alt_core_clk);
725put_core_clk:
726 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530727
728 return ret;
729}
Vamsi Krishna34f01582011-12-14 19:54:42 -0800730static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
731{
732 struct msm_hsic_hcd *mehci = dev_id;
733
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800734 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -0800735
736 if (mehci)
737 msm_hsic_config_gpios(mehci, 0);
738
739 return IRQ_HANDLED;
740}
741
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800742static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
743{
744 struct msm_hsic_hcd *mehci = data;
745
746 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt\n", __func__);
747
Jack Phamfe441ea2012-03-23 17:03:15 -0700748 if (mehci->wakeup_irq_enabled) {
749 mehci->wakeup_irq_enabled = 0;
750 disable_irq_wake(irq);
751 disable_irq_nosync(irq);
752 }
753
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800754 return IRQ_HANDLED;
755}
756
757
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530758static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
759{
760 struct usb_hcd *hcd;
761 struct resource *res;
762 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530763 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530764 int ret;
765
766 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
767
768 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
769 dev_name(&pdev->dev));
770 if (!hcd) {
771 dev_err(&pdev->dev, "Unable to create HCD\n");
772 return -ENOMEM;
773 }
774
775 hcd->irq = platform_get_irq(pdev, 0);
776 if (hcd->irq < 0) {
777 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
778 ret = hcd->irq;
779 goto put_hcd;
780 }
781
782 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
783 if (!res) {
784 dev_err(&pdev->dev, "Unable to get memory resource\n");
785 ret = -ENODEV;
786 goto put_hcd;
787 }
788
789 hcd->rsrc_start = res->start;
790 hcd->rsrc_len = resource_size(res);
791 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
792 if (!hcd->regs) {
793 dev_err(&pdev->dev, "ioremap failed\n");
794 ret = -ENOMEM;
795 goto put_hcd;
796 }
797
798 mehci = hcd_to_hsic(hcd);
799 mehci->dev = &pdev->dev;
800
Vamsi Krishna34f01582011-12-14 19:54:42 -0800801 res = platform_get_resource_byname(pdev,
802 IORESOURCE_IRQ,
803 "peripheral_status_irq");
804 if (res)
805 mehci->peripheral_status_irq = res->start;
806
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530807 ret = msm_hsic_init_clocks(mehci, 1);
808 if (ret) {
809 dev_err(&pdev->dev, "unable to initialize clocks\n");
810 ret = -ENODEV;
811 goto unmap;
812 }
813
814 ret = msm_hsic_init_vddcx(mehci, 1);
815 if (ret) {
816 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
817 ret = -ENODEV;
818 goto deinit_clocks;
819 }
820
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530821 pdata = mehci->dev->platform_data;
Lena Salman8c8ba382012-02-14 15:59:31 +0200822 if (pdata && pdata->hub_reset) {
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530823 mehci->xo_handle = msm_xo_get(MSM_XO_TCXO_D1, "hsic");
824 if (IS_ERR(mehci->xo_handle)) {
825 pr_err(" %s not able to get the handle"
826 "to vote for TCXO D1 buffer\n", __func__);
827 ret = PTR_ERR(mehci->xo_handle);
828 goto deinit_vddcx;
829 }
830
831 ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_ON);
832 if (ret) {
833 pr_err("%s failed to vote for TCXO"
834 "D1 buffer%d\n", __func__, ret);
835 goto free_xo_handle;
836 }
837 }
838
839 ret = msm_hsic_config_hub(mehci, 1);
840 if (ret) {
841 dev_err(&pdev->dev, "unable to initialize hsic hub");
842 goto free_xo_handle;
843 }
844
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530845 ret = msm_hsic_reset(mehci);
846 if (ret) {
847 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530848 goto deinit_hub;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530849 }
850
851 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
852 if (ret) {
853 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530854 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530855 }
856
857 device_init_wakeup(&pdev->dev, 1);
858 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
859 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -0800860
861 if (mehci->peripheral_status_irq) {
862 ret = request_threaded_irq(mehci->peripheral_status_irq,
863 NULL, hsic_peripheral_status_change,
864 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
865 | IRQF_SHARED,
866 "hsic_peripheral_status", mehci);
867 if (ret)
868 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
869 __func__, mehci->peripheral_status_irq, ret);
870 }
871
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800872 /* configure wakeup irq */
873 ret = platform_get_irq(pdev, 2);
874 if (ret > 0) {
875 mehci->wakeup_irq = ret;
876 dev_dbg(&pdev->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
877 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
878 IRQF_TRIGGER_LOW,
879 "msm_hsic_wakeup", mehci);
880 if (!ret) {
881 disable_irq_nosync(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800882 } else {
883 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
884 mehci->wakeup_irq, ret);
885 mehci->wakeup_irq = 0;
886 }
887 }
888
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530889 /*
890 * This pdev->dev is assigned parent of root-hub by USB core,
891 * hence, runtime framework automatically calls this driver's
892 * runtime APIs based on root-hub's state.
893 */
894 pm_runtime_set_active(&pdev->dev);
895 pm_runtime_enable(&pdev->dev);
896
897 return 0;
898
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530899unconfig_gpio:
900 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530901deinit_hub:
902 msm_hsic_config_hub(mehci, 0);
903free_xo_handle:
Lena Salman8c8ba382012-02-14 15:59:31 +0200904 if (pdata && pdata->hub_reset)
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530905 msm_xo_put(mehci->xo_handle);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530906deinit_vddcx:
907 msm_hsic_init_vddcx(mehci, 0);
908deinit_clocks:
909 msm_hsic_init_clocks(mehci, 0);
910unmap:
911 iounmap(hcd->regs);
912put_hcd:
913 usb_put_hcd(hcd);
914
915 return ret;
916}
917
918static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
919{
920 struct usb_hcd *hcd = platform_get_drvdata(pdev);
921 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530922 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530923
Vamsi Krishna34f01582011-12-14 19:54:42 -0800924 if (mehci->peripheral_status_irq)
925 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -0700926
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800927 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -0700928 if (mehci->wakeup_irq_enabled)
929 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800930 free_irq(mehci->wakeup_irq, mehci);
931 }
Vamsi Krishna34f01582011-12-14 19:54:42 -0800932
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530933 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530934 pm_runtime_set_suspended(&pdev->dev);
935
936 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530937 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530938 msm_hsic_config_hub(mehci, 0);
939 pdata = mehci->dev->platform_data;
Lena Salman8c8ba382012-02-14 15:59:31 +0200940 if (pdata && pdata->hub_reset)
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530941 msm_xo_put(mehci->xo_handle);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530942 msm_hsic_init_vddcx(mehci, 0);
943
944 msm_hsic_init_clocks(mehci, 0);
945 wake_lock_destroy(&mehci->wlock);
946 iounmap(hcd->regs);
947 usb_put_hcd(hcd);
948
949 return 0;
950}
951
952#ifdef CONFIG_PM_SLEEP
953static int msm_hsic_pm_suspend(struct device *dev)
954{
955 struct usb_hcd *hcd = dev_get_drvdata(dev);
956 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
957
958 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
959
960 if (device_may_wakeup(dev))
961 enable_irq_wake(hcd->irq);
962
963 return msm_hsic_suspend(mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -0700964}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530965
Jack Phamfe441ea2012-03-23 17:03:15 -0700966static int msm_hsic_pm_suspend_noirq(struct device *dev)
967{
968 struct usb_hcd *hcd = dev_get_drvdata(dev);
969 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
970
971 dev_dbg(dev, "ehci-msm-hsic PM suspend_noirq\n");
972
973 if (device_may_wakeup(dev) && !mehci->wakeup_irq_enabled) {
974 enable_irq(mehci->wakeup_irq);
975 enable_irq_wake(mehci->wakeup_irq);
976 mehci->wakeup_irq_enabled = 1;
977 }
978
979 return 0;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530980}
981
982static int msm_hsic_pm_resume(struct device *dev)
983{
984 int ret;
985 struct usb_hcd *hcd = dev_get_drvdata(dev);
986 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
987
988 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
989
990 if (device_may_wakeup(dev))
991 disable_irq_wake(hcd->irq);
992
Jack Phamfe441ea2012-03-23 17:03:15 -0700993 if (mehci->wakeup_irq_enabled) {
994 mehci->wakeup_irq_enabled = 0;
995 disable_irq_wake(mehci->wakeup_irq);
996 disable_irq_nosync(mehci->wakeup_irq);
997 }
998
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530999 ret = msm_hsic_resume(mehci);
1000 if (ret)
1001 return ret;
1002
1003 /* Bring the device to full powered state upon system resume */
1004 pm_runtime_disable(dev);
1005 pm_runtime_set_active(dev);
1006 pm_runtime_enable(dev);
1007
1008 return 0;
1009}
1010#endif
1011
1012#ifdef CONFIG_PM_RUNTIME
1013static int msm_hsic_runtime_idle(struct device *dev)
1014{
1015 dev_dbg(dev, "EHCI runtime idle\n");
1016
1017 return 0;
1018}
1019
1020static int msm_hsic_runtime_suspend(struct device *dev)
1021{
1022 struct usb_hcd *hcd = dev_get_drvdata(dev);
1023 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1024
1025 dev_dbg(dev, "EHCI runtime suspend\n");
1026 return msm_hsic_suspend(mehci);
1027}
1028
1029static int msm_hsic_runtime_resume(struct device *dev)
1030{
1031 struct usb_hcd *hcd = dev_get_drvdata(dev);
1032 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1033
1034 dev_dbg(dev, "EHCI runtime resume\n");
1035 return msm_hsic_resume(mehci);
1036}
1037#endif
1038
1039#ifdef CONFIG_PM
1040static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1041 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Phamfe441ea2012-03-23 17:03:15 -07001042 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301043 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1044 msm_hsic_runtime_idle)
1045};
1046#endif
1047
1048static struct platform_driver ehci_msm_hsic_driver = {
1049 .probe = ehci_hsic_msm_probe,
1050 .remove = __devexit_p(ehci_hsic_msm_remove),
1051 .driver = {
1052 .name = "msm_hsic_host",
1053#ifdef CONFIG_PM
1054 .pm = &msm_hsic_dev_pm_ops,
1055#endif
1056 },
1057};