blob: 822abdcfcce3ca278506f630b3a1f64b85f73f03 [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;
Hemant Kumar6fd65032012-05-23 13:02:24 -070059 int wakeup_gpio;
Jack Phamfe441ea2012-03-23 17:03:15 -070060 bool wakeup_irq_enabled;
Hemant Kumar6fd65032012-05-23 13:02:24 -070061 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080062 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070063 uint32_t wakeup_int_cnt;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053064};
65
Hemant Kumare6275972012-02-29 20:06:21 -080066static bool debug_bus_voting_enabled = true;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053067static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
68{
69 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
70}
71
72static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
73{
74 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
75}
76
77#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
78
Vamsi Krishna45d88fa2011-11-02 13:28:42 -070079#define USB_PHY_VDD_DIG_VOL_SUSP_MIN 500000 /* uV */
80#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
81#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
82#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053083
Lena Salman8c8ba382012-02-14 15:59:31 +020084#define HSIC_DBG1_REG 0x38
85
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053086static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
87{
88 int ret = 0;
89
90 if (!init)
91 goto disable_reg;
92
Mayank Rana189ac052012-03-24 04:35:02 +053093 mehci->hsic_vddcx = devm_regulator_get(mehci->dev, "HSIC_VDDCX");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053094 if (IS_ERR(mehci->hsic_vddcx)) {
95 dev_err(mehci->dev, "unable to get hsic vddcx\n");
96 return PTR_ERR(mehci->hsic_vddcx);
97 }
98
99 ret = regulator_set_voltage(mehci->hsic_vddcx,
100 USB_PHY_VDD_DIG_VOL_MIN,
101 USB_PHY_VDD_DIG_VOL_MAX);
102 if (ret) {
103 dev_err(mehci->dev, "unable to set the voltage"
104 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530105 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530106 }
107
108 ret = regulator_set_optimum_mode(mehci->hsic_vddcx,
109 USB_PHY_VDD_DIG_LOAD);
110 if (ret < 0) {
111 pr_err("%s: Unable to set optimum mode of the regulator:"
112 "VDDCX\n", __func__);
113 goto reg_optimum_mode_err;
114 }
115
116 ret = regulator_enable(mehci->hsic_vddcx);
117 if (ret) {
118 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
119 goto reg_enable_err;
120 }
121
122 return 0;
123
124disable_reg:
125 regulator_disable(mehci->hsic_vddcx);
126reg_enable_err:
127 regulator_set_optimum_mode(mehci->hsic_vddcx, 0);
128reg_optimum_mode_err:
129 regulator_set_voltage(mehci->hsic_vddcx, 0,
130 USB_PHY_VDD_DIG_VOL_MIN);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530131 return ret;
132
133}
134
135static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
136{
137 struct usb_hcd *hcd = hsic_to_hcd(mehci);
138 int cnt = 0;
139
140 /* initiate write operation */
141 writel_relaxed(ULPI_RUN | ULPI_WRITE |
142 ULPI_ADDR(reg) | ULPI_DATA(val),
143 USB_ULPI_VIEWPORT);
144
145 /* wait for completion */
146 while (cnt < ULPI_IO_TIMEOUT_USEC) {
147 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
148 break;
149 udelay(1);
150 cnt++;
151 }
152
153 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
154 dev_err(mehci->dev, "ulpi_write: timeout\n");
155 return -ETIMEDOUT;
156 }
157
158 return 0;
159}
160
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530161static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
162{
163 int rc = 0;
164 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800165 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530166
167 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800168
Lena Salman8c8ba382012-02-14 15:59:31 +0200169 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530170 return rc;
171
Vamsi Krishna34f01582011-12-14 19:54:42 -0800172 if (gpio_status == gpio_en)
173 return 0;
174
175 gpio_status = gpio_en;
176
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530177 if (!gpio_en)
178 goto free_gpio;
179
180 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
181 if (rc < 0) {
182 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
183 return rc;
184 }
185
186 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
187 if (rc < 0) {
188 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
189 goto free_strobe;
190 }
191
Hemant Kumar6fd65032012-05-23 13:02:24 -0700192 if (mehci->wakeup_gpio) {
193 rc = gpio_request(mehci->wakeup_gpio, "HSIC_WAKEUP_GPIO");
194 if (rc < 0) {
195 dev_err(mehci->dev, "gpio request failed for HSIC WAKEUP\n");
196 goto free_data;
197 }
198 }
199
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530200 return 0;
201
202free_gpio:
Hemant Kumar6fd65032012-05-23 13:02:24 -0700203 if (mehci->wakeup_gpio)
204 gpio_free(mehci->wakeup_gpio);
205free_data:
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530206 gpio_free(pdata->data);
207free_strobe:
208 gpio_free(pdata->strobe);
209
210 return rc;
211}
212
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530213static int msm_hsic_phy_clk_reset(struct msm_hsic_hcd *mehci)
214{
215 int ret;
216
Manu Gautam28b1bac2012-01-30 16:43:06 +0530217 clk_prepare_enable(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530218
Manu Gautam5143b252012-01-05 19:25:23 -0800219 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530220 if (ret) {
Manu Gautam28b1bac2012-01-30 16:43:06 +0530221 clk_disable_unprepare(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530222 dev_err(mehci->dev, "usb phy clk assert failed\n");
223 return ret;
224 }
225 usleep_range(10000, 12000);
Manu Gautam28b1bac2012-01-30 16:43:06 +0530226 clk_disable_unprepare(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530227
Manu Gautam5143b252012-01-05 19:25:23 -0800228 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530229 if (ret)
230 dev_err(mehci->dev, "usb phy clk deassert failed\n");
231
232 return ret;
233}
234
235static int msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
236{
237 struct usb_hcd *hcd = hsic_to_hcd(mehci);
238 u32 val;
239 int ret;
240
241 ret = msm_hsic_phy_clk_reset(mehci);
242 if (ret)
243 return ret;
244
245 val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
246 writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);
247
248 /* Ensure that RESET operation is completed before turning off clock */
249 mb();
250 dev_dbg(mehci->dev, "phy_reset: success\n");
251
252 return 0;
253}
254
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530255#define HSIC_GPIO150_PAD_CTL (MSM_TLMM_BASE+0x20C0)
256#define HSIC_GPIO151_PAD_CTL (MSM_TLMM_BASE+0x20C4)
257#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
258#define HSIC_LV_MODE 0x04
259#define HSIC_PAD_CALIBRATION 0xA8
260#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530261#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
262static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
263{
264 struct usb_hcd *hcd = hsic_to_hcd(mehci);
265 int cnt = 0;
266 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200267 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530268
269 ret = msm_hsic_phy_reset(mehci);
270 if (ret) {
271 dev_err(mehci->dev, "phy_reset failed\n");
272 return ret;
273 }
274
275 writel_relaxed(USBCMD_RESET, USB_USBCMD);
276 while (cnt < LINK_RESET_TIMEOUT_USEC) {
277 if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
278 break;
279 udelay(1);
280 cnt++;
281 }
282 if (cnt >= LINK_RESET_TIMEOUT_USEC)
283 return -ETIMEDOUT;
284
Lena Salman8c8ba382012-02-14 15:59:31 +0200285 /* Reset PORTSC and select ULPI phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530286 writel_relaxed(0x80000000, USB_PORTSC);
287
288 /* TODO: Need to confirm if HSIC PHY also requires delay after RESET */
289 msleep(100);
290
291 /* HSIC PHY Initialization */
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530292
Lena Salman8c8ba382012-02-14 15:59:31 +0200293 /* HSIC init sequence when HSIC signals (Strobe/Data) are
294 routed via GPIOs */
295 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530296
Lena Salman8c8ba382012-02-14 15:59:31 +0200297 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
298 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530299
Lena Salman8c8ba382012-02-14 15:59:31 +0200300 /*set periodic calibration interval to ~2.048sec in
301 HSIC_IO_CAL_REG */
302 ulpi_write(mehci, 0xFF, 0x33);
303
304 /* Enable periodic IO calibration in HSIC_CFG register */
305 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
306
307 /* Configure GPIO 150/151 pins for HSIC functionality mode */
308 ret = msm_hsic_config_gpios(mehci, 1);
309 if (ret) {
310 dev_err(mehci->dev, " gpio configuarion failed\n");
311 return ret;
312 }
313 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL
314 register */
315 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
316 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
317 /* Enable HSIC mode in HSIC_CFG register */
318 ulpi_write(mehci, 0x01, 0x31);
319 } else {
320 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
321 via dedicated I/O */
322
323 /* programmable length of connect signaling (33.2ns) */
324 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
325 if (ret) {
326 pr_err("%s: Unable to program length of connect "
327 "signaling\n", __func__);
328 }
329
330 /*set periodic calibration interval to ~2.048sec in
331 HSIC_IO_CAL_REG */
332 ulpi_write(mehci, 0xFF, 0x33);
333
334 /* Enable HSIC mode in HSIC_CFG register */
335 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530336 }
337
Hemant Kumar6fd65032012-05-23 13:02:24 -0700338 /*disable auto resume*/
339 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
340
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530341 return 0;
342}
343
344#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
345#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
346
347#ifdef CONFIG_PM_SLEEP
348static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
349{
350 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530351 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530352 u32 val;
353
354 if (atomic_read(&mehci->in_lpm)) {
355 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
356 return 0;
357 }
358
Hemant Kumar7f374632012-05-31 20:10:32 -0700359 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
360 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
361 __func__);
362 return -EAGAIN;
363 }
364
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530365 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700366
367 /* make sure we don't race against a remote wakeup */
368 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
369 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
370 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
371 enable_irq(hcd->irq);
372 return -EBUSY;
373 }
374
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530375 /*
376 * PHY may take some time or even fail to enter into low power
377 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
378 * in failure case.
379 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700380 val = readl_relaxed(USB_PORTSC);
381 val &= ~PORT_RWC_BITS;
382 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530383 writel_relaxed(val, USB_PORTSC);
384 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
385 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
386 break;
387 udelay(1);
388 cnt++;
389 }
390
391 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
392 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530393 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530394 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530395 }
396
397 /*
398 * PHY has capability to generate interrupt asynchronously in low
399 * power mode (LPM). This interrupt is level triggered. So USB IRQ
400 * line must be disabled till async interrupt enable bit is cleared
401 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
402 * block data communication from PHY.
403 */
404 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
405 ULPI_STP_CTRL, USB_USBCMD);
406
407 /*
408 * Ensure that hardware is put in low power mode before
409 * clocks are turned OFF and VDD is allowed to minimize.
410 */
411 mb();
412
Manu Gautam28b1bac2012-01-30 16:43:06 +0530413 clk_disable_unprepare(mehci->core_clk);
414 clk_disable_unprepare(mehci->phy_clk);
415 clk_disable_unprepare(mehci->cal_clk);
416 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530417
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700418 ret = regulator_set_voltage(mehci->hsic_vddcx,
419 USB_PHY_VDD_DIG_VOL_SUSP_MIN,
420 USB_PHY_VDD_DIG_VOL_MAX);
421 if (ret < 0)
422 dev_err(mehci->dev, "unable to set vddcx voltage: min:0.5v max:1.3v\n");
423
Hemant Kumare6275972012-02-29 20:06:21 -0800424 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
425 ret = msm_bus_scale_client_update_request(
426 mehci->bus_perf_client, 0);
427 if (ret)
428 dev_err(mehci->dev, "%s: Failed to dvote for "
429 "bus bandwidth %d\n", __func__, ret);
430 }
431
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530432 atomic_set(&mehci->in_lpm, 1);
433 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700434
435 mehci->wakeup_irq_enabled = 1;
436 enable_irq_wake(mehci->wakeup_irq);
437 enable_irq(mehci->wakeup_irq);
438
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530439 wake_unlock(&mehci->wlock);
440
441 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
442
443 return 0;
444}
445
446static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
447{
448 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530449 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530450 unsigned temp;
451
452 if (!atomic_read(&mehci->in_lpm)) {
453 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
454 return 0;
455 }
456
Hemant Kumar6fd65032012-05-23 13:02:24 -0700457 if (mehci->wakeup_irq_enabled) {
458 disable_irq_wake(mehci->wakeup_irq);
459 disable_irq_nosync(mehci->wakeup_irq);
460 mehci->wakeup_irq_enabled = 0;
461 }
462
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530463 wake_lock(&mehci->wlock);
464
Hemant Kumare6275972012-02-29 20:06:21 -0800465 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
466 ret = msm_bus_scale_client_update_request(
467 mehci->bus_perf_client, 1);
468 if (ret)
469 dev_err(mehci->dev, "%s: Failed to vote for "
470 "bus bandwidth %d\n", __func__, ret);
471 }
472
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700473 ret = regulator_set_voltage(mehci->hsic_vddcx,
474 USB_PHY_VDD_DIG_VOL_MIN,
475 USB_PHY_VDD_DIG_VOL_MAX);
476 if (ret < 0)
477 dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
478
Manu Gautam28b1bac2012-01-30 16:43:06 +0530479 clk_prepare_enable(mehci->core_clk);
480 clk_prepare_enable(mehci->phy_clk);
481 clk_prepare_enable(mehci->cal_clk);
482 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530483
484 temp = readl_relaxed(USB_USBCMD);
485 temp &= ~ASYNC_INTR_CTRL;
486 temp &= ~ULPI_STP_CTRL;
487 writel_relaxed(temp, USB_USBCMD);
488
489 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
490 goto skip_phy_resume;
491
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700492 temp = readl_relaxed(USB_PORTSC);
493 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530494 writel_relaxed(temp, USB_PORTSC);
495 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
496 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
497 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
498 break;
499 udelay(1);
500 cnt++;
501 }
502
503 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
504 /*
505 * This is a fatal error. Reset the link and
506 * PHY to make hsic working.
507 */
508 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530509 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530510 msm_hsic_reset(mehci);
511 }
512
513skip_phy_resume:
514
Hemant Kumar6fd65032012-05-23 13:02:24 -0700515 usb_hcd_resume_root_hub(hcd);
516
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530517 atomic_set(&mehci->in_lpm, 0);
518
519 if (mehci->async_int) {
520 mehci->async_int = false;
521 pm_runtime_put_noidle(mehci->dev);
522 enable_irq(hcd->irq);
523 }
524
Hemant Kumar6fd65032012-05-23 13:02:24 -0700525 if (atomic_read(&mehci->pm_usage_cnt)) {
526 atomic_set(&mehci->pm_usage_cnt, 0);
527 pm_runtime_put_noidle(mehci->dev);
528 }
529
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530530 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
531
532 return 0;
533}
534#endif
535
536static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
537{
538 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
539
540 if (atomic_read(&mehci->in_lpm)) {
541 disable_irq_nosync(hcd->irq);
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700542 dev_dbg(mehci->dev, "phy async intr\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530543 mehci->async_int = true;
544 pm_runtime_get(mehci->dev);
545 return IRQ_HANDLED;
546 }
547
548 return ehci_irq(hcd);
549}
550
551static int ehci_hsic_reset(struct usb_hcd *hcd)
552{
553 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
554 int retval;
555
556 ehci->caps = USB_CAPLENGTH;
557 ehci->regs = USB_CAPLENGTH +
558 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
559 dbg_hcs_params(ehci, "reset");
560 dbg_hcc_params(ehci, "reset");
561
562 /* cache the data to minimize the chip reads*/
563 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
564
565 hcd->has_tt = 1;
566 ehci->sbrn = HCD_USB2;
567
568 retval = ehci_halt(ehci);
569 if (retval)
570 return retval;
571
572 /* data structure init */
573 retval = ehci_init(hcd);
574 if (retval)
575 return retval;
576
577 retval = ehci_reset(ehci);
578 if (retval)
579 return retval;
580
581 /* bursts of unspecified length. */
582 writel_relaxed(0, USB_AHBBURST);
583 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530584 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530585 /* Disable streaming mode and select host mode */
586 writel_relaxed(0x13, USB_USBMODE);
587
588 ehci_port_power(ehci, 1);
589 return 0;
590}
591
592static struct hc_driver msm_hsic_driver = {
593 .description = hcd_name,
594 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
595 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
596
597 /*
598 * generic hardware linkage
599 */
600 .irq = msm_hsic_irq,
601 .flags = HCD_USB2 | HCD_MEMORY,
602
603 .reset = ehci_hsic_reset,
604 .start = ehci_run,
605
606 .stop = ehci_stop,
607 .shutdown = ehci_shutdown,
608
609 /*
610 * managing i/o requests and associated device resources
611 */
612 .urb_enqueue = ehci_urb_enqueue,
613 .urb_dequeue = ehci_urb_dequeue,
614 .endpoint_disable = ehci_endpoint_disable,
615 .endpoint_reset = ehci_endpoint_reset,
616 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
617
618 /*
619 * scheduling support
620 */
621 .get_frame_number = ehci_get_frame,
622
623 /*
624 * root hub support
625 */
626 .hub_status_data = ehci_hub_status_data,
627 .hub_control = ehci_hub_control,
628 .relinquish_port = ehci_relinquish_port,
629 .port_handed_over = ehci_port_handed_over,
630
631 /*
632 * PM support
633 */
634 .bus_suspend = ehci_bus_suspend,
635 .bus_resume = ehci_bus_resume,
636};
637
638static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
639{
640 int ret = 0;
641
642 if (!init)
643 goto put_clocks;
644
Lena Salman8c8ba382012-02-14 15:59:31 +0200645 /*core_clk is required for LINK protocol engine
646 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800647 mehci->core_clk = clk_get(mehci->dev, "core_clk");
648 if (IS_ERR(mehci->core_clk)) {
649 dev_err(mehci->dev, "failed to get core_clk\n");
650 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530651 return ret;
652 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530653
Lena Salman8c8ba382012-02-14 15:59:31 +0200654 /* alt_core_clk is for LINK to be used during PHY RESET
655 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800656 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
657 if (IS_ERR(mehci->alt_core_clk)) {
658 dev_err(mehci->dev, "failed to core_clk\n");
659 ret = PTR_ERR(mehci->alt_core_clk);
660 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530661 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530662
Lena Salman8c8ba382012-02-14 15:59:31 +0200663 /* phy_clk is required for HSIC PHY operation
664 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800665 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
666 if (IS_ERR(mehci->phy_clk)) {
667 dev_err(mehci->dev, "failed to get phy_clk\n");
668 ret = PTR_ERR(mehci->phy_clk);
669 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530670 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530671
672 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -0800673 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530674 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800675 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530676 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800677 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530678 }
679 clk_set_rate(mehci->cal_clk, 10000000);
680
681 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -0800682 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530683 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800684 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530685 ret = PTR_ERR(mehci->ahb_clk);
686 goto put_cal_clk;
687 }
688
Manu Gautam28b1bac2012-01-30 16:43:06 +0530689 clk_prepare_enable(mehci->core_clk);
690 clk_prepare_enable(mehci->phy_clk);
691 clk_prepare_enable(mehci->cal_clk);
692 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530693
694 return 0;
695
696put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -0800697 if (!atomic_read(&mehci->in_lpm)) {
698 clk_disable_unprepare(mehci->core_clk);
699 clk_disable_unprepare(mehci->phy_clk);
700 clk_disable_unprepare(mehci->cal_clk);
701 clk_disable_unprepare(mehci->ahb_clk);
702 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530703 clk_put(mehci->ahb_clk);
704put_cal_clk:
705 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800706put_phy_clk:
707 clk_put(mehci->phy_clk);
708put_alt_core_clk:
709 clk_put(mehci->alt_core_clk);
710put_core_clk:
711 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530712
713 return ret;
714}
Vamsi Krishna34f01582011-12-14 19:54:42 -0800715static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
716{
717 struct msm_hsic_hcd *mehci = dev_id;
718
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800719 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -0800720
721 if (mehci)
722 msm_hsic_config_gpios(mehci, 0);
723
724 return IRQ_HANDLED;
725}
726
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800727static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
728{
729 struct msm_hsic_hcd *mehci = data;
730
Hemant Kumar6fd65032012-05-23 13:02:24 -0700731 mehci->wakeup_int_cnt++;
732 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
733 __func__, mehci->wakeup_int_cnt);
734
735 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800736
Jack Phamfe441ea2012-03-23 17:03:15 -0700737 if (mehci->wakeup_irq_enabled) {
738 mehci->wakeup_irq_enabled = 0;
739 disable_irq_wake(irq);
740 disable_irq_nosync(irq);
741 }
742
Hemant Kumar6fd65032012-05-23 13:02:24 -0700743 if (!atomic_read(&mehci->pm_usage_cnt)) {
744 atomic_set(&mehci->pm_usage_cnt, 1);
745 pm_runtime_get(mehci->dev);
746 }
747
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800748 return IRQ_HANDLED;
749}
750
Hemant Kumare6275972012-02-29 20:06:21 -0800751static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
752{
753 if (debug_bus_voting_enabled)
754 seq_printf(s, "enabled\n");
755 else
756 seq_printf(s, "disabled\n");
757
758 return 0;
759}
760
761static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
762{
763 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
764}
765
766static ssize_t ehci_hsic_msm_bus_write(struct file *file,
767 const char __user *ubuf, size_t count, loff_t *ppos)
768{
769 char buf[8];
770 int ret;
771 struct seq_file *s = file->private_data;
772 struct msm_hsic_hcd *mehci = s->private;
773
774 memset(buf, 0x00, sizeof(buf));
775
776 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
777 return -EFAULT;
778
779 if (!strncmp(buf, "enable", 6)) {
780 /* Do not vote here. Let hsic driver decide when to vote */
781 debug_bus_voting_enabled = true;
782 } else {
783 debug_bus_voting_enabled = false;
784 if (mehci->bus_perf_client) {
785 ret = msm_bus_scale_client_update_request(
786 mehci->bus_perf_client, 0);
787 if (ret)
788 dev_err(mehci->dev, "%s: Failed to devote "
789 "for bus bw %d\n", __func__, ret);
790 }
791 }
792
793 return count;
794}
795
796const struct file_operations ehci_hsic_msm_bus_fops = {
797 .open = ehci_hsic_msm_bus_open,
798 .read = seq_read,
799 .write = ehci_hsic_msm_bus_write,
800 .llseek = seq_lseek,
801 .release = single_release,
802};
803
Hemant Kumar6fd65032012-05-23 13:02:24 -0700804static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
805{
806 struct msm_hsic_hcd *mehci = s->private;
807
808 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
809
810 return 0;
811}
812
813static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
814{
815 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
816}
817
818const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
819 .open = ehci_hsic_msm_wakeup_cnt_open,
820 .read = seq_read,
821 .llseek = seq_lseek,
822 .release = single_release,
823};
824
Hemant Kumare6275972012-02-29 20:06:21 -0800825static struct dentry *ehci_hsic_msm_dbg_root;
826static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
827{
828 struct dentry *ehci_hsic_msm_dentry;
829
830 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
831
832 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
833 return -ENODEV;
834
835 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
836 S_IRUGO | S_IWUSR,
837 ehci_hsic_msm_dbg_root, mehci,
838 &ehci_hsic_msm_bus_fops);
839
840 if (!ehci_hsic_msm_dentry) {
841 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
842 return -ENODEV;
843 }
844
Hemant Kumar6fd65032012-05-23 13:02:24 -0700845 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
846 S_IRUGO,
847 ehci_hsic_msm_dbg_root, mehci,
848 &ehci_hsic_msm_wakeup_cnt_fops);
849
850 if (!ehci_hsic_msm_dentry) {
851 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
852 return -ENODEV;
853 }
854
Hemant Kumare6275972012-02-29 20:06:21 -0800855 return 0;
856}
857
858static void ehci_hsic_msm_debugfs_cleanup(void)
859{
860 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
861}
862
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530863static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
864{
865 struct usb_hcd *hcd;
866 struct resource *res;
867 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530868 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530869 int ret;
870
871 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
872
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530873 /* After parent device's probe is executed, it will be put in suspend
874 * mode. When child device's probe is called, driver core is not
875 * resuming parent device due to which parent will be in suspend even
876 * though child is active. Hence resume the parent device explicitly.
877 */
878 if (pdev->dev.parent)
879 pm_runtime_get_sync(pdev->dev.parent);
880
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530881 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
882 dev_name(&pdev->dev));
883 if (!hcd) {
884 dev_err(&pdev->dev, "Unable to create HCD\n");
885 return -ENOMEM;
886 }
887
888 hcd->irq = platform_get_irq(pdev, 0);
889 if (hcd->irq < 0) {
890 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
891 ret = hcd->irq;
892 goto put_hcd;
893 }
894
895 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
896 if (!res) {
897 dev_err(&pdev->dev, "Unable to get memory resource\n");
898 ret = -ENODEV;
899 goto put_hcd;
900 }
901
902 hcd->rsrc_start = res->start;
903 hcd->rsrc_len = resource_size(res);
904 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
905 if (!hcd->regs) {
906 dev_err(&pdev->dev, "ioremap failed\n");
907 ret = -ENOMEM;
908 goto put_hcd;
909 }
910
911 mehci = hcd_to_hsic(hcd);
912 mehci->dev = &pdev->dev;
913
Hemant Kumar38ce5d82012-05-29 13:00:58 -0700914 mehci->ehci.susp_sof_bug = 1;
915
Hemant Kumar933e0402012-05-22 11:11:40 -0700916 mehci->ehci.max_log2_irq_thresh = 6;
917
Vamsi Krishna34f01582011-12-14 19:54:42 -0800918 res = platform_get_resource_byname(pdev,
919 IORESOURCE_IRQ,
920 "peripheral_status_irq");
921 if (res)
922 mehci->peripheral_status_irq = res->start;
923
Hemant Kumar6fd65032012-05-23 13:02:24 -0700924 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
925 if (res) {
926 mehci->wakeup_gpio = res->start;
927 mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
928 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
929 }
930
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530931 ret = msm_hsic_init_clocks(mehci, 1);
932 if (ret) {
933 dev_err(&pdev->dev, "unable to initialize clocks\n");
934 ret = -ENODEV;
935 goto unmap;
936 }
937
938 ret = msm_hsic_init_vddcx(mehci, 1);
939 if (ret) {
940 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
941 ret = -ENODEV;
942 goto deinit_clocks;
943 }
944
945 ret = msm_hsic_reset(mehci);
946 if (ret) {
947 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530948 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530949 }
950
951 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
952 if (ret) {
953 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530954 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530955 }
956
957 device_init_wakeup(&pdev->dev, 1);
958 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
959 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -0800960
961 if (mehci->peripheral_status_irq) {
962 ret = request_threaded_irq(mehci->peripheral_status_irq,
963 NULL, hsic_peripheral_status_change,
964 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
965 | IRQF_SHARED,
966 "hsic_peripheral_status", mehci);
967 if (ret)
968 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
969 __func__, mehci->peripheral_status_irq, ret);
970 }
971
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800972 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -0700973 if (mehci->wakeup_irq) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800974 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -0700975 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800976 "msm_hsic_wakeup", mehci);
977 if (!ret) {
978 disable_irq_nosync(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800979 } else {
980 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
981 mehci->wakeup_irq, ret);
982 mehci->wakeup_irq = 0;
983 }
984 }
985
Hemant Kumare6275972012-02-29 20:06:21 -0800986 ret = ehci_hsic_msm_debugfs_init(mehci);
987 if (ret)
988 dev_dbg(&pdev->dev, "mode debugfs file is"
989 "not available\n");
990
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +0530991 pdata = mehci->dev->platform_data;
Hemant Kumare6275972012-02-29 20:06:21 -0800992 if (pdata && pdata->bus_scale_table) {
993 mehci->bus_perf_client =
994 msm_bus_scale_register_client(pdata->bus_scale_table);
995 /* Configure BUS performance parameters for MAX bandwidth */
996 if (mehci->bus_perf_client) {
997 ret = msm_bus_scale_client_update_request(
998 mehci->bus_perf_client, 1);
999 if (ret)
1000 dev_err(&pdev->dev, "%s: Failed to vote for "
1001 "bus bandwidth %d\n", __func__, ret);
1002 } else {
1003 dev_err(&pdev->dev, "%s: Failed to register BUS "
1004 "scaling client!!\n", __func__);
1005 }
1006 }
1007
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301008 /*
1009 * This pdev->dev is assigned parent of root-hub by USB core,
1010 * hence, runtime framework automatically calls this driver's
1011 * runtime APIs based on root-hub's state.
1012 */
1013 pm_runtime_set_active(&pdev->dev);
1014 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301015 /* Decrement the parent device's counter after probe.
1016 * As child is active, parent will not be put into
1017 * suspend mode.
1018 */
1019 if (pdev->dev.parent)
1020 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301021
1022 return 0;
1023
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301024unconfig_gpio:
1025 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301026deinit_vddcx:
1027 msm_hsic_init_vddcx(mehci, 0);
1028deinit_clocks:
1029 msm_hsic_init_clocks(mehci, 0);
1030unmap:
1031 iounmap(hcd->regs);
1032put_hcd:
1033 usb_put_hcd(hcd);
1034
1035 return ret;
1036}
1037
1038static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1039{
1040 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1041 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1042
Vamsi Krishna34f01582011-12-14 19:54:42 -08001043 if (mehci->peripheral_status_irq)
1044 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001045
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001046 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001047 if (mehci->wakeup_irq_enabled)
1048 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001049 free_irq(mehci->wakeup_irq, mehci);
1050 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001051
Hemant Kumare6275972012-02-29 20:06:21 -08001052 if (mehci->bus_perf_client)
1053 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1054
1055 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301056 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301057 pm_runtime_set_suspended(&pdev->dev);
1058
1059 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301060 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301061 msm_hsic_init_vddcx(mehci, 0);
1062
1063 msm_hsic_init_clocks(mehci, 0);
1064 wake_lock_destroy(&mehci->wlock);
1065 iounmap(hcd->regs);
1066 usb_put_hcd(hcd);
1067
1068 return 0;
1069}
1070
1071#ifdef CONFIG_PM_SLEEP
1072static int msm_hsic_pm_suspend(struct device *dev)
1073{
Jack Phambe05fbb2012-05-16 10:56:26 -07001074 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301075 struct usb_hcd *hcd = dev_get_drvdata(dev);
1076 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1077
1078 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1079
1080 if (device_may_wakeup(dev))
1081 enable_irq_wake(hcd->irq);
1082
Jack Phambe05fbb2012-05-16 10:56:26 -07001083 ret = msm_hsic_suspend(mehci);
1084
1085 if (ret && device_may_wakeup(dev))
1086 disable_irq_wake(hcd->irq);
1087
1088 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001089}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301090
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301091static int msm_hsic_pm_resume(struct device *dev)
1092{
1093 int ret;
1094 struct usb_hcd *hcd = dev_get_drvdata(dev);
1095 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1096
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301097 if (device_may_wakeup(dev))
1098 disable_irq_wake(hcd->irq);
1099
1100 ret = msm_hsic_resume(mehci);
1101 if (ret)
1102 return ret;
1103
1104 /* Bring the device to full powered state upon system resume */
1105 pm_runtime_disable(dev);
1106 pm_runtime_set_active(dev);
1107 pm_runtime_enable(dev);
1108
1109 return 0;
1110}
1111#endif
1112
1113#ifdef CONFIG_PM_RUNTIME
1114static int msm_hsic_runtime_idle(struct device *dev)
1115{
1116 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301117 return 0;
1118}
1119
1120static int msm_hsic_runtime_suspend(struct device *dev)
1121{
1122 struct usb_hcd *hcd = dev_get_drvdata(dev);
1123 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1124
1125 dev_dbg(dev, "EHCI runtime suspend\n");
1126 return msm_hsic_suspend(mehci);
1127}
1128
1129static int msm_hsic_runtime_resume(struct device *dev)
1130{
1131 struct usb_hcd *hcd = dev_get_drvdata(dev);
1132 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1133
1134 dev_dbg(dev, "EHCI runtime resume\n");
1135 return msm_hsic_resume(mehci);
1136}
1137#endif
1138
1139#ifdef CONFIG_PM
1140static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1141 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301142 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1143 msm_hsic_runtime_idle)
1144};
1145#endif
1146
1147static struct platform_driver ehci_msm_hsic_driver = {
1148 .probe = ehci_hsic_msm_probe,
1149 .remove = __devexit_p(ehci_hsic_msm_remove),
1150 .driver = {
1151 .name = "msm_hsic_host",
1152#ifdef CONFIG_PM
1153 .pm = &msm_hsic_dev_pm_ops,
1154#endif
1155 },
1156};