blob: 6bd0577ac59c0e6c5640cbd9646d392dd7e3e4cd [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>
Hemant Kumar45d211b2012-05-31 17:58:43 -070042#include <linux/cpu.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053043
44#define MSM_USB_BASE (hcd->regs)
45
46struct msm_hsic_hcd {
47 struct ehci_hcd ehci;
48 struct device *dev;
49 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080050 struct clk *core_clk;
51 struct clk *alt_core_clk;
52 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053053 struct clk *cal_clk;
54 struct regulator *hsic_vddcx;
55 bool async_int;
56 atomic_t in_lpm;
57 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080058 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080059 int wakeup_irq;
Hemant Kumar6fd65032012-05-23 13:02:24 -070060 int wakeup_gpio;
Jack Phamfe441ea2012-03-23 17:03:15 -070061 bool wakeup_irq_enabled;
Hemant Kumar6fd65032012-05-23 13:02:24 -070062 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080063 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070064 uint32_t wakeup_int_cnt;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053065};
66
Hemant Kumare6275972012-02-29 20:06:21 -080067static bool debug_bus_voting_enabled = true;
Hemant Kumar45d211b2012-05-31 17:58:43 -070068
69static unsigned int enable_dbg_log = 1;
70module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
71/*by default log ep0 and efs sync ep*/
72static unsigned int ep_addr_rxdbg_mask = 9;
73module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
74static unsigned int ep_addr_txdbg_mask = 9;
75module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
76
77/* Maximum debug message length */
78#define DBG_MSG_LEN 100UL
79
80/* Maximum number of messages */
81#define DBG_MAX_MSG 256UL
82
83#define TIME_BUF_LEN 20
84
85enum event_type {
86 EVENT_UNDEF = -1,
87 URB_SUBMIT,
88 URB_COMPLETE,
89 EVENT_NONE,
90};
91
92#define EVENT_STR_LEN 5
93
94static char *event_to_str(enum event_type e)
95{
96 switch (e) {
97 case URB_SUBMIT:
98 return "S";
99 case URB_COMPLETE:
100 return "C";
101 case EVENT_NONE:
102 return "NONE";
103 default:
104 return "UNDEF";
105 }
106}
107
108static enum event_type str_to_event(const char *name)
109{
110 if (!strncasecmp("S", name, EVENT_STR_LEN))
111 return URB_SUBMIT;
112 if (!strncasecmp("C", name, EVENT_STR_LEN))
113 return URB_COMPLETE;
114 if (!strncasecmp("", name, EVENT_STR_LEN))
115 return EVENT_NONE;
116
117 return EVENT_UNDEF;
118}
119
120/*log ep0 activity*/
121static struct {
122 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
123 unsigned idx; /* index */
124 rwlock_t lck; /* lock */
125} dbg_hsic_ctrl = {
126 .idx = 0,
127 .lck = __RW_LOCK_UNLOCKED(lck)
128};
129
130static struct {
131 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
132 unsigned idx; /* index */
133 rwlock_t lck; /* lock */
134} dbg_hsic_data = {
135 .idx = 0,
136 .lck = __RW_LOCK_UNLOCKED(lck)
137};
138
139/**
140 * dbg_inc: increments debug event index
141 * @idx: buffer index
142 */
143static void dbg_inc(unsigned *idx)
144{
145 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
146}
147
148/*get_timestamp - returns time of day in us */
149static char *get_timestamp(char *tbuf)
150{
151 unsigned long long t;
152 unsigned long nanosec_rem;
153
154 t = cpu_clock(smp_processor_id());
155 nanosec_rem = do_div(t, 1000000000)/1000;
156 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
157 nanosec_rem);
158 return tbuf;
159}
160
161static int allow_dbg_log(int ep_addr)
162{
163 int dir, num;
164
165 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
166 num = ep_addr & ~USB_DIR_IN;
167 num = 1 << num;
168
169 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
170 return 1;
171 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
172 return 1;
173
174 return 0;
175}
176
177static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
178{
179 unsigned long flags;
180 int ep_addr;
181 char tbuf[TIME_BUF_LEN];
182
183 if (!enable_dbg_log)
184 return;
185
186 if (!urb) {
187 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
188 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
189 "%s: %s : %u\n", get_timestamp(tbuf), event, extra);
190 dbg_inc(&dbg_hsic_ctrl.idx);
191 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
192 return;
193 }
194
195 ep_addr = urb->ep->desc.bEndpointAddress;
196 if (!allow_dbg_log(ep_addr))
197 return;
198
199 if ((ep_addr & 0x0f) == 0x0) {
200 /*submit event*/
201 if (!str_to_event(event)) {
202 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
203 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
204 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
205 "%02x %02x %04x %04x %04x %u %d\n",
206 get_timestamp(tbuf), event, urb,
207 (ep_addr & USB_DIR_IN) ? "in" : "out",
208 urb->setup_packet[0], urb->setup_packet[1],
209 (urb->setup_packet[3] << 8) |
210 urb->setup_packet[2],
211 (urb->setup_packet[5] << 8) |
212 urb->setup_packet[4],
213 (urb->setup_packet[7] << 8) |
214 urb->setup_packet[6],
215 urb->transfer_buffer_length, urb->status);
216
217 dbg_inc(&dbg_hsic_ctrl.idx);
218 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
219 } else {
220 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
221 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
222 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d\n",
223 get_timestamp(tbuf), event, urb,
224 (ep_addr & USB_DIR_IN) ? "in" : "out",
225 urb->actual_length, extra);
226
227 dbg_inc(&dbg_hsic_ctrl.idx);
228 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
229 }
230 } else {
231 write_lock_irqsave(&dbg_hsic_data.lck, flags);
232 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
233 "%s: [%s : %p]:ep%d[%s] %u %d\n",
234 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
235 (ep_addr & USB_DIR_IN) ? "in" : "out",
236 str_to_event(event) ? urb->actual_length :
237 urb->transfer_buffer_length,
238 str_to_event(event) ? extra : urb->status);
239
240 dbg_inc(&dbg_hsic_data.idx);
241 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
242 }
243}
244
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530245static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
246{
247 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
248}
249
250static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
251{
252 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
253}
254
255#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
256
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700257#define USB_PHY_VDD_DIG_VOL_SUSP_MIN 500000 /* uV */
258#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
259#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
260#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530261
Lena Salman8c8ba382012-02-14 15:59:31 +0200262#define HSIC_DBG1_REG 0x38
263
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530264static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
265{
266 int ret = 0;
267
268 if (!init)
269 goto disable_reg;
270
Mayank Rana189ac052012-03-24 04:35:02 +0530271 mehci->hsic_vddcx = devm_regulator_get(mehci->dev, "HSIC_VDDCX");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530272 if (IS_ERR(mehci->hsic_vddcx)) {
273 dev_err(mehci->dev, "unable to get hsic vddcx\n");
274 return PTR_ERR(mehci->hsic_vddcx);
275 }
276
277 ret = regulator_set_voltage(mehci->hsic_vddcx,
278 USB_PHY_VDD_DIG_VOL_MIN,
279 USB_PHY_VDD_DIG_VOL_MAX);
280 if (ret) {
281 dev_err(mehci->dev, "unable to set the voltage"
282 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530283 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530284 }
285
286 ret = regulator_set_optimum_mode(mehci->hsic_vddcx,
287 USB_PHY_VDD_DIG_LOAD);
288 if (ret < 0) {
289 pr_err("%s: Unable to set optimum mode of the regulator:"
290 "VDDCX\n", __func__);
291 goto reg_optimum_mode_err;
292 }
293
294 ret = regulator_enable(mehci->hsic_vddcx);
295 if (ret) {
296 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
297 goto reg_enable_err;
298 }
299
300 return 0;
301
302disable_reg:
303 regulator_disable(mehci->hsic_vddcx);
304reg_enable_err:
305 regulator_set_optimum_mode(mehci->hsic_vddcx, 0);
306reg_optimum_mode_err:
307 regulator_set_voltage(mehci->hsic_vddcx, 0,
308 USB_PHY_VDD_DIG_VOL_MIN);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530309 return ret;
310
311}
312
313static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
314{
315 struct usb_hcd *hcd = hsic_to_hcd(mehci);
316 int cnt = 0;
317
318 /* initiate write operation */
319 writel_relaxed(ULPI_RUN | ULPI_WRITE |
320 ULPI_ADDR(reg) | ULPI_DATA(val),
321 USB_ULPI_VIEWPORT);
322
323 /* wait for completion */
324 while (cnt < ULPI_IO_TIMEOUT_USEC) {
325 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
326 break;
327 udelay(1);
328 cnt++;
329 }
330
331 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
332 dev_err(mehci->dev, "ulpi_write: timeout\n");
333 return -ETIMEDOUT;
334 }
335
336 return 0;
337}
338
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530339static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
340{
341 int rc = 0;
342 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800343 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530344
345 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800346
Lena Salman8c8ba382012-02-14 15:59:31 +0200347 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530348 return rc;
349
Vamsi Krishna34f01582011-12-14 19:54:42 -0800350 if (gpio_status == gpio_en)
351 return 0;
352
353 gpio_status = gpio_en;
354
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530355 if (!gpio_en)
356 goto free_gpio;
357
358 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
359 if (rc < 0) {
360 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
361 return rc;
362 }
363
364 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
365 if (rc < 0) {
366 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
367 goto free_strobe;
368 }
369
Hemant Kumar6fd65032012-05-23 13:02:24 -0700370 if (mehci->wakeup_gpio) {
371 rc = gpio_request(mehci->wakeup_gpio, "HSIC_WAKEUP_GPIO");
372 if (rc < 0) {
373 dev_err(mehci->dev, "gpio request failed for HSIC WAKEUP\n");
374 goto free_data;
375 }
376 }
377
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530378 return 0;
379
380free_gpio:
Hemant Kumar6fd65032012-05-23 13:02:24 -0700381 if (mehci->wakeup_gpio)
382 gpio_free(mehci->wakeup_gpio);
383free_data:
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530384 gpio_free(pdata->data);
385free_strobe:
386 gpio_free(pdata->strobe);
387
388 return rc;
389}
390
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530391static int msm_hsic_phy_clk_reset(struct msm_hsic_hcd *mehci)
392{
393 int ret;
394
Manu Gautam28b1bac2012-01-30 16:43:06 +0530395 clk_prepare_enable(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530396
Manu Gautam5143b252012-01-05 19:25:23 -0800397 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530398 if (ret) {
Manu Gautam28b1bac2012-01-30 16:43:06 +0530399 clk_disable_unprepare(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530400 dev_err(mehci->dev, "usb phy clk assert failed\n");
401 return ret;
402 }
403 usleep_range(10000, 12000);
Manu Gautam28b1bac2012-01-30 16:43:06 +0530404 clk_disable_unprepare(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530405
Manu Gautam5143b252012-01-05 19:25:23 -0800406 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530407 if (ret)
408 dev_err(mehci->dev, "usb phy clk deassert failed\n");
409
410 return ret;
411}
412
413static int msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
414{
415 struct usb_hcd *hcd = hsic_to_hcd(mehci);
416 u32 val;
417 int ret;
418
419 ret = msm_hsic_phy_clk_reset(mehci);
420 if (ret)
421 return ret;
422
423 val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
424 writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);
425
426 /* Ensure that RESET operation is completed before turning off clock */
427 mb();
428 dev_dbg(mehci->dev, "phy_reset: success\n");
429
430 return 0;
431}
432
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530433#define HSIC_GPIO150_PAD_CTL (MSM_TLMM_BASE+0x20C0)
434#define HSIC_GPIO151_PAD_CTL (MSM_TLMM_BASE+0x20C4)
435#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
436#define HSIC_LV_MODE 0x04
437#define HSIC_PAD_CALIBRATION 0xA8
438#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530439#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
440static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
441{
442 struct usb_hcd *hcd = hsic_to_hcd(mehci);
443 int cnt = 0;
444 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200445 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530446
447 ret = msm_hsic_phy_reset(mehci);
448 if (ret) {
449 dev_err(mehci->dev, "phy_reset failed\n");
450 return ret;
451 }
452
453 writel_relaxed(USBCMD_RESET, USB_USBCMD);
454 while (cnt < LINK_RESET_TIMEOUT_USEC) {
455 if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
456 break;
457 udelay(1);
458 cnt++;
459 }
460 if (cnt >= LINK_RESET_TIMEOUT_USEC)
461 return -ETIMEDOUT;
462
Lena Salman8c8ba382012-02-14 15:59:31 +0200463 /* Reset PORTSC and select ULPI phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530464 writel_relaxed(0x80000000, USB_PORTSC);
465
466 /* TODO: Need to confirm if HSIC PHY also requires delay after RESET */
467 msleep(100);
468
469 /* HSIC PHY Initialization */
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530470
Lena Salman8c8ba382012-02-14 15:59:31 +0200471 /* HSIC init sequence when HSIC signals (Strobe/Data) are
472 routed via GPIOs */
473 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530474
Lena Salman8c8ba382012-02-14 15:59:31 +0200475 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
476 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530477
Lena Salman8c8ba382012-02-14 15:59:31 +0200478 /*set periodic calibration interval to ~2.048sec in
479 HSIC_IO_CAL_REG */
480 ulpi_write(mehci, 0xFF, 0x33);
481
482 /* Enable periodic IO calibration in HSIC_CFG register */
483 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
484
485 /* Configure GPIO 150/151 pins for HSIC functionality mode */
486 ret = msm_hsic_config_gpios(mehci, 1);
487 if (ret) {
488 dev_err(mehci->dev, " gpio configuarion failed\n");
489 return ret;
490 }
491 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL
492 register */
493 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
494 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
495 /* Enable HSIC mode in HSIC_CFG register */
496 ulpi_write(mehci, 0x01, 0x31);
497 } else {
498 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
499 via dedicated I/O */
500
501 /* programmable length of connect signaling (33.2ns) */
502 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
503 if (ret) {
504 pr_err("%s: Unable to program length of connect "
505 "signaling\n", __func__);
506 }
507
508 /*set periodic calibration interval to ~2.048sec in
509 HSIC_IO_CAL_REG */
510 ulpi_write(mehci, 0xFF, 0x33);
511
512 /* Enable HSIC mode in HSIC_CFG register */
513 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530514 }
515
Hemant Kumar6fd65032012-05-23 13:02:24 -0700516 /*disable auto resume*/
517 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
518
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530519 return 0;
520}
521
522#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
523#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
524
525#ifdef CONFIG_PM_SLEEP
526static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
527{
528 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530529 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530530 u32 val;
531
532 if (atomic_read(&mehci->in_lpm)) {
533 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
534 return 0;
535 }
536
Hemant Kumar7f374632012-05-31 20:10:32 -0700537 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
538 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
539 __func__);
540 return -EAGAIN;
541 }
542
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530543 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700544
545 /* make sure we don't race against a remote wakeup */
546 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
547 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
548 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
549 enable_irq(hcd->irq);
550 return -EBUSY;
551 }
552
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530553 /*
554 * PHY may take some time or even fail to enter into low power
555 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
556 * in failure case.
557 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700558 val = readl_relaxed(USB_PORTSC);
559 val &= ~PORT_RWC_BITS;
560 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530561 writel_relaxed(val, USB_PORTSC);
562 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
563 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
564 break;
565 udelay(1);
566 cnt++;
567 }
568
569 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
570 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530571 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530572 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530573 }
574
575 /*
576 * PHY has capability to generate interrupt asynchronously in low
577 * power mode (LPM). This interrupt is level triggered. So USB IRQ
578 * line must be disabled till async interrupt enable bit is cleared
579 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
580 * block data communication from PHY.
581 */
582 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
583 ULPI_STP_CTRL, USB_USBCMD);
584
585 /*
586 * Ensure that hardware is put in low power mode before
587 * clocks are turned OFF and VDD is allowed to minimize.
588 */
589 mb();
590
Manu Gautam28b1bac2012-01-30 16:43:06 +0530591 clk_disable_unprepare(mehci->core_clk);
592 clk_disable_unprepare(mehci->phy_clk);
593 clk_disable_unprepare(mehci->cal_clk);
594 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530595
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700596 ret = regulator_set_voltage(mehci->hsic_vddcx,
597 USB_PHY_VDD_DIG_VOL_SUSP_MIN,
598 USB_PHY_VDD_DIG_VOL_MAX);
599 if (ret < 0)
600 dev_err(mehci->dev, "unable to set vddcx voltage: min:0.5v max:1.3v\n");
601
Hemant Kumare6275972012-02-29 20:06:21 -0800602 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
603 ret = msm_bus_scale_client_update_request(
604 mehci->bus_perf_client, 0);
605 if (ret)
606 dev_err(mehci->dev, "%s: Failed to dvote for "
607 "bus bandwidth %d\n", __func__, ret);
608 }
609
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530610 atomic_set(&mehci->in_lpm, 1);
611 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700612
613 mehci->wakeup_irq_enabled = 1;
614 enable_irq_wake(mehci->wakeup_irq);
615 enable_irq(mehci->wakeup_irq);
616
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530617 wake_unlock(&mehci->wlock);
618
619 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
620
621 return 0;
622}
623
624static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
625{
626 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530627 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530628 unsigned temp;
629
630 if (!atomic_read(&mehci->in_lpm)) {
631 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
632 return 0;
633 }
634
Hemant Kumar6fd65032012-05-23 13:02:24 -0700635 if (mehci->wakeup_irq_enabled) {
636 disable_irq_wake(mehci->wakeup_irq);
637 disable_irq_nosync(mehci->wakeup_irq);
638 mehci->wakeup_irq_enabled = 0;
639 }
640
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530641 wake_lock(&mehci->wlock);
642
Hemant Kumare6275972012-02-29 20:06:21 -0800643 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
644 ret = msm_bus_scale_client_update_request(
645 mehci->bus_perf_client, 1);
646 if (ret)
647 dev_err(mehci->dev, "%s: Failed to vote for "
648 "bus bandwidth %d\n", __func__, ret);
649 }
650
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700651 ret = regulator_set_voltage(mehci->hsic_vddcx,
652 USB_PHY_VDD_DIG_VOL_MIN,
653 USB_PHY_VDD_DIG_VOL_MAX);
654 if (ret < 0)
655 dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
656
Manu Gautam28b1bac2012-01-30 16:43:06 +0530657 clk_prepare_enable(mehci->core_clk);
658 clk_prepare_enable(mehci->phy_clk);
659 clk_prepare_enable(mehci->cal_clk);
660 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530661
662 temp = readl_relaxed(USB_USBCMD);
663 temp &= ~ASYNC_INTR_CTRL;
664 temp &= ~ULPI_STP_CTRL;
665 writel_relaxed(temp, USB_USBCMD);
666
667 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
668 goto skip_phy_resume;
669
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700670 temp = readl_relaxed(USB_PORTSC);
671 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530672 writel_relaxed(temp, USB_PORTSC);
673 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
674 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
675 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
676 break;
677 udelay(1);
678 cnt++;
679 }
680
681 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
682 /*
683 * This is a fatal error. Reset the link and
684 * PHY to make hsic working.
685 */
686 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530687 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530688 msm_hsic_reset(mehci);
689 }
690
691skip_phy_resume:
692
Hemant Kumar6fd65032012-05-23 13:02:24 -0700693 usb_hcd_resume_root_hub(hcd);
694
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530695 atomic_set(&mehci->in_lpm, 0);
696
697 if (mehci->async_int) {
698 mehci->async_int = false;
699 pm_runtime_put_noidle(mehci->dev);
700 enable_irq(hcd->irq);
701 }
702
Hemant Kumar6fd65032012-05-23 13:02:24 -0700703 if (atomic_read(&mehci->pm_usage_cnt)) {
704 atomic_set(&mehci->pm_usage_cnt, 0);
705 pm_runtime_put_noidle(mehci->dev);
706 }
707
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530708 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
709
710 return 0;
711}
712#endif
713
714static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
715{
716 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
717
718 if (atomic_read(&mehci->in_lpm)) {
719 disable_irq_nosync(hcd->irq);
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700720 dev_dbg(mehci->dev, "phy async intr\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530721 mehci->async_int = true;
722 pm_runtime_get(mehci->dev);
723 return IRQ_HANDLED;
724 }
725
726 return ehci_irq(hcd);
727}
728
729static int ehci_hsic_reset(struct usb_hcd *hcd)
730{
731 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
732 int retval;
733
734 ehci->caps = USB_CAPLENGTH;
735 ehci->regs = USB_CAPLENGTH +
736 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
737 dbg_hcs_params(ehci, "reset");
738 dbg_hcc_params(ehci, "reset");
739
740 /* cache the data to minimize the chip reads*/
741 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
742
743 hcd->has_tt = 1;
744 ehci->sbrn = HCD_USB2;
745
746 retval = ehci_halt(ehci);
747 if (retval)
748 return retval;
749
750 /* data structure init */
751 retval = ehci_init(hcd);
752 if (retval)
753 return retval;
754
755 retval = ehci_reset(ehci);
756 if (retval)
757 return retval;
758
759 /* bursts of unspecified length. */
760 writel_relaxed(0, USB_AHBBURST);
761 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530762 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530763 /* Disable streaming mode and select host mode */
764 writel_relaxed(0x13, USB_USBMODE);
765
766 ehci_port_power(ehci, 1);
767 return 0;
768}
769
Hemant Kumar45d211b2012-05-31 17:58:43 -0700770static int ehci_hsic_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
771 gfp_t mem_flags)
772{
773 dbg_log_event(urb, event_to_str(URB_SUBMIT), 0);
774 return ehci_urb_enqueue(hcd, urb, mem_flags);
775}
776
777static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
778{
779 dbg_log_event(NULL, "Suspend RH", 0);
780 return ehci_bus_suspend(hcd);
781}
782
783static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
784{
785 dbg_log_event(NULL, "Resume RH", 0);
786 return ehci_bus_resume(hcd);
787}
788
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530789static struct hc_driver msm_hsic_driver = {
790 .description = hcd_name,
791 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
792 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
793
794 /*
795 * generic hardware linkage
796 */
797 .irq = msm_hsic_irq,
798 .flags = HCD_USB2 | HCD_MEMORY,
799
800 .reset = ehci_hsic_reset,
801 .start = ehci_run,
802
803 .stop = ehci_stop,
804 .shutdown = ehci_shutdown,
805
806 /*
807 * managing i/o requests and associated device resources
808 */
Hemant Kumar45d211b2012-05-31 17:58:43 -0700809 .urb_enqueue = ehci_hsic_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530810 .urb_dequeue = ehci_urb_dequeue,
811 .endpoint_disable = ehci_endpoint_disable,
812 .endpoint_reset = ehci_endpoint_reset,
813 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
814
815 /*
816 * scheduling support
817 */
818 .get_frame_number = ehci_get_frame,
819
820 /*
821 * root hub support
822 */
823 .hub_status_data = ehci_hub_status_data,
824 .hub_control = ehci_hub_control,
825 .relinquish_port = ehci_relinquish_port,
826 .port_handed_over = ehci_port_handed_over,
827
828 /*
829 * PM support
830 */
Hemant Kumar45d211b2012-05-31 17:58:43 -0700831 .bus_suspend = ehci_hsic_bus_suspend,
832 .bus_resume = ehci_hsic_bus_resume,
833
834 .log_urb_complete = dbg_log_event,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530835};
836
837static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
838{
839 int ret = 0;
840
841 if (!init)
842 goto put_clocks;
843
Lena Salman8c8ba382012-02-14 15:59:31 +0200844 /*core_clk is required for LINK protocol engine
845 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800846 mehci->core_clk = clk_get(mehci->dev, "core_clk");
847 if (IS_ERR(mehci->core_clk)) {
848 dev_err(mehci->dev, "failed to get core_clk\n");
849 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530850 return ret;
851 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530852
Lena Salman8c8ba382012-02-14 15:59:31 +0200853 /* alt_core_clk is for LINK to be used during PHY RESET
854 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800855 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
856 if (IS_ERR(mehci->alt_core_clk)) {
857 dev_err(mehci->dev, "failed to core_clk\n");
858 ret = PTR_ERR(mehci->alt_core_clk);
859 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530860 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530861
Lena Salman8c8ba382012-02-14 15:59:31 +0200862 /* phy_clk is required for HSIC PHY operation
863 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800864 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
865 if (IS_ERR(mehci->phy_clk)) {
866 dev_err(mehci->dev, "failed to get phy_clk\n");
867 ret = PTR_ERR(mehci->phy_clk);
868 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530869 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530870
871 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -0800872 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530873 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800874 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530875 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800876 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530877 }
878 clk_set_rate(mehci->cal_clk, 10000000);
879
880 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -0800881 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530882 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800883 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530884 ret = PTR_ERR(mehci->ahb_clk);
885 goto put_cal_clk;
886 }
887
Manu Gautam28b1bac2012-01-30 16:43:06 +0530888 clk_prepare_enable(mehci->core_clk);
889 clk_prepare_enable(mehci->phy_clk);
890 clk_prepare_enable(mehci->cal_clk);
891 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530892
893 return 0;
894
895put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -0800896 if (!atomic_read(&mehci->in_lpm)) {
897 clk_disable_unprepare(mehci->core_clk);
898 clk_disable_unprepare(mehci->phy_clk);
899 clk_disable_unprepare(mehci->cal_clk);
900 clk_disable_unprepare(mehci->ahb_clk);
901 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530902 clk_put(mehci->ahb_clk);
903put_cal_clk:
904 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800905put_phy_clk:
906 clk_put(mehci->phy_clk);
907put_alt_core_clk:
908 clk_put(mehci->alt_core_clk);
909put_core_clk:
910 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530911
912 return ret;
913}
Vamsi Krishna34f01582011-12-14 19:54:42 -0800914static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
915{
916 struct msm_hsic_hcd *mehci = dev_id;
917
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800918 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -0800919
920 if (mehci)
921 msm_hsic_config_gpios(mehci, 0);
922
923 return IRQ_HANDLED;
924}
925
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800926static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
927{
928 struct msm_hsic_hcd *mehci = data;
929
Hemant Kumar6fd65032012-05-23 13:02:24 -0700930 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700931 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700932 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
933 __func__, mehci->wakeup_int_cnt);
934
935 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800936
Jack Phamfe441ea2012-03-23 17:03:15 -0700937 if (mehci->wakeup_irq_enabled) {
938 mehci->wakeup_irq_enabled = 0;
939 disable_irq_wake(irq);
940 disable_irq_nosync(irq);
941 }
942
Hemant Kumar6fd65032012-05-23 13:02:24 -0700943 if (!atomic_read(&mehci->pm_usage_cnt)) {
944 atomic_set(&mehci->pm_usage_cnt, 1);
945 pm_runtime_get(mehci->dev);
946 }
947
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800948 return IRQ_HANDLED;
949}
950
Hemant Kumare6275972012-02-29 20:06:21 -0800951static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
952{
953 if (debug_bus_voting_enabled)
954 seq_printf(s, "enabled\n");
955 else
956 seq_printf(s, "disabled\n");
957
958 return 0;
959}
960
961static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
962{
963 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
964}
965
966static ssize_t ehci_hsic_msm_bus_write(struct file *file,
967 const char __user *ubuf, size_t count, loff_t *ppos)
968{
969 char buf[8];
970 int ret;
971 struct seq_file *s = file->private_data;
972 struct msm_hsic_hcd *mehci = s->private;
973
974 memset(buf, 0x00, sizeof(buf));
975
976 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
977 return -EFAULT;
978
979 if (!strncmp(buf, "enable", 6)) {
980 /* Do not vote here. Let hsic driver decide when to vote */
981 debug_bus_voting_enabled = true;
982 } else {
983 debug_bus_voting_enabled = false;
984 if (mehci->bus_perf_client) {
985 ret = msm_bus_scale_client_update_request(
986 mehci->bus_perf_client, 0);
987 if (ret)
988 dev_err(mehci->dev, "%s: Failed to devote "
989 "for bus bw %d\n", __func__, ret);
990 }
991 }
992
993 return count;
994}
995
996const struct file_operations ehci_hsic_msm_bus_fops = {
997 .open = ehci_hsic_msm_bus_open,
998 .read = seq_read,
999 .write = ehci_hsic_msm_bus_write,
1000 .llseek = seq_lseek,
1001 .release = single_release,
1002};
1003
Hemant Kumar6fd65032012-05-23 13:02:24 -07001004static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1005{
1006 struct msm_hsic_hcd *mehci = s->private;
1007
1008 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1009
1010 return 0;
1011}
1012
1013static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1014{
1015 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1016}
1017
1018const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1019 .open = ehci_hsic_msm_wakeup_cnt_open,
1020 .read = seq_read,
1021 .llseek = seq_lseek,
1022 .release = single_release,
1023};
1024
Hemant Kumar45d211b2012-05-31 17:58:43 -07001025static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1026{
1027 unsigned long flags;
1028 unsigned i;
1029
1030 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1031
1032 i = dbg_hsic_data.idx;
1033 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1034 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1035 continue;
1036 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1037 }
1038
1039 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1040
1041 return 0;
1042}
1043
1044static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1045{
1046 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1047}
1048
1049const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1050 .open = ehci_hsic_msm_data_events_open,
1051 .read = seq_read,
1052 .llseek = seq_lseek,
1053 .release = single_release,
1054};
1055
1056static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1057{
1058 unsigned long flags;
1059 unsigned i;
1060
1061 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1062
1063 i = dbg_hsic_ctrl.idx;
1064 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1065 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1066 continue;
1067 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1068 }
1069
1070 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1071
1072 return 0;
1073}
1074
1075static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1076{
1077 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1078}
1079
1080const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1081 .open = ehci_hsic_msm_ctrl_events_open,
1082 .read = seq_read,
1083 .llseek = seq_lseek,
1084 .release = single_release,
1085};
1086
Hemant Kumare6275972012-02-29 20:06:21 -08001087static struct dentry *ehci_hsic_msm_dbg_root;
1088static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1089{
1090 struct dentry *ehci_hsic_msm_dentry;
1091
1092 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1093
1094 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1095 return -ENODEV;
1096
1097 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1098 S_IRUGO | S_IWUSR,
1099 ehci_hsic_msm_dbg_root, mehci,
1100 &ehci_hsic_msm_bus_fops);
1101
1102 if (!ehci_hsic_msm_dentry) {
1103 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1104 return -ENODEV;
1105 }
1106
Hemant Kumar6fd65032012-05-23 13:02:24 -07001107 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1108 S_IRUGO,
1109 ehci_hsic_msm_dbg_root, mehci,
1110 &ehci_hsic_msm_wakeup_cnt_fops);
1111
1112 if (!ehci_hsic_msm_dentry) {
1113 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1114 return -ENODEV;
1115 }
1116
Hemant Kumar45d211b2012-05-31 17:58:43 -07001117 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1118 S_IRUGO,
1119 ehci_hsic_msm_dbg_root, mehci,
1120 &ehci_hsic_msm_dbg_ctrl_fops);
1121
1122 if (!ehci_hsic_msm_dentry) {
1123 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1124 return -ENODEV;
1125 }
1126
1127 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1128 S_IRUGO,
1129 ehci_hsic_msm_dbg_root, mehci,
1130 &ehci_hsic_msm_dbg_data_fops);
1131
1132 if (!ehci_hsic_msm_dentry) {
1133 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1134 return -ENODEV;
1135 }
1136
Hemant Kumare6275972012-02-29 20:06:21 -08001137 return 0;
1138}
1139
1140static void ehci_hsic_msm_debugfs_cleanup(void)
1141{
1142 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1143}
1144
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301145static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1146{
1147 struct usb_hcd *hcd;
1148 struct resource *res;
1149 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301150 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301151 int ret;
1152
1153 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1154
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301155 /* After parent device's probe is executed, it will be put in suspend
1156 * mode. When child device's probe is called, driver core is not
1157 * resuming parent device due to which parent will be in suspend even
1158 * though child is active. Hence resume the parent device explicitly.
1159 */
1160 if (pdev->dev.parent)
1161 pm_runtime_get_sync(pdev->dev.parent);
1162
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301163 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1164 dev_name(&pdev->dev));
1165 if (!hcd) {
1166 dev_err(&pdev->dev, "Unable to create HCD\n");
1167 return -ENOMEM;
1168 }
1169
1170 hcd->irq = platform_get_irq(pdev, 0);
1171 if (hcd->irq < 0) {
1172 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1173 ret = hcd->irq;
1174 goto put_hcd;
1175 }
1176
1177 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1178 if (!res) {
1179 dev_err(&pdev->dev, "Unable to get memory resource\n");
1180 ret = -ENODEV;
1181 goto put_hcd;
1182 }
1183
1184 hcd->rsrc_start = res->start;
1185 hcd->rsrc_len = resource_size(res);
1186 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1187 if (!hcd->regs) {
1188 dev_err(&pdev->dev, "ioremap failed\n");
1189 ret = -ENOMEM;
1190 goto put_hcd;
1191 }
1192
1193 mehci = hcd_to_hsic(hcd);
1194 mehci->dev = &pdev->dev;
1195
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001196 mehci->ehci.susp_sof_bug = 1;
1197
Hemant Kumar933e0402012-05-22 11:11:40 -07001198 mehci->ehci.max_log2_irq_thresh = 6;
1199
Vamsi Krishna34f01582011-12-14 19:54:42 -08001200 res = platform_get_resource_byname(pdev,
1201 IORESOURCE_IRQ,
1202 "peripheral_status_irq");
1203 if (res)
1204 mehci->peripheral_status_irq = res->start;
1205
Hemant Kumar6fd65032012-05-23 13:02:24 -07001206 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
1207 if (res) {
1208 mehci->wakeup_gpio = res->start;
1209 mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
1210 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1211 }
1212
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301213 ret = msm_hsic_init_clocks(mehci, 1);
1214 if (ret) {
1215 dev_err(&pdev->dev, "unable to initialize clocks\n");
1216 ret = -ENODEV;
1217 goto unmap;
1218 }
1219
1220 ret = msm_hsic_init_vddcx(mehci, 1);
1221 if (ret) {
1222 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1223 ret = -ENODEV;
1224 goto deinit_clocks;
1225 }
1226
1227 ret = msm_hsic_reset(mehci);
1228 if (ret) {
1229 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301230 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301231 }
1232
1233 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1234 if (ret) {
1235 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301236 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301237 }
1238
1239 device_init_wakeup(&pdev->dev, 1);
1240 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1241 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001242
1243 if (mehci->peripheral_status_irq) {
1244 ret = request_threaded_irq(mehci->peripheral_status_irq,
1245 NULL, hsic_peripheral_status_change,
1246 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1247 | IRQF_SHARED,
1248 "hsic_peripheral_status", mehci);
1249 if (ret)
1250 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1251 __func__, mehci->peripheral_status_irq, ret);
1252 }
1253
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001254 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001255 if (mehci->wakeup_irq) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001256 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001257 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001258 "msm_hsic_wakeup", mehci);
1259 if (!ret) {
1260 disable_irq_nosync(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001261 } else {
1262 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1263 mehci->wakeup_irq, ret);
1264 mehci->wakeup_irq = 0;
1265 }
1266 }
1267
Hemant Kumare6275972012-02-29 20:06:21 -08001268 ret = ehci_hsic_msm_debugfs_init(mehci);
1269 if (ret)
1270 dev_dbg(&pdev->dev, "mode debugfs file is"
1271 "not available\n");
1272
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301273 pdata = mehci->dev->platform_data;
Hemant Kumare6275972012-02-29 20:06:21 -08001274 if (pdata && pdata->bus_scale_table) {
1275 mehci->bus_perf_client =
1276 msm_bus_scale_register_client(pdata->bus_scale_table);
1277 /* Configure BUS performance parameters for MAX bandwidth */
1278 if (mehci->bus_perf_client) {
1279 ret = msm_bus_scale_client_update_request(
1280 mehci->bus_perf_client, 1);
1281 if (ret)
1282 dev_err(&pdev->dev, "%s: Failed to vote for "
1283 "bus bandwidth %d\n", __func__, ret);
1284 } else {
1285 dev_err(&pdev->dev, "%s: Failed to register BUS "
1286 "scaling client!!\n", __func__);
1287 }
1288 }
1289
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301290 /*
1291 * This pdev->dev is assigned parent of root-hub by USB core,
1292 * hence, runtime framework automatically calls this driver's
1293 * runtime APIs based on root-hub's state.
1294 */
1295 pm_runtime_set_active(&pdev->dev);
1296 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301297 /* Decrement the parent device's counter after probe.
1298 * As child is active, parent will not be put into
1299 * suspend mode.
1300 */
1301 if (pdev->dev.parent)
1302 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301303
1304 return 0;
1305
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301306unconfig_gpio:
1307 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301308deinit_vddcx:
1309 msm_hsic_init_vddcx(mehci, 0);
1310deinit_clocks:
1311 msm_hsic_init_clocks(mehci, 0);
1312unmap:
1313 iounmap(hcd->regs);
1314put_hcd:
1315 usb_put_hcd(hcd);
1316
1317 return ret;
1318}
1319
1320static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1321{
1322 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1323 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1324
Vamsi Krishna34f01582011-12-14 19:54:42 -08001325 if (mehci->peripheral_status_irq)
1326 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001327
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001328 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001329 if (mehci->wakeup_irq_enabled)
1330 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001331 free_irq(mehci->wakeup_irq, mehci);
1332 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001333
Hemant Kumare6275972012-02-29 20:06:21 -08001334 if (mehci->bus_perf_client)
1335 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1336
1337 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301338 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301339 pm_runtime_set_suspended(&pdev->dev);
1340
1341 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301342 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301343 msm_hsic_init_vddcx(mehci, 0);
1344
1345 msm_hsic_init_clocks(mehci, 0);
1346 wake_lock_destroy(&mehci->wlock);
1347 iounmap(hcd->regs);
1348 usb_put_hcd(hcd);
1349
1350 return 0;
1351}
1352
1353#ifdef CONFIG_PM_SLEEP
1354static int msm_hsic_pm_suspend(struct device *dev)
1355{
Jack Phambe05fbb2012-05-16 10:56:26 -07001356 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301357 struct usb_hcd *hcd = dev_get_drvdata(dev);
1358 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1359
1360 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1361
Hemant Kumar45d211b2012-05-31 17:58:43 -07001362 dbg_log_event(NULL, "PM Suspend", 0);
1363
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301364 if (device_may_wakeup(dev))
1365 enable_irq_wake(hcd->irq);
1366
Jack Phambe05fbb2012-05-16 10:56:26 -07001367 ret = msm_hsic_suspend(mehci);
1368
1369 if (ret && device_may_wakeup(dev))
1370 disable_irq_wake(hcd->irq);
1371
1372 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001373}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301374
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301375static int msm_hsic_pm_resume(struct device *dev)
1376{
1377 int ret;
1378 struct usb_hcd *hcd = dev_get_drvdata(dev);
1379 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1380
Hemant Kumar45d211b2012-05-31 17:58:43 -07001381 dbg_log_event(NULL, "PM Resume", 0);
1382
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301383 if (device_may_wakeup(dev))
1384 disable_irq_wake(hcd->irq);
1385
1386 ret = msm_hsic_resume(mehci);
1387 if (ret)
1388 return ret;
1389
1390 /* Bring the device to full powered state upon system resume */
1391 pm_runtime_disable(dev);
1392 pm_runtime_set_active(dev);
1393 pm_runtime_enable(dev);
1394
1395 return 0;
1396}
1397#endif
1398
1399#ifdef CONFIG_PM_RUNTIME
1400static int msm_hsic_runtime_idle(struct device *dev)
1401{
1402 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301403 return 0;
1404}
1405
1406static int msm_hsic_runtime_suspend(struct device *dev)
1407{
1408 struct usb_hcd *hcd = dev_get_drvdata(dev);
1409 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1410
1411 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001412
1413 dbg_log_event(NULL, "Run Time PM Suspend", 0);
1414
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301415 return msm_hsic_suspend(mehci);
1416}
1417
1418static int msm_hsic_runtime_resume(struct device *dev)
1419{
1420 struct usb_hcd *hcd = dev_get_drvdata(dev);
1421 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1422
1423 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001424
1425 dbg_log_event(NULL, "Run Time PM Resume", 0);
1426
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301427 return msm_hsic_resume(mehci);
1428}
1429#endif
1430
1431#ifdef CONFIG_PM
1432static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1433 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301434 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1435 msm_hsic_runtime_idle)
1436};
1437#endif
1438
1439static struct platform_driver ehci_msm_hsic_driver = {
1440 .probe = ehci_hsic_msm_probe,
1441 .remove = __devexit_p(ehci_hsic_msm_remove),
1442 .driver = {
1443 .name = "msm_hsic_host",
1444#ifdef CONFIG_PM
1445 .pm = &msm_hsic_dev_pm_ops,
1446#endif
1447 },
1448};