blob: 5ee19083c5acae4b8095d67719179b1aa95aa349 [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>
Hemant Kumare6275972012-02-29 20:06:21 -080028#include <linux/debugfs.h>
29#include <linux/seq_file.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053030#include <linux/wakelock.h>
31#include <linux/pm_runtime.h>
32#include <linux/regulator/consumer.h>
Hemant Kumare6275972012-02-29 20:06:21 -080033#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053034
35#include <linux/usb/msm_hsusb_hw.h>
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +053036#include <linux/usb/msm_hsusb.h>
37#include <linux/gpio.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053038#include <mach/clk.h>
39#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053040#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080041#include <linux/spinlock.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053042
43#define MSM_USB_BASE (hcd->regs)
44
45struct msm_hsic_hcd {
46 struct ehci_hcd ehci;
47 struct device *dev;
48 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080049 struct clk *core_clk;
50 struct clk *alt_core_clk;
51 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053052 struct clk *cal_clk;
53 struct regulator *hsic_vddcx;
54 bool async_int;
55 atomic_t in_lpm;
56 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080057 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080058 int wakeup_irq;
Jack Phamfe441ea2012-03-23 17:03:15 -070059 bool wakeup_irq_enabled;
Hemant Kumare6275972012-02-29 20:06:21 -080060 uint32_t bus_perf_client;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053061};
62
Hemant Kumare6275972012-02-29 20:06:21 -080063static bool debug_bus_voting_enabled = true;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053064static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
65{
66 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
67}
68
69static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
70{
71 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
72}
73
74#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
75
Vamsi Krishna45d88fa2011-11-02 13:28:42 -070076#define USB_PHY_VDD_DIG_VOL_SUSP_MIN 500000 /* uV */
77#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
78#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
79#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053080
Lena Salman8c8ba382012-02-14 15:59:31 +020081#define HSIC_DBG1_REG 0x38
82
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053083static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
84{
85 int ret = 0;
86
87 if (!init)
88 goto disable_reg;
89
Mayank Rana189ac052012-03-24 04:35:02 +053090 mehci->hsic_vddcx = devm_regulator_get(mehci->dev, "HSIC_VDDCX");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053091 if (IS_ERR(mehci->hsic_vddcx)) {
92 dev_err(mehci->dev, "unable to get hsic vddcx\n");
93 return PTR_ERR(mehci->hsic_vddcx);
94 }
95
96 ret = regulator_set_voltage(mehci->hsic_vddcx,
97 USB_PHY_VDD_DIG_VOL_MIN,
98 USB_PHY_VDD_DIG_VOL_MAX);
99 if (ret) {
100 dev_err(mehci->dev, "unable to set the voltage"
101 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530102 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530103 }
104
105 ret = regulator_set_optimum_mode(mehci->hsic_vddcx,
106 USB_PHY_VDD_DIG_LOAD);
107 if (ret < 0) {
108 pr_err("%s: Unable to set optimum mode of the regulator:"
109 "VDDCX\n", __func__);
110 goto reg_optimum_mode_err;
111 }
112
113 ret = regulator_enable(mehci->hsic_vddcx);
114 if (ret) {
115 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
116 goto reg_enable_err;
117 }
118
119 return 0;
120
121disable_reg:
122 regulator_disable(mehci->hsic_vddcx);
123reg_enable_err:
124 regulator_set_optimum_mode(mehci->hsic_vddcx, 0);
125reg_optimum_mode_err:
126 regulator_set_voltage(mehci->hsic_vddcx, 0,
127 USB_PHY_VDD_DIG_VOL_MIN);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530128 return ret;
129
130}
131
132static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
133{
134 struct usb_hcd *hcd = hsic_to_hcd(mehci);
135 int cnt = 0;
136
137 /* initiate write operation */
138 writel_relaxed(ULPI_RUN | ULPI_WRITE |
139 ULPI_ADDR(reg) | ULPI_DATA(val),
140 USB_ULPI_VIEWPORT);
141
142 /* wait for completion */
143 while (cnt < ULPI_IO_TIMEOUT_USEC) {
144 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
145 break;
146 udelay(1);
147 cnt++;
148 }
149
150 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
151 dev_err(mehci->dev, "ulpi_write: timeout\n");
152 return -ETIMEDOUT;
153 }
154
155 return 0;
156}
157
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530158static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
159{
160 int rc = 0;
161 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800162 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530163
164 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800165
Lena Salman8c8ba382012-02-14 15:59:31 +0200166 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530167 return rc;
168
Vamsi Krishna34f01582011-12-14 19:54:42 -0800169 if (gpio_status == gpio_en)
170 return 0;
171
172 gpio_status = gpio_en;
173
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530174 if (!gpio_en)
175 goto free_gpio;
176
177 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
178 if (rc < 0) {
179 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
180 return rc;
181 }
182
183 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
184 if (rc < 0) {
185 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
186 goto free_strobe;
187 }
188
189 return 0;
190
191free_gpio:
192 gpio_free(pdata->data);
193free_strobe:
194 gpio_free(pdata->strobe);
195
196 return rc;
197}
198
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530199static int msm_hsic_phy_clk_reset(struct msm_hsic_hcd *mehci)
200{
201 int ret;
202
Manu Gautam28b1bac2012-01-30 16:43:06 +0530203 clk_prepare_enable(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530204
Manu Gautam5143b252012-01-05 19:25:23 -0800205 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530206 if (ret) {
Manu Gautam28b1bac2012-01-30 16:43:06 +0530207 clk_disable_unprepare(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530208 dev_err(mehci->dev, "usb phy clk assert failed\n");
209 return ret;
210 }
211 usleep_range(10000, 12000);
Manu Gautam28b1bac2012-01-30 16:43:06 +0530212 clk_disable_unprepare(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530213
Manu Gautam5143b252012-01-05 19:25:23 -0800214 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530215 if (ret)
216 dev_err(mehci->dev, "usb phy clk deassert failed\n");
217
218 return ret;
219}
220
221static int msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
222{
223 struct usb_hcd *hcd = hsic_to_hcd(mehci);
224 u32 val;
225 int ret;
226
227 ret = msm_hsic_phy_clk_reset(mehci);
228 if (ret)
229 return ret;
230
231 val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
232 writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);
233
234 /* Ensure that RESET operation is completed before turning off clock */
235 mb();
236 dev_dbg(mehci->dev, "phy_reset: success\n");
237
238 return 0;
239}
240
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530241#define HSIC_GPIO150_PAD_CTL (MSM_TLMM_BASE+0x20C0)
242#define HSIC_GPIO151_PAD_CTL (MSM_TLMM_BASE+0x20C4)
243#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
244#define HSIC_LV_MODE 0x04
245#define HSIC_PAD_CALIBRATION 0xA8
246#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530247#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
248static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
249{
250 struct usb_hcd *hcd = hsic_to_hcd(mehci);
251 int cnt = 0;
252 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200253 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530254
255 ret = msm_hsic_phy_reset(mehci);
256 if (ret) {
257 dev_err(mehci->dev, "phy_reset failed\n");
258 return ret;
259 }
260
261 writel_relaxed(USBCMD_RESET, USB_USBCMD);
262 while (cnt < LINK_RESET_TIMEOUT_USEC) {
263 if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
264 break;
265 udelay(1);
266 cnt++;
267 }
268 if (cnt >= LINK_RESET_TIMEOUT_USEC)
269 return -ETIMEDOUT;
270
Lena Salman8c8ba382012-02-14 15:59:31 +0200271 /* Reset PORTSC and select ULPI phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530272 writel_relaxed(0x80000000, USB_PORTSC);
273
274 /* TODO: Need to confirm if HSIC PHY also requires delay after RESET */
275 msleep(100);
276
277 /* HSIC PHY Initialization */
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530278
Lena Salman8c8ba382012-02-14 15:59:31 +0200279 /* HSIC init sequence when HSIC signals (Strobe/Data) are
280 routed via GPIOs */
281 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530282
Lena Salman8c8ba382012-02-14 15:59:31 +0200283 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
284 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530285
Lena Salman8c8ba382012-02-14 15:59:31 +0200286 /*set periodic calibration interval to ~2.048sec in
287 HSIC_IO_CAL_REG */
288 ulpi_write(mehci, 0xFF, 0x33);
289
290 /* Enable periodic IO calibration in HSIC_CFG register */
291 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
292
293 /* Configure GPIO 150/151 pins for HSIC functionality mode */
294 ret = msm_hsic_config_gpios(mehci, 1);
295 if (ret) {
296 dev_err(mehci->dev, " gpio configuarion failed\n");
297 return ret;
298 }
299 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL
300 register */
301 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
302 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
303 /* Enable HSIC mode in HSIC_CFG register */
304 ulpi_write(mehci, 0x01, 0x31);
305 } else {
306 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
307 via dedicated I/O */
308
309 /* programmable length of connect signaling (33.2ns) */
310 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
311 if (ret) {
312 pr_err("%s: Unable to program length of connect "
313 "signaling\n", __func__);
314 }
315
316 /*set periodic calibration interval to ~2.048sec in
317 HSIC_IO_CAL_REG */
318 ulpi_write(mehci, 0xFF, 0x33);
319
320 /* Enable HSIC mode in HSIC_CFG register */
321 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530322 }
323
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530324 return 0;
325}
326
327#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
328#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
329
330#ifdef CONFIG_PM_SLEEP
331static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
332{
333 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530334 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530335 u32 val;
336
337 if (atomic_read(&mehci->in_lpm)) {
338 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
339 return 0;
340 }
341
342 disable_irq(hcd->irq);
343 /*
344 * PHY may take some time or even fail to enter into low power
345 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
346 * in failure case.
347 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700348 val = readl_relaxed(USB_PORTSC);
349 val &= ~PORT_RWC_BITS;
350 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530351 writel_relaxed(val, USB_PORTSC);
352 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
353 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
354 break;
355 udelay(1);
356 cnt++;
357 }
358
359 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
360 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530361 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530362 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530363 }
364
365 /*
366 * PHY has capability to generate interrupt asynchronously in low
367 * power mode (LPM). This interrupt is level triggered. So USB IRQ
368 * line must be disabled till async interrupt enable bit is cleared
369 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
370 * block data communication from PHY.
371 */
372 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
373 ULPI_STP_CTRL, USB_USBCMD);
374
375 /*
376 * Ensure that hardware is put in low power mode before
377 * clocks are turned OFF and VDD is allowed to minimize.
378 */
379 mb();
380
Manu Gautam28b1bac2012-01-30 16:43:06 +0530381 clk_disable_unprepare(mehci->core_clk);
382 clk_disable_unprepare(mehci->phy_clk);
383 clk_disable_unprepare(mehci->cal_clk);
384 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530385
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700386 ret = regulator_set_voltage(mehci->hsic_vddcx,
387 USB_PHY_VDD_DIG_VOL_SUSP_MIN,
388 USB_PHY_VDD_DIG_VOL_MAX);
389 if (ret < 0)
390 dev_err(mehci->dev, "unable to set vddcx voltage: min:0.5v max:1.3v\n");
391
Hemant Kumare6275972012-02-29 20:06:21 -0800392 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
393 ret = msm_bus_scale_client_update_request(
394 mehci->bus_perf_client, 0);
395 if (ret)
396 dev_err(mehci->dev, "%s: Failed to dvote for "
397 "bus bandwidth %d\n", __func__, ret);
398 }
399
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530400 atomic_set(&mehci->in_lpm, 1);
401 enable_irq(hcd->irq);
402 wake_unlock(&mehci->wlock);
403
404 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
405
406 return 0;
407}
408
409static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
410{
411 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530412 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530413 unsigned temp;
414
415 if (!atomic_read(&mehci->in_lpm)) {
416 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
417 return 0;
418 }
419
420 wake_lock(&mehci->wlock);
421
Hemant Kumare6275972012-02-29 20:06:21 -0800422 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
423 ret = msm_bus_scale_client_update_request(
424 mehci->bus_perf_client, 1);
425 if (ret)
426 dev_err(mehci->dev, "%s: Failed to vote for "
427 "bus bandwidth %d\n", __func__, ret);
428 }
429
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700430 ret = regulator_set_voltage(mehci->hsic_vddcx,
431 USB_PHY_VDD_DIG_VOL_MIN,
432 USB_PHY_VDD_DIG_VOL_MAX);
433 if (ret < 0)
434 dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
435
Manu Gautam28b1bac2012-01-30 16:43:06 +0530436 clk_prepare_enable(mehci->core_clk);
437 clk_prepare_enable(mehci->phy_clk);
438 clk_prepare_enable(mehci->cal_clk);
439 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530440
441 temp = readl_relaxed(USB_USBCMD);
442 temp &= ~ASYNC_INTR_CTRL;
443 temp &= ~ULPI_STP_CTRL;
444 writel_relaxed(temp, USB_USBCMD);
445
446 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
447 goto skip_phy_resume;
448
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700449 temp = readl_relaxed(USB_PORTSC);
450 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530451 writel_relaxed(temp, USB_PORTSC);
452 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
453 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
454 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
455 break;
456 udelay(1);
457 cnt++;
458 }
459
460 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
461 /*
462 * This is a fatal error. Reset the link and
463 * PHY to make hsic working.
464 */
465 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530466 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530467 msm_hsic_reset(mehci);
468 }
469
470skip_phy_resume:
471
472 atomic_set(&mehci->in_lpm, 0);
473
474 if (mehci->async_int) {
475 mehci->async_int = false;
476 pm_runtime_put_noidle(mehci->dev);
477 enable_irq(hcd->irq);
478 }
479
480 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
481
482 return 0;
483}
484#endif
485
486static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
487{
488 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
489
490 if (atomic_read(&mehci->in_lpm)) {
491 disable_irq_nosync(hcd->irq);
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700492 dev_dbg(mehci->dev, "phy async intr\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530493 mehci->async_int = true;
494 pm_runtime_get(mehci->dev);
495 return IRQ_HANDLED;
496 }
497
498 return ehci_irq(hcd);
499}
500
501static int ehci_hsic_reset(struct usb_hcd *hcd)
502{
503 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
504 int retval;
505
506 ehci->caps = USB_CAPLENGTH;
507 ehci->regs = USB_CAPLENGTH +
508 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
509 dbg_hcs_params(ehci, "reset");
510 dbg_hcc_params(ehci, "reset");
511
512 /* cache the data to minimize the chip reads*/
513 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
514
515 hcd->has_tt = 1;
516 ehci->sbrn = HCD_USB2;
517
518 retval = ehci_halt(ehci);
519 if (retval)
520 return retval;
521
522 /* data structure init */
523 retval = ehci_init(hcd);
524 if (retval)
525 return retval;
526
527 retval = ehci_reset(ehci);
528 if (retval)
529 return retval;
530
531 /* bursts of unspecified length. */
532 writel_relaxed(0, USB_AHBBURST);
533 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530534 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530535 /* Disable streaming mode and select host mode */
536 writel_relaxed(0x13, USB_USBMODE);
537
538 ehci_port_power(ehci, 1);
539 return 0;
540}
541
542static struct hc_driver msm_hsic_driver = {
543 .description = hcd_name,
544 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
545 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
546
547 /*
548 * generic hardware linkage
549 */
550 .irq = msm_hsic_irq,
551 .flags = HCD_USB2 | HCD_MEMORY,
552
553 .reset = ehci_hsic_reset,
554 .start = ehci_run,
555
556 .stop = ehci_stop,
557 .shutdown = ehci_shutdown,
558
559 /*
560 * managing i/o requests and associated device resources
561 */
562 .urb_enqueue = ehci_urb_enqueue,
563 .urb_dequeue = ehci_urb_dequeue,
564 .endpoint_disable = ehci_endpoint_disable,
565 .endpoint_reset = ehci_endpoint_reset,
566 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
567
568 /*
569 * scheduling support
570 */
571 .get_frame_number = ehci_get_frame,
572
573 /*
574 * root hub support
575 */
576 .hub_status_data = ehci_hub_status_data,
577 .hub_control = ehci_hub_control,
578 .relinquish_port = ehci_relinquish_port,
579 .port_handed_over = ehci_port_handed_over,
580
581 /*
582 * PM support
583 */
584 .bus_suspend = ehci_bus_suspend,
585 .bus_resume = ehci_bus_resume,
586};
587
588static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
589{
590 int ret = 0;
591
592 if (!init)
593 goto put_clocks;
594
Lena Salman8c8ba382012-02-14 15:59:31 +0200595 /*core_clk is required for LINK protocol engine
596 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800597 mehci->core_clk = clk_get(mehci->dev, "core_clk");
598 if (IS_ERR(mehci->core_clk)) {
599 dev_err(mehci->dev, "failed to get core_clk\n");
600 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530601 return ret;
602 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530603
Lena Salman8c8ba382012-02-14 15:59:31 +0200604 /* alt_core_clk is for LINK to be used during PHY RESET
605 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800606 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
607 if (IS_ERR(mehci->alt_core_clk)) {
608 dev_err(mehci->dev, "failed to core_clk\n");
609 ret = PTR_ERR(mehci->alt_core_clk);
610 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530611 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530612
Lena Salman8c8ba382012-02-14 15:59:31 +0200613 /* phy_clk is required for HSIC PHY operation
614 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800615 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
616 if (IS_ERR(mehci->phy_clk)) {
617 dev_err(mehci->dev, "failed to get phy_clk\n");
618 ret = PTR_ERR(mehci->phy_clk);
619 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530620 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530621
622 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -0800623 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530624 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800625 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530626 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800627 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530628 }
629 clk_set_rate(mehci->cal_clk, 10000000);
630
631 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -0800632 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530633 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800634 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530635 ret = PTR_ERR(mehci->ahb_clk);
636 goto put_cal_clk;
637 }
638
Manu Gautam28b1bac2012-01-30 16:43:06 +0530639 clk_prepare_enable(mehci->core_clk);
640 clk_prepare_enable(mehci->phy_clk);
641 clk_prepare_enable(mehci->cal_clk);
642 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530643
644 return 0;
645
646put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -0800647 if (!atomic_read(&mehci->in_lpm)) {
648 clk_disable_unprepare(mehci->core_clk);
649 clk_disable_unprepare(mehci->phy_clk);
650 clk_disable_unprepare(mehci->cal_clk);
651 clk_disable_unprepare(mehci->ahb_clk);
652 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530653 clk_put(mehci->ahb_clk);
654put_cal_clk:
655 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800656put_phy_clk:
657 clk_put(mehci->phy_clk);
658put_alt_core_clk:
659 clk_put(mehci->alt_core_clk);
660put_core_clk:
661 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530662
663 return ret;
664}
Vamsi Krishna34f01582011-12-14 19:54:42 -0800665static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
666{
667 struct msm_hsic_hcd *mehci = dev_id;
668
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800669 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -0800670
671 if (mehci)
672 msm_hsic_config_gpios(mehci, 0);
673
674 return IRQ_HANDLED;
675}
676
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800677static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
678{
679 struct msm_hsic_hcd *mehci = data;
680
681 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt\n", __func__);
682
Jack Phamfe441ea2012-03-23 17:03:15 -0700683 if (mehci->wakeup_irq_enabled) {
684 mehci->wakeup_irq_enabled = 0;
685 disable_irq_wake(irq);
686 disable_irq_nosync(irq);
687 }
688
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800689 return IRQ_HANDLED;
690}
691
Hemant Kumare6275972012-02-29 20:06:21 -0800692static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
693{
694 if (debug_bus_voting_enabled)
695 seq_printf(s, "enabled\n");
696 else
697 seq_printf(s, "disabled\n");
698
699 return 0;
700}
701
702static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
703{
704 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
705}
706
707static ssize_t ehci_hsic_msm_bus_write(struct file *file,
708 const char __user *ubuf, size_t count, loff_t *ppos)
709{
710 char buf[8];
711 int ret;
712 struct seq_file *s = file->private_data;
713 struct msm_hsic_hcd *mehci = s->private;
714
715 memset(buf, 0x00, sizeof(buf));
716
717 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
718 return -EFAULT;
719
720 if (!strncmp(buf, "enable", 6)) {
721 /* Do not vote here. Let hsic driver decide when to vote */
722 debug_bus_voting_enabled = true;
723 } else {
724 debug_bus_voting_enabled = false;
725 if (mehci->bus_perf_client) {
726 ret = msm_bus_scale_client_update_request(
727 mehci->bus_perf_client, 0);
728 if (ret)
729 dev_err(mehci->dev, "%s: Failed to devote "
730 "for bus bw %d\n", __func__, ret);
731 }
732 }
733
734 return count;
735}
736
737const struct file_operations ehci_hsic_msm_bus_fops = {
738 .open = ehci_hsic_msm_bus_open,
739 .read = seq_read,
740 .write = ehci_hsic_msm_bus_write,
741 .llseek = seq_lseek,
742 .release = single_release,
743};
744
745static struct dentry *ehci_hsic_msm_dbg_root;
746static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
747{
748 struct dentry *ehci_hsic_msm_dentry;
749
750 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
751
752 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
753 return -ENODEV;
754
755 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
756 S_IRUGO | S_IWUSR,
757 ehci_hsic_msm_dbg_root, mehci,
758 &ehci_hsic_msm_bus_fops);
759
760 if (!ehci_hsic_msm_dentry) {
761 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
762 return -ENODEV;
763 }
764
765 return 0;
766}
767
768static void ehci_hsic_msm_debugfs_cleanup(void)
769{
770 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
771}
772
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530773static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
774{
775 struct usb_hcd *hcd;
776 struct resource *res;
777 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530778 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530779 int ret;
780
781 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
782
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530783 /* After parent device's probe is executed, it will be put in suspend
784 * mode. When child device's probe is called, driver core is not
785 * resuming parent device due to which parent will be in suspend even
786 * though child is active. Hence resume the parent device explicitly.
787 */
788 if (pdev->dev.parent)
789 pm_runtime_get_sync(pdev->dev.parent);
790
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530791 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
792 dev_name(&pdev->dev));
793 if (!hcd) {
794 dev_err(&pdev->dev, "Unable to create HCD\n");
795 return -ENOMEM;
796 }
797
798 hcd->irq = platform_get_irq(pdev, 0);
799 if (hcd->irq < 0) {
800 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
801 ret = hcd->irq;
802 goto put_hcd;
803 }
804
805 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
806 if (!res) {
807 dev_err(&pdev->dev, "Unable to get memory resource\n");
808 ret = -ENODEV;
809 goto put_hcd;
810 }
811
812 hcd->rsrc_start = res->start;
813 hcd->rsrc_len = resource_size(res);
814 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
815 if (!hcd->regs) {
816 dev_err(&pdev->dev, "ioremap failed\n");
817 ret = -ENOMEM;
818 goto put_hcd;
819 }
820
821 mehci = hcd_to_hsic(hcd);
822 mehci->dev = &pdev->dev;
823
Vamsi Krishna34f01582011-12-14 19:54:42 -0800824 res = platform_get_resource_byname(pdev,
825 IORESOURCE_IRQ,
826 "peripheral_status_irq");
827 if (res)
828 mehci->peripheral_status_irq = res->start;
829
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530830 ret = msm_hsic_init_clocks(mehci, 1);
831 if (ret) {
832 dev_err(&pdev->dev, "unable to initialize clocks\n");
833 ret = -ENODEV;
834 goto unmap;
835 }
836
837 ret = msm_hsic_init_vddcx(mehci, 1);
838 if (ret) {
839 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
840 ret = -ENODEV;
841 goto deinit_clocks;
842 }
843
844 ret = msm_hsic_reset(mehci);
845 if (ret) {
846 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530847 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530848 }
849
850 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
851 if (ret) {
852 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530853 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530854 }
855
856 device_init_wakeup(&pdev->dev, 1);
857 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
858 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -0800859
860 if (mehci->peripheral_status_irq) {
861 ret = request_threaded_irq(mehci->peripheral_status_irq,
862 NULL, hsic_peripheral_status_change,
863 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
864 | IRQF_SHARED,
865 "hsic_peripheral_status", mehci);
866 if (ret)
867 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
868 __func__, mehci->peripheral_status_irq, ret);
869 }
870
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800871 /* configure wakeup irq */
872 ret = platform_get_irq(pdev, 2);
873 if (ret > 0) {
874 mehci->wakeup_irq = ret;
875 dev_dbg(&pdev->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
876 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
877 IRQF_TRIGGER_LOW,
878 "msm_hsic_wakeup", mehci);
879 if (!ret) {
880 disable_irq_nosync(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800881 } else {
882 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
883 mehci->wakeup_irq, ret);
884 mehci->wakeup_irq = 0;
885 }
886 }
887
Hemant Kumare6275972012-02-29 20:06:21 -0800888 ret = ehci_hsic_msm_debugfs_init(mehci);
889 if (ret)
890 dev_dbg(&pdev->dev, "mode debugfs file is"
891 "not available\n");
892
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530893 pdata = mehci->dev->platform_data;
Hemant Kumare6275972012-02-29 20:06:21 -0800894 if (pdata && pdata->bus_scale_table) {
895 mehci->bus_perf_client =
896 msm_bus_scale_register_client(pdata->bus_scale_table);
897 /* Configure BUS performance parameters for MAX bandwidth */
898 if (mehci->bus_perf_client) {
899 ret = msm_bus_scale_client_update_request(
900 mehci->bus_perf_client, 1);
901 if (ret)
902 dev_err(&pdev->dev, "%s: Failed to vote for "
903 "bus bandwidth %d\n", __func__, ret);
904 } else {
905 dev_err(&pdev->dev, "%s: Failed to register BUS "
906 "scaling client!!\n", __func__);
907 }
908 }
909
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530910 /*
911 * This pdev->dev is assigned parent of root-hub by USB core,
912 * hence, runtime framework automatically calls this driver's
913 * runtime APIs based on root-hub's state.
914 */
915 pm_runtime_set_active(&pdev->dev);
916 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530917 /* Decrement the parent device's counter after probe.
918 * As child is active, parent will not be put into
919 * suspend mode.
920 */
921 if (pdev->dev.parent)
922 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530923
924 return 0;
925
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530926unconfig_gpio:
927 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530928deinit_vddcx:
929 msm_hsic_init_vddcx(mehci, 0);
930deinit_clocks:
931 msm_hsic_init_clocks(mehci, 0);
932unmap:
933 iounmap(hcd->regs);
934put_hcd:
935 usb_put_hcd(hcd);
936
937 return ret;
938}
939
940static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
941{
942 struct usb_hcd *hcd = platform_get_drvdata(pdev);
943 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
944
Vamsi Krishna34f01582011-12-14 19:54:42 -0800945 if (mehci->peripheral_status_irq)
946 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -0700947
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800948 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -0700949 if (mehci->wakeup_irq_enabled)
950 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800951 free_irq(mehci->wakeup_irq, mehci);
952 }
Vamsi Krishna34f01582011-12-14 19:54:42 -0800953
Hemant Kumare6275972012-02-29 20:06:21 -0800954 if (mehci->bus_perf_client)
955 msm_bus_scale_unregister_client(mehci->bus_perf_client);
956
957 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530958 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530959 pm_runtime_set_suspended(&pdev->dev);
960
961 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530962 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530963 msm_hsic_init_vddcx(mehci, 0);
964
965 msm_hsic_init_clocks(mehci, 0);
966 wake_lock_destroy(&mehci->wlock);
967 iounmap(hcd->regs);
968 usb_put_hcd(hcd);
969
970 return 0;
971}
972
973#ifdef CONFIG_PM_SLEEP
974static int msm_hsic_pm_suspend(struct device *dev)
975{
976 struct usb_hcd *hcd = dev_get_drvdata(dev);
977 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
978
979 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
980
981 if (device_may_wakeup(dev))
982 enable_irq_wake(hcd->irq);
983
984 return msm_hsic_suspend(mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -0700985}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530986
Jack Phamfe441ea2012-03-23 17:03:15 -0700987static int msm_hsic_pm_suspend_noirq(struct device *dev)
988{
989 struct usb_hcd *hcd = dev_get_drvdata(dev);
990 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
991
992 dev_dbg(dev, "ehci-msm-hsic PM suspend_noirq\n");
993
994 if (device_may_wakeup(dev) && !mehci->wakeup_irq_enabled) {
995 enable_irq(mehci->wakeup_irq);
996 enable_irq_wake(mehci->wakeup_irq);
997 mehci->wakeup_irq_enabled = 1;
998 }
999
1000 return 0;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301001}
1002
1003static int msm_hsic_pm_resume(struct device *dev)
1004{
1005 int ret;
1006 struct usb_hcd *hcd = dev_get_drvdata(dev);
1007 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1008
1009 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
1010
1011 if (device_may_wakeup(dev))
1012 disable_irq_wake(hcd->irq);
1013
Jack Phamfe441ea2012-03-23 17:03:15 -07001014 if (mehci->wakeup_irq_enabled) {
1015 mehci->wakeup_irq_enabled = 0;
1016 disable_irq_wake(mehci->wakeup_irq);
1017 disable_irq_nosync(mehci->wakeup_irq);
1018 }
1019
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301020 ret = msm_hsic_resume(mehci);
1021 if (ret)
1022 return ret;
1023
1024 /* Bring the device to full powered state upon system resume */
1025 pm_runtime_disable(dev);
1026 pm_runtime_set_active(dev);
1027 pm_runtime_enable(dev);
1028
1029 return 0;
1030}
1031#endif
1032
1033#ifdef CONFIG_PM_RUNTIME
1034static int msm_hsic_runtime_idle(struct device *dev)
1035{
Hemant Kumar68315252012-04-30 17:44:03 -07001036 struct usb_hcd *hcd = dev_get_drvdata(dev);
Hemant Kumar68315252012-04-30 17:44:03 -07001037
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301038 dev_dbg(dev, "EHCI runtime idle\n");
1039
Hemant Kumar3dbc5b32012-05-09 15:36:11 -07001040 /*don't allow runtime suspend in the middle of remote wakeup*/
1041 if (readl_relaxed(USB_PORTSC) & PORT_RESUME)
Hemant Kumar68315252012-04-30 17:44:03 -07001042 return -EAGAIN;
Hemant Kumar68315252012-04-30 17:44:03 -07001043
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301044 return 0;
1045}
1046
1047static int msm_hsic_runtime_suspend(struct device *dev)
1048{
1049 struct usb_hcd *hcd = dev_get_drvdata(dev);
1050 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1051
1052 dev_dbg(dev, "EHCI runtime suspend\n");
1053 return msm_hsic_suspend(mehci);
1054}
1055
1056static int msm_hsic_runtime_resume(struct device *dev)
1057{
1058 struct usb_hcd *hcd = dev_get_drvdata(dev);
1059 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1060
1061 dev_dbg(dev, "EHCI runtime resume\n");
1062 return msm_hsic_resume(mehci);
1063}
1064#endif
1065
1066#ifdef CONFIG_PM
1067static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1068 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Phamfe441ea2012-03-23 17:03:15 -07001069 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301070 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1071 msm_hsic_runtime_idle)
1072};
1073#endif
1074
1075static struct platform_driver ehci_msm_hsic_driver = {
1076 .probe = ehci_hsic_msm_probe,
1077 .remove = __devexit_p(ehci_hsic_msm_remove),
1078 .driver = {
1079 .name = "msm_hsic_host",
1080#ifdef CONFIG_PM
1081 .pm = &msm_hsic_dev_pm_ops,
1082#endif
1083 },
1084};