blob: 5ed16ccb0a45f3b6ec5df607f5726e7fd1184999 [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 Kumard4ee29f2012-06-06 11:47:50 -0700693 if (!(readl_relaxed(USB_USBCMD) & CMD_RUN) &&
694 (readl_relaxed(USB_PORTSC) & PORT_SUSPEND)) {
695 writel_relaxed(readl_relaxed(USB_USBCMD) | CMD_RUN ,
696 USB_USBCMD);
697 dbg_log_event(NULL, "Set RS", readl_relaxed(USB_USBCMD));
698 }
699
Hemant Kumar6fd65032012-05-23 13:02:24 -0700700 usb_hcd_resume_root_hub(hcd);
701
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530702 atomic_set(&mehci->in_lpm, 0);
703
704 if (mehci->async_int) {
705 mehci->async_int = false;
706 pm_runtime_put_noidle(mehci->dev);
707 enable_irq(hcd->irq);
708 }
709
Hemant Kumar6fd65032012-05-23 13:02:24 -0700710 if (atomic_read(&mehci->pm_usage_cnt)) {
711 atomic_set(&mehci->pm_usage_cnt, 0);
712 pm_runtime_put_noidle(mehci->dev);
713 }
714
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530715 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
716
717 return 0;
718}
719#endif
720
721static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
722{
723 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
724
725 if (atomic_read(&mehci->in_lpm)) {
726 disable_irq_nosync(hcd->irq);
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700727 dev_dbg(mehci->dev, "phy async intr\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530728 mehci->async_int = true;
729 pm_runtime_get(mehci->dev);
730 return IRQ_HANDLED;
731 }
732
733 return ehci_irq(hcd);
734}
735
736static int ehci_hsic_reset(struct usb_hcd *hcd)
737{
738 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
739 int retval;
740
741 ehci->caps = USB_CAPLENGTH;
742 ehci->regs = USB_CAPLENGTH +
743 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
744 dbg_hcs_params(ehci, "reset");
745 dbg_hcc_params(ehci, "reset");
746
747 /* cache the data to minimize the chip reads*/
748 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
749
750 hcd->has_tt = 1;
751 ehci->sbrn = HCD_USB2;
752
753 retval = ehci_halt(ehci);
754 if (retval)
755 return retval;
756
757 /* data structure init */
758 retval = ehci_init(hcd);
759 if (retval)
760 return retval;
761
762 retval = ehci_reset(ehci);
763 if (retval)
764 return retval;
765
766 /* bursts of unspecified length. */
767 writel_relaxed(0, USB_AHBBURST);
768 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530769 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530770 /* Disable streaming mode and select host mode */
771 writel_relaxed(0x13, USB_USBMODE);
772
773 ehci_port_power(ehci, 1);
774 return 0;
775}
776
Hemant Kumar45d211b2012-05-31 17:58:43 -0700777static int ehci_hsic_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
778 gfp_t mem_flags)
779{
780 dbg_log_event(urb, event_to_str(URB_SUBMIT), 0);
781 return ehci_urb_enqueue(hcd, urb, mem_flags);
782}
783
784static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
785{
786 dbg_log_event(NULL, "Suspend RH", 0);
787 return ehci_bus_suspend(hcd);
788}
789
790static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
791{
792 dbg_log_event(NULL, "Resume RH", 0);
793 return ehci_bus_resume(hcd);
794}
795
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530796static struct hc_driver msm_hsic_driver = {
797 .description = hcd_name,
798 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
799 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
800
801 /*
802 * generic hardware linkage
803 */
804 .irq = msm_hsic_irq,
805 .flags = HCD_USB2 | HCD_MEMORY,
806
807 .reset = ehci_hsic_reset,
808 .start = ehci_run,
809
810 .stop = ehci_stop,
811 .shutdown = ehci_shutdown,
812
813 /*
814 * managing i/o requests and associated device resources
815 */
Hemant Kumar45d211b2012-05-31 17:58:43 -0700816 .urb_enqueue = ehci_hsic_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530817 .urb_dequeue = ehci_urb_dequeue,
818 .endpoint_disable = ehci_endpoint_disable,
819 .endpoint_reset = ehci_endpoint_reset,
820 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
821
822 /*
823 * scheduling support
824 */
825 .get_frame_number = ehci_get_frame,
826
827 /*
828 * root hub support
829 */
830 .hub_status_data = ehci_hub_status_data,
831 .hub_control = ehci_hub_control,
832 .relinquish_port = ehci_relinquish_port,
833 .port_handed_over = ehci_port_handed_over,
834
835 /*
836 * PM support
837 */
Hemant Kumar45d211b2012-05-31 17:58:43 -0700838 .bus_suspend = ehci_hsic_bus_suspend,
839 .bus_resume = ehci_hsic_bus_resume,
840
841 .log_urb_complete = dbg_log_event,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530842};
843
844static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
845{
846 int ret = 0;
847
848 if (!init)
849 goto put_clocks;
850
Lena Salman8c8ba382012-02-14 15:59:31 +0200851 /*core_clk is required for LINK protocol engine
852 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800853 mehci->core_clk = clk_get(mehci->dev, "core_clk");
854 if (IS_ERR(mehci->core_clk)) {
855 dev_err(mehci->dev, "failed to get core_clk\n");
856 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530857 return ret;
858 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530859
Lena Salman8c8ba382012-02-14 15:59:31 +0200860 /* alt_core_clk is for LINK to be used during PHY RESET
861 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800862 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
863 if (IS_ERR(mehci->alt_core_clk)) {
864 dev_err(mehci->dev, "failed to core_clk\n");
865 ret = PTR_ERR(mehci->alt_core_clk);
866 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530867 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530868
Lena Salman8c8ba382012-02-14 15:59:31 +0200869 /* phy_clk is required for HSIC PHY operation
870 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800871 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
872 if (IS_ERR(mehci->phy_clk)) {
873 dev_err(mehci->dev, "failed to get phy_clk\n");
874 ret = PTR_ERR(mehci->phy_clk);
875 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530876 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530877
878 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -0800879 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530880 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800881 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530882 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800883 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530884 }
885 clk_set_rate(mehci->cal_clk, 10000000);
886
887 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -0800888 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530889 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800890 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530891 ret = PTR_ERR(mehci->ahb_clk);
892 goto put_cal_clk;
893 }
894
Manu Gautam28b1bac2012-01-30 16:43:06 +0530895 clk_prepare_enable(mehci->core_clk);
896 clk_prepare_enable(mehci->phy_clk);
897 clk_prepare_enable(mehci->cal_clk);
898 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530899
900 return 0;
901
902put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -0800903 if (!atomic_read(&mehci->in_lpm)) {
904 clk_disable_unprepare(mehci->core_clk);
905 clk_disable_unprepare(mehci->phy_clk);
906 clk_disable_unprepare(mehci->cal_clk);
907 clk_disable_unprepare(mehci->ahb_clk);
908 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530909 clk_put(mehci->ahb_clk);
910put_cal_clk:
911 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800912put_phy_clk:
913 clk_put(mehci->phy_clk);
914put_alt_core_clk:
915 clk_put(mehci->alt_core_clk);
916put_core_clk:
917 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530918
919 return ret;
920}
Vamsi Krishna34f01582011-12-14 19:54:42 -0800921static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
922{
923 struct msm_hsic_hcd *mehci = dev_id;
924
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800925 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -0800926
927 if (mehci)
928 msm_hsic_config_gpios(mehci, 0);
929
930 return IRQ_HANDLED;
931}
932
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800933static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
934{
935 struct msm_hsic_hcd *mehci = data;
936
Hemant Kumar6fd65032012-05-23 13:02:24 -0700937 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700938 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700939 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
940 __func__, mehci->wakeup_int_cnt);
941
942 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800943
Jack Phamfe441ea2012-03-23 17:03:15 -0700944 if (mehci->wakeup_irq_enabled) {
945 mehci->wakeup_irq_enabled = 0;
946 disable_irq_wake(irq);
947 disable_irq_nosync(irq);
948 }
949
Hemant Kumar6fd65032012-05-23 13:02:24 -0700950 if (!atomic_read(&mehci->pm_usage_cnt)) {
951 atomic_set(&mehci->pm_usage_cnt, 1);
952 pm_runtime_get(mehci->dev);
953 }
954
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800955 return IRQ_HANDLED;
956}
957
Hemant Kumare6275972012-02-29 20:06:21 -0800958static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
959{
960 if (debug_bus_voting_enabled)
961 seq_printf(s, "enabled\n");
962 else
963 seq_printf(s, "disabled\n");
964
965 return 0;
966}
967
968static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
969{
970 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
971}
972
973static ssize_t ehci_hsic_msm_bus_write(struct file *file,
974 const char __user *ubuf, size_t count, loff_t *ppos)
975{
976 char buf[8];
977 int ret;
978 struct seq_file *s = file->private_data;
979 struct msm_hsic_hcd *mehci = s->private;
980
981 memset(buf, 0x00, sizeof(buf));
982
983 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
984 return -EFAULT;
985
986 if (!strncmp(buf, "enable", 6)) {
987 /* Do not vote here. Let hsic driver decide when to vote */
988 debug_bus_voting_enabled = true;
989 } else {
990 debug_bus_voting_enabled = false;
991 if (mehci->bus_perf_client) {
992 ret = msm_bus_scale_client_update_request(
993 mehci->bus_perf_client, 0);
994 if (ret)
995 dev_err(mehci->dev, "%s: Failed to devote "
996 "for bus bw %d\n", __func__, ret);
997 }
998 }
999
1000 return count;
1001}
1002
1003const struct file_operations ehci_hsic_msm_bus_fops = {
1004 .open = ehci_hsic_msm_bus_open,
1005 .read = seq_read,
1006 .write = ehci_hsic_msm_bus_write,
1007 .llseek = seq_lseek,
1008 .release = single_release,
1009};
1010
Hemant Kumar6fd65032012-05-23 13:02:24 -07001011static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1012{
1013 struct msm_hsic_hcd *mehci = s->private;
1014
1015 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1016
1017 return 0;
1018}
1019
1020static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1021{
1022 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1023}
1024
1025const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1026 .open = ehci_hsic_msm_wakeup_cnt_open,
1027 .read = seq_read,
1028 .llseek = seq_lseek,
1029 .release = single_release,
1030};
1031
Hemant Kumar45d211b2012-05-31 17:58:43 -07001032static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1033{
1034 unsigned long flags;
1035 unsigned i;
1036
1037 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1038
1039 i = dbg_hsic_data.idx;
1040 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1041 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1042 continue;
1043 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1044 }
1045
1046 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1047
1048 return 0;
1049}
1050
1051static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1052{
1053 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1054}
1055
1056const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1057 .open = ehci_hsic_msm_data_events_open,
1058 .read = seq_read,
1059 .llseek = seq_lseek,
1060 .release = single_release,
1061};
1062
1063static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1064{
1065 unsigned long flags;
1066 unsigned i;
1067
1068 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1069
1070 i = dbg_hsic_ctrl.idx;
1071 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1072 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1073 continue;
1074 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1075 }
1076
1077 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1078
1079 return 0;
1080}
1081
1082static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1083{
1084 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1085}
1086
1087const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1088 .open = ehci_hsic_msm_ctrl_events_open,
1089 .read = seq_read,
1090 .llseek = seq_lseek,
1091 .release = single_release,
1092};
1093
Hemant Kumare6275972012-02-29 20:06:21 -08001094static struct dentry *ehci_hsic_msm_dbg_root;
1095static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1096{
1097 struct dentry *ehci_hsic_msm_dentry;
1098
1099 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1100
1101 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1102 return -ENODEV;
1103
1104 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1105 S_IRUGO | S_IWUSR,
1106 ehci_hsic_msm_dbg_root, mehci,
1107 &ehci_hsic_msm_bus_fops);
1108
1109 if (!ehci_hsic_msm_dentry) {
1110 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1111 return -ENODEV;
1112 }
1113
Hemant Kumar6fd65032012-05-23 13:02:24 -07001114 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1115 S_IRUGO,
1116 ehci_hsic_msm_dbg_root, mehci,
1117 &ehci_hsic_msm_wakeup_cnt_fops);
1118
1119 if (!ehci_hsic_msm_dentry) {
1120 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1121 return -ENODEV;
1122 }
1123
Hemant Kumar45d211b2012-05-31 17:58:43 -07001124 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1125 S_IRUGO,
1126 ehci_hsic_msm_dbg_root, mehci,
1127 &ehci_hsic_msm_dbg_ctrl_fops);
1128
1129 if (!ehci_hsic_msm_dentry) {
1130 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1131 return -ENODEV;
1132 }
1133
1134 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1135 S_IRUGO,
1136 ehci_hsic_msm_dbg_root, mehci,
1137 &ehci_hsic_msm_dbg_data_fops);
1138
1139 if (!ehci_hsic_msm_dentry) {
1140 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1141 return -ENODEV;
1142 }
1143
Hemant Kumare6275972012-02-29 20:06:21 -08001144 return 0;
1145}
1146
1147static void ehci_hsic_msm_debugfs_cleanup(void)
1148{
1149 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1150}
1151
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301152static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1153{
1154 struct usb_hcd *hcd;
1155 struct resource *res;
1156 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301157 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301158 int ret;
1159
1160 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1161
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301162 /* After parent device's probe is executed, it will be put in suspend
1163 * mode. When child device's probe is called, driver core is not
1164 * resuming parent device due to which parent will be in suspend even
1165 * though child is active. Hence resume the parent device explicitly.
1166 */
1167 if (pdev->dev.parent)
1168 pm_runtime_get_sync(pdev->dev.parent);
1169
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301170 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1171 dev_name(&pdev->dev));
1172 if (!hcd) {
1173 dev_err(&pdev->dev, "Unable to create HCD\n");
1174 return -ENOMEM;
1175 }
1176
1177 hcd->irq = platform_get_irq(pdev, 0);
1178 if (hcd->irq < 0) {
1179 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1180 ret = hcd->irq;
1181 goto put_hcd;
1182 }
1183
1184 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1185 if (!res) {
1186 dev_err(&pdev->dev, "Unable to get memory resource\n");
1187 ret = -ENODEV;
1188 goto put_hcd;
1189 }
1190
1191 hcd->rsrc_start = res->start;
1192 hcd->rsrc_len = resource_size(res);
1193 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1194 if (!hcd->regs) {
1195 dev_err(&pdev->dev, "ioremap failed\n");
1196 ret = -ENOMEM;
1197 goto put_hcd;
1198 }
1199
1200 mehci = hcd_to_hsic(hcd);
1201 mehci->dev = &pdev->dev;
1202
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001203 mehci->ehci.susp_sof_bug = 1;
1204
Hemant Kumar933e0402012-05-22 11:11:40 -07001205 mehci->ehci.max_log2_irq_thresh = 6;
1206
Vamsi Krishna34f01582011-12-14 19:54:42 -08001207 res = platform_get_resource_byname(pdev,
1208 IORESOURCE_IRQ,
1209 "peripheral_status_irq");
1210 if (res)
1211 mehci->peripheral_status_irq = res->start;
1212
Hemant Kumar6fd65032012-05-23 13:02:24 -07001213 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
1214 if (res) {
1215 mehci->wakeup_gpio = res->start;
1216 mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
1217 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1218 }
1219
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301220 ret = msm_hsic_init_clocks(mehci, 1);
1221 if (ret) {
1222 dev_err(&pdev->dev, "unable to initialize clocks\n");
1223 ret = -ENODEV;
1224 goto unmap;
1225 }
1226
1227 ret = msm_hsic_init_vddcx(mehci, 1);
1228 if (ret) {
1229 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1230 ret = -ENODEV;
1231 goto deinit_clocks;
1232 }
1233
1234 ret = msm_hsic_reset(mehci);
1235 if (ret) {
1236 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301237 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301238 }
1239
1240 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1241 if (ret) {
1242 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301243 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301244 }
1245
1246 device_init_wakeup(&pdev->dev, 1);
1247 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1248 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001249
1250 if (mehci->peripheral_status_irq) {
1251 ret = request_threaded_irq(mehci->peripheral_status_irq,
1252 NULL, hsic_peripheral_status_change,
1253 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1254 | IRQF_SHARED,
1255 "hsic_peripheral_status", mehci);
1256 if (ret)
1257 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1258 __func__, mehci->peripheral_status_irq, ret);
1259 }
1260
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001261 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001262 if (mehci->wakeup_irq) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001263 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001264 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001265 "msm_hsic_wakeup", mehci);
1266 if (!ret) {
1267 disable_irq_nosync(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001268 } else {
1269 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1270 mehci->wakeup_irq, ret);
1271 mehci->wakeup_irq = 0;
1272 }
1273 }
1274
Hemant Kumare6275972012-02-29 20:06:21 -08001275 ret = ehci_hsic_msm_debugfs_init(mehci);
1276 if (ret)
1277 dev_dbg(&pdev->dev, "mode debugfs file is"
1278 "not available\n");
1279
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301280 pdata = mehci->dev->platform_data;
Hemant Kumare6275972012-02-29 20:06:21 -08001281 if (pdata && pdata->bus_scale_table) {
1282 mehci->bus_perf_client =
1283 msm_bus_scale_register_client(pdata->bus_scale_table);
1284 /* Configure BUS performance parameters for MAX bandwidth */
1285 if (mehci->bus_perf_client) {
1286 ret = msm_bus_scale_client_update_request(
1287 mehci->bus_perf_client, 1);
1288 if (ret)
1289 dev_err(&pdev->dev, "%s: Failed to vote for "
1290 "bus bandwidth %d\n", __func__, ret);
1291 } else {
1292 dev_err(&pdev->dev, "%s: Failed to register BUS "
1293 "scaling client!!\n", __func__);
1294 }
1295 }
1296
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301297 /*
1298 * This pdev->dev is assigned parent of root-hub by USB core,
1299 * hence, runtime framework automatically calls this driver's
1300 * runtime APIs based on root-hub's state.
1301 */
1302 pm_runtime_set_active(&pdev->dev);
1303 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301304 /* Decrement the parent device's counter after probe.
1305 * As child is active, parent will not be put into
1306 * suspend mode.
1307 */
1308 if (pdev->dev.parent)
1309 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301310
1311 return 0;
1312
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301313unconfig_gpio:
1314 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301315deinit_vddcx:
1316 msm_hsic_init_vddcx(mehci, 0);
1317deinit_clocks:
1318 msm_hsic_init_clocks(mehci, 0);
1319unmap:
1320 iounmap(hcd->regs);
1321put_hcd:
1322 usb_put_hcd(hcd);
1323
1324 return ret;
1325}
1326
1327static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1328{
1329 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1330 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1331
Vamsi Krishna34f01582011-12-14 19:54:42 -08001332 if (mehci->peripheral_status_irq)
1333 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001334
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001335 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001336 if (mehci->wakeup_irq_enabled)
1337 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001338 free_irq(mehci->wakeup_irq, mehci);
1339 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001340
Hemant Kumare6275972012-02-29 20:06:21 -08001341 if (mehci->bus_perf_client)
1342 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1343
1344 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301345 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301346 pm_runtime_set_suspended(&pdev->dev);
1347
1348 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301349 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301350 msm_hsic_init_vddcx(mehci, 0);
1351
1352 msm_hsic_init_clocks(mehci, 0);
1353 wake_lock_destroy(&mehci->wlock);
1354 iounmap(hcd->regs);
1355 usb_put_hcd(hcd);
1356
1357 return 0;
1358}
1359
1360#ifdef CONFIG_PM_SLEEP
1361static int msm_hsic_pm_suspend(struct device *dev)
1362{
Jack Phambe05fbb2012-05-16 10:56:26 -07001363 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301364 struct usb_hcd *hcd = dev_get_drvdata(dev);
1365 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1366
1367 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1368
Hemant Kumar45d211b2012-05-31 17:58:43 -07001369 dbg_log_event(NULL, "PM Suspend", 0);
1370
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301371 if (device_may_wakeup(dev))
1372 enable_irq_wake(hcd->irq);
1373
Jack Phambe05fbb2012-05-16 10:56:26 -07001374 ret = msm_hsic_suspend(mehci);
1375
1376 if (ret && device_may_wakeup(dev))
1377 disable_irq_wake(hcd->irq);
1378
1379 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001380}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301381
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301382static int msm_hsic_pm_resume(struct device *dev)
1383{
1384 int ret;
1385 struct usb_hcd *hcd = dev_get_drvdata(dev);
1386 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1387
Hemant Kumar45d211b2012-05-31 17:58:43 -07001388 dbg_log_event(NULL, "PM Resume", 0);
1389
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301390 if (device_may_wakeup(dev))
1391 disable_irq_wake(hcd->irq);
1392
1393 ret = msm_hsic_resume(mehci);
1394 if (ret)
1395 return ret;
1396
1397 /* Bring the device to full powered state upon system resume */
1398 pm_runtime_disable(dev);
1399 pm_runtime_set_active(dev);
1400 pm_runtime_enable(dev);
1401
1402 return 0;
1403}
1404#endif
1405
1406#ifdef CONFIG_PM_RUNTIME
1407static int msm_hsic_runtime_idle(struct device *dev)
1408{
1409 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301410 return 0;
1411}
1412
1413static int msm_hsic_runtime_suspend(struct device *dev)
1414{
1415 struct usb_hcd *hcd = dev_get_drvdata(dev);
1416 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1417
1418 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001419
1420 dbg_log_event(NULL, "Run Time PM Suspend", 0);
1421
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301422 return msm_hsic_suspend(mehci);
1423}
1424
1425static int msm_hsic_runtime_resume(struct device *dev)
1426{
1427 struct usb_hcd *hcd = dev_get_drvdata(dev);
1428 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1429
1430 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001431
1432 dbg_log_event(NULL, "Run Time PM Resume", 0);
1433
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301434 return msm_hsic_resume(mehci);
1435}
1436#endif
1437
1438#ifdef CONFIG_PM
1439static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1440 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301441 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1442 msm_hsic_runtime_idle)
1443};
1444#endif
1445
1446static struct platform_driver ehci_msm_hsic_driver = {
1447 .probe = ehci_hsic_msm_probe,
1448 .remove = __devexit_p(ehci_hsic_msm_remove),
1449 .driver = {
1450 .name = "msm_hsic_host",
1451#ifdef CONFIG_PM
1452 .pm = &msm_hsic_dev_pm_ops,
1453#endif
1454 },
1455};