blob: 2b7f8b3032254fef468c68526db59947cef95fd5 [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>
Ajay Dudaniab3bf192012-08-28 09:58:04 -070030#include <linux/wakelock.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053031#include <linux/pm_runtime.h>
32#include <linux/regulator/consumer.h>
33
34#include <linux/usb/msm_hsusb_hw.h>
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +053035#include <linux/usb/msm_hsusb.h>
36#include <linux/gpio.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030037#include <linux/spinlock.h>
Ajay Dudani11ab1d52012-08-17 17:12:26 -070038#include <linux/kthread.h>
39#include <linux/wait.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030040
41#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053042#include <mach/clk.h>
43#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053044#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080045#include <linux/spinlock.h>
Hemant Kumar45d211b2012-05-31 17:58:43 -070046#include <linux/cpu.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030047#include <mach/rpm-regulator.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053048
49#define MSM_USB_BASE (hcd->regs)
Hemant Kumar105d07f2012-07-02 15:33:07 -070050#define USB_REG_START_OFFSET 0x90
51#define USB_REG_END_OFFSET 0x250
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053052
Hemant Kumar2309eaa2012-08-14 16:46:42 -070053static struct workqueue_struct *ehci_wq;
Ajay Dudani11ab1d52012-08-17 17:12:26 -070054struct ehci_timer {
55#define GPT_LD(p) ((p) & 0x00FFFFFF)
56 u32 gptimer0_ld;
57#define GPT_RUN BIT(31)
58#define GPT_RESET BIT(30)
59#define GPT_MODE BIT(24)
60#define GPT_CNT(p) ((p) & 0x00FFFFFF)
61 u32 gptimer0_ctrl;
62
63 u32 gptimer1_ld;
64 u32 gptimer1_ctrl;
65};
Hemant Kumar2309eaa2012-08-14 16:46:42 -070066
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053067struct msm_hsic_hcd {
68 struct ehci_hcd ehci;
69 struct device *dev;
70 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080071 struct clk *core_clk;
72 struct clk *alt_core_clk;
73 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053074 struct clk *cal_clk;
75 struct regulator *hsic_vddcx;
Ajay Dudaniab3bf192012-08-28 09:58:04 -070076 bool async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053077 atomic_t in_lpm;
Ajay Dudaniab3bf192012-08-28 09:58:04 -070078 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080079 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080080 int wakeup_irq;
Hemant Kumar6fd65032012-05-23 13:02:24 -070081 int wakeup_gpio;
Jack Phamfe441ea2012-03-23 17:03:15 -070082 bool wakeup_irq_enabled;
Ajay Dudaniab3bf192012-08-28 09:58:04 -070083 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080084 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070085 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030086 enum usb_vdd_type vdd_type;
Hemant Kumar2309eaa2012-08-14 16:46:42 -070087
88 struct work_struct bus_vote_w;
89 bool bus_vote;
Ajay Dudani11ab1d52012-08-17 17:12:26 -070090
91 /* gp timer */
92 struct ehci_timer __iomem *timer;
93 struct completion gpt0_completion;
94 struct completion rt_completion;
95 int resume_status;
96 int resume_again;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053097};
98
Hemant Kumar105d07f2012-07-02 15:33:07 -070099struct msm_hsic_hcd *__mehci;
100
Hemant Kumare6275972012-02-29 20:06:21 -0800101static bool debug_bus_voting_enabled = true;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700102
103static unsigned int enable_dbg_log = 1;
104module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
105/*by default log ep0 and efs sync ep*/
106static unsigned int ep_addr_rxdbg_mask = 9;
107module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
108static unsigned int ep_addr_txdbg_mask = 9;
109module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
110
111/* Maximum debug message length */
112#define DBG_MSG_LEN 100UL
113
114/* Maximum number of messages */
115#define DBG_MAX_MSG 256UL
116
117#define TIME_BUF_LEN 20
118
119enum event_type {
120 EVENT_UNDEF = -1,
121 URB_SUBMIT,
122 URB_COMPLETE,
123 EVENT_NONE,
124};
125
126#define EVENT_STR_LEN 5
127
128static char *event_to_str(enum event_type e)
129{
130 switch (e) {
131 case URB_SUBMIT:
132 return "S";
133 case URB_COMPLETE:
134 return "C";
135 case EVENT_NONE:
136 return "NONE";
137 default:
138 return "UNDEF";
139 }
140}
141
142static enum event_type str_to_event(const char *name)
143{
144 if (!strncasecmp("S", name, EVENT_STR_LEN))
145 return URB_SUBMIT;
146 if (!strncasecmp("C", name, EVENT_STR_LEN))
147 return URB_COMPLETE;
148 if (!strncasecmp("", name, EVENT_STR_LEN))
149 return EVENT_NONE;
150
151 return EVENT_UNDEF;
152}
153
154/*log ep0 activity*/
155static struct {
156 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
157 unsigned idx; /* index */
158 rwlock_t lck; /* lock */
159} dbg_hsic_ctrl = {
160 .idx = 0,
161 .lck = __RW_LOCK_UNLOCKED(lck)
162};
163
164static struct {
165 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
166 unsigned idx; /* index */
167 rwlock_t lck; /* lock */
168} dbg_hsic_data = {
169 .idx = 0,
170 .lck = __RW_LOCK_UNLOCKED(lck)
171};
172
173/**
174 * dbg_inc: increments debug event index
175 * @idx: buffer index
176 */
177static void dbg_inc(unsigned *idx)
178{
179 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
180}
181
182/*get_timestamp - returns time of day in us */
183static char *get_timestamp(char *tbuf)
184{
185 unsigned long long t;
186 unsigned long nanosec_rem;
187
188 t = cpu_clock(smp_processor_id());
189 nanosec_rem = do_div(t, 1000000000)/1000;
190 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
191 nanosec_rem);
192 return tbuf;
193}
194
195static int allow_dbg_log(int ep_addr)
196{
197 int dir, num;
198
199 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
200 num = ep_addr & ~USB_DIR_IN;
201 num = 1 << num;
202
203 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
204 return 1;
205 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
206 return 1;
207
208 return 0;
209}
210
211static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
212{
213 unsigned long flags;
214 int ep_addr;
215 char tbuf[TIME_BUF_LEN];
216
217 if (!enable_dbg_log)
218 return;
219
220 if (!urb) {
221 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
222 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
223 "%s: %s : %u\n", get_timestamp(tbuf), event, extra);
224 dbg_inc(&dbg_hsic_ctrl.idx);
225 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
226 return;
227 }
228
229 ep_addr = urb->ep->desc.bEndpointAddress;
230 if (!allow_dbg_log(ep_addr))
231 return;
232
233 if ((ep_addr & 0x0f) == 0x0) {
234 /*submit event*/
235 if (!str_to_event(event)) {
236 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
237 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
238 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
239 "%02x %02x %04x %04x %04x %u %d\n",
240 get_timestamp(tbuf), event, urb,
241 (ep_addr & USB_DIR_IN) ? "in" : "out",
242 urb->setup_packet[0], urb->setup_packet[1],
243 (urb->setup_packet[3] << 8) |
244 urb->setup_packet[2],
245 (urb->setup_packet[5] << 8) |
246 urb->setup_packet[4],
247 (urb->setup_packet[7] << 8) |
248 urb->setup_packet[6],
249 urb->transfer_buffer_length, urb->status);
250
251 dbg_inc(&dbg_hsic_ctrl.idx);
252 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
253 } else {
254 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
255 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
256 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d\n",
257 get_timestamp(tbuf), event, urb,
258 (ep_addr & USB_DIR_IN) ? "in" : "out",
259 urb->actual_length, extra);
260
261 dbg_inc(&dbg_hsic_ctrl.idx);
262 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
263 }
264 } else {
265 write_lock_irqsave(&dbg_hsic_data.lck, flags);
266 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
267 "%s: [%s : %p]:ep%d[%s] %u %d\n",
268 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
269 (ep_addr & USB_DIR_IN) ? "in" : "out",
270 str_to_event(event) ? urb->actual_length :
271 urb->transfer_buffer_length,
272 str_to_event(event) ? extra : urb->status);
273
274 dbg_inc(&dbg_hsic_data.idx);
275 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
276 }
277}
278
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530279static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
280{
281 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
282}
283
284static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
285{
286 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
287}
288
Hemant Kumar105d07f2012-07-02 15:33:07 -0700289static void dump_hsic_regs(struct usb_hcd *hcd)
290{
291 int i;
292 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
293
294 if (atomic_read(&mehci->in_lpm))
295 return;
296
297 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
298 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
299 readl_relaxed(hcd->regs + i),
300 readl_relaxed(hcd->regs + i + 4),
301 readl_relaxed(hcd->regs + i + 8),
302 readl_relaxed(hcd->regs + i + 0xc));
303}
304
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530305#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
306
Amit Blayd6ea6102012-06-07 16:26:24 +0300307#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700308#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
309#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530310
Lena Salman8c8ba382012-02-14 15:59:31 +0200311#define HSIC_DBG1_REG 0x38
312
Amit Blayd6ea6102012-06-07 16:26:24 +0300313static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
314 { /* VDD_CX CORNER Voting */
315 [VDD_NONE] = RPM_VREG_CORNER_NONE,
316 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
317 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
318 },
319 { /* VDD_CX Voltage Voting */
320 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
321 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
322 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
323 },
324};
325
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530326static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
327{
328 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300329 int none_vol, min_vol, max_vol;
330
331 if (!mehci->hsic_vddcx) {
332 mehci->vdd_type = VDDCX_CORNER;
333 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
334 "hsic_vdd_dig");
335 if (IS_ERR(mehci->hsic_vddcx)) {
336 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
337 "HSIC_VDDCX");
338 if (IS_ERR(mehci->hsic_vddcx)) {
339 dev_err(mehci->dev, "unable to get hsic vddcx\n");
340 return PTR_ERR(mehci->hsic_vddcx);
341 }
342 mehci->vdd_type = VDDCX;
343 }
344 }
345
346 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
347 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
348 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530349
350 if (!init)
351 goto disable_reg;
352
Amit Blayd6ea6102012-06-07 16:26:24 +0300353 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530354 if (ret) {
355 dev_err(mehci->dev, "unable to set the voltage"
356 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530357 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530358 }
359
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530360 ret = regulator_enable(mehci->hsic_vddcx);
361 if (ret) {
362 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
363 goto reg_enable_err;
364 }
365
366 return 0;
367
368disable_reg:
369 regulator_disable(mehci->hsic_vddcx);
370reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300371 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
372
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530373 return ret;
374
375}
376
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700377static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
378{
379 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Devin Kim01e5a5b2012-08-30 02:52:45 -0700380 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700381
382 /* initiate read operation */
383 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
384 USB_ULPI_VIEWPORT);
385
386 /* wait for completion */
Devin Kim01e5a5b2012-08-30 02:52:45 -0700387 while (cnt < ULPI_IO_TIMEOUT_USEC) {
388 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
389 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700390 udelay(1);
Devin Kim01e5a5b2012-08-30 02:52:45 -0700391 cnt++;
392 }
393
394 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
395 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
396 readl_relaxed(USB_ULPI_VIEWPORT));
397 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
398 readl_relaxed(USB_PORTSC),
399 readl_relaxed(USB_USBCMD),
400 readl_relaxed(USB_FRINDEX));
401
402 /*frame counter increments afte 125us*/
403 udelay(130);
404 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
405 readl_relaxed(USB_FRINDEX));
406 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700407 }
408
409 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
410}
411
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530412static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
413{
414 struct usb_hcd *hcd = hsic_to_hcd(mehci);
415 int cnt = 0;
416
417 /* initiate write operation */
418 writel_relaxed(ULPI_RUN | ULPI_WRITE |
419 ULPI_ADDR(reg) | ULPI_DATA(val),
420 USB_ULPI_VIEWPORT);
421
422 /* wait for completion */
423 while (cnt < ULPI_IO_TIMEOUT_USEC) {
424 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
425 break;
426 udelay(1);
427 cnt++;
428 }
429
430 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Devin Kim01e5a5b2012-08-30 02:52:45 -0700431 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
432 readl_relaxed(USB_ULPI_VIEWPORT));
433 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
434 readl_relaxed(USB_PORTSC),
435 readl_relaxed(USB_USBCMD),
436 readl_relaxed(USB_FRINDEX));
437
438 /*frame counter increments afte 125us*/
439 udelay(130);
440 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
441 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530442 return -ETIMEDOUT;
443 }
444
445 return 0;
446}
447
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700448#define HSIC_DBG1 0X38
449#define ULPI_MANUAL_ENABLE BIT(4)
450#define ULPI_LINESTATE_DATA BIT(5)
451#define ULPI_LINESTATE_STROBE BIT(6)
452static void ehci_msm_enable_ulpi_control(struct usb_hcd *hcd, u32 linestate)
453{
454 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
455 int val;
456
457 switch (linestate) {
458 case PORT_RESET:
459 val = ulpi_read(mehci, HSIC_DBG1);
460 val |= ULPI_MANUAL_ENABLE;
461 val &= ~(ULPI_LINESTATE_DATA | ULPI_LINESTATE_STROBE);
462 ulpi_write(mehci, val, HSIC_DBG1);
463 break;
464 default:
465 pr_info("%s: Unknown linestate:%0x\n", __func__, linestate);
466 }
467}
468
469static void ehci_msm_disable_ulpi_control(struct usb_hcd *hcd)
470{
471 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
472 int val;
473
474 val = ulpi_read(mehci, HSIC_DBG1);
475 val &= ~ULPI_MANUAL_ENABLE;
476 ulpi_write(mehci, val, HSIC_DBG1);
477}
478
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530479static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
480{
481 int rc = 0;
482 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800483 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530484
485 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800486
Lena Salman8c8ba382012-02-14 15:59:31 +0200487 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530488 return rc;
489
Vamsi Krishna34f01582011-12-14 19:54:42 -0800490 if (gpio_status == gpio_en)
491 return 0;
492
493 gpio_status = gpio_en;
494
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530495 if (!gpio_en)
496 goto free_gpio;
497
498 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
499 if (rc < 0) {
500 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
501 return rc;
502 }
503
504 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
505 if (rc < 0) {
506 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
507 goto free_strobe;
508 }
509
Hemant Kumar6fd65032012-05-23 13:02:24 -0700510 if (mehci->wakeup_gpio) {
511 rc = gpio_request(mehci->wakeup_gpio, "HSIC_WAKEUP_GPIO");
512 if (rc < 0) {
513 dev_err(mehci->dev, "gpio request failed for HSIC WAKEUP\n");
514 goto free_data;
515 }
516 }
517
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530518 return 0;
519
520free_gpio:
Hemant Kumar6fd65032012-05-23 13:02:24 -0700521 if (mehci->wakeup_gpio)
522 gpio_free(mehci->wakeup_gpio);
523free_data:
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530524 gpio_free(pdata->data);
525free_strobe:
526 gpio_free(pdata->strobe);
527
528 return rc;
529}
530
Vamsi Krishna64b48612012-06-14 16:08:11 -0700531static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530532{
533 int ret;
534
Manu Gautam5143b252012-01-05 19:25:23 -0800535 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530536 if (ret) {
Vamsi Krishna64b48612012-06-14 16:08:11 -0700537 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
538 return;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530539 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700540 clk_disable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530541
Manu Gautam5143b252012-01-05 19:25:23 -0800542 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530543 if (ret)
Vamsi Krishna64b48612012-06-14 16:08:11 -0700544 dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530545
Vamsi Krishna64b48612012-06-14 16:08:11 -0700546 usleep_range(10000, 12000);
547
548 clk_enable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530549}
550
Vamsi Krishna64b48612012-06-14 16:08:11 -0700551#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
552#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530553#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
554#define HSIC_LV_MODE 0x04
555#define HSIC_PAD_CALIBRATION 0xA8
556#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530557#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
558static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
559{
560 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530561 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200562 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530563
Vamsi Krishna64b48612012-06-14 16:08:11 -0700564 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530565
Vamsi Krishna64b48612012-06-14 16:08:11 -0700566 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530567 writel_relaxed(0x80000000, USB_PORTSC);
568
Vamsi Krishna64b48612012-06-14 16:08:11 -0700569 mb();
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530570
Lena Salman8c8ba382012-02-14 15:59:31 +0200571 /* HSIC init sequence when HSIC signals (Strobe/Data) are
572 routed via GPIOs */
573 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530574
Lena Salman8c8ba382012-02-14 15:59:31 +0200575 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
576 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530577
Vamsi Krishna64b48612012-06-14 16:08:11 -0700578 mb();
579
Lena Salman8c8ba382012-02-14 15:59:31 +0200580 /*set periodic calibration interval to ~2.048sec in
581 HSIC_IO_CAL_REG */
582 ulpi_write(mehci, 0xFF, 0x33);
583
584 /* Enable periodic IO calibration in HSIC_CFG register */
585 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
586
Vamsi Krishna64b48612012-06-14 16:08:11 -0700587 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200588 ret = msm_hsic_config_gpios(mehci, 1);
589 if (ret) {
590 dev_err(mehci->dev, " gpio configuarion failed\n");
591 return ret;
592 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700593 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO PAD_CTL register */
594 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_STROBE_GPIO_PAD_CTL);
595 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_DATA_GPIO_PAD_CTL);
596
597 mb();
598
Lena Salman8c8ba382012-02-14 15:59:31 +0200599 /* Enable HSIC mode in HSIC_CFG register */
600 ulpi_write(mehci, 0x01, 0x31);
601 } else {
602 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
603 via dedicated I/O */
604
605 /* programmable length of connect signaling (33.2ns) */
606 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
607 if (ret) {
608 pr_err("%s: Unable to program length of connect "
609 "signaling\n", __func__);
610 }
611
612 /*set periodic calibration interval to ~2.048sec in
613 HSIC_IO_CAL_REG */
614 ulpi_write(mehci, 0xFF, 0x33);
615
616 /* Enable HSIC mode in HSIC_CFG register */
617 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530618 }
619
Hemant Kumar6fd65032012-05-23 13:02:24 -0700620 /*disable auto resume*/
621 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
622
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530623 return 0;
624}
625
626#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
627#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
628
629#ifdef CONFIG_PM_SLEEP
630static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
631{
632 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530633 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530634 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300635 int none_vol, max_vol;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530636
637 if (atomic_read(&mehci->in_lpm)) {
638 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
639 return 0;
640 }
641
Hemant Kumar7f374632012-05-31 20:10:32 -0700642 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
643 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
644 __func__);
645 return -EAGAIN;
646 }
647
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530648 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700649
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700650 /* make sure we don't race against a remote wakeup */
651 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700652 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700653 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700654 enable_irq(hcd->irq);
655 return -EBUSY;
656 }
657
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530658 /*
659 * PHY may take some time or even fail to enter into low power
660 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
661 * in failure case.
662 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700663 val = readl_relaxed(USB_PORTSC);
664 val &= ~PORT_RWC_BITS;
665 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530666 writel_relaxed(val, USB_PORTSC);
667 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
668 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
669 break;
670 udelay(1);
671 cnt++;
672 }
673
674 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
675 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530676 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530677 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530678 }
679
680 /*
681 * PHY has capability to generate interrupt asynchronously in low
682 * power mode (LPM). This interrupt is level triggered. So USB IRQ
683 * line must be disabled till async interrupt enable bit is cleared
684 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
685 * block data communication from PHY.
686 */
687 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
688 ULPI_STP_CTRL, USB_USBCMD);
689
690 /*
691 * Ensure that hardware is put in low power mode before
692 * clocks are turned OFF and VDD is allowed to minimize.
693 */
694 mb();
695
Manu Gautam28b1bac2012-01-30 16:43:06 +0530696 clk_disable_unprepare(mehci->core_clk);
697 clk_disable_unprepare(mehci->phy_clk);
698 clk_disable_unprepare(mehci->cal_clk);
699 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530700
Amit Blayd6ea6102012-06-07 16:26:24 +0300701 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
702 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
703
704 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700705 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300706 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700707
Hemant Kumare6275972012-02-29 20:06:21 -0800708 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700709 mehci->bus_vote = false;
710 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800711 }
712
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530713 atomic_set(&mehci->in_lpm, 1);
714 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700715
716 mehci->wakeup_irq_enabled = 1;
717 enable_irq_wake(mehci->wakeup_irq);
718 enable_irq(mehci->wakeup_irq);
719
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700720 wake_unlock(&mehci->wlock);
721
Devin Kim476bbd72012-07-19 18:11:11 -0700722 dev_dbg(mehci->dev, "HSIC-USB in low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530723
724 return 0;
725}
726
727static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
728{
729 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530730 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530731 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300732 int min_vol, max_vol;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530733
734 if (!atomic_read(&mehci->in_lpm)) {
735 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
736 return 0;
737 }
738
Hemant Kumar6fd65032012-05-23 13:02:24 -0700739 if (mehci->wakeup_irq_enabled) {
740 disable_irq_wake(mehci->wakeup_irq);
741 disable_irq_nosync(mehci->wakeup_irq);
742 mehci->wakeup_irq_enabled = 0;
743 }
744
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700745 wake_lock(&mehci->wlock);
746
Hemant Kumare6275972012-02-29 20:06:21 -0800747 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700748 mehci->bus_vote = true;
749 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800750 }
751
Amit Blayd6ea6102012-06-07 16:26:24 +0300752 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
753 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
754
755 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700756 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300757 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700758
Manu Gautam28b1bac2012-01-30 16:43:06 +0530759 clk_prepare_enable(mehci->core_clk);
760 clk_prepare_enable(mehci->phy_clk);
761 clk_prepare_enable(mehci->cal_clk);
762 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530763
764 temp = readl_relaxed(USB_USBCMD);
765 temp &= ~ASYNC_INTR_CTRL;
766 temp &= ~ULPI_STP_CTRL;
767 writel_relaxed(temp, USB_USBCMD);
768
769 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
770 goto skip_phy_resume;
771
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700772 temp = readl_relaxed(USB_PORTSC);
773 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530774 writel_relaxed(temp, USB_PORTSC);
775 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
776 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
777 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
778 break;
779 udelay(1);
780 cnt++;
781 }
782
783 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
784 /*
785 * This is a fatal error. Reset the link and
786 * PHY to make hsic working.
787 */
788 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530789 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530790 msm_hsic_reset(mehci);
791 }
792
793skip_phy_resume:
794
Hemant Kumar6fd65032012-05-23 13:02:24 -0700795 usb_hcd_resume_root_hub(hcd);
796
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530797 atomic_set(&mehci->in_lpm, 0);
798
799 if (mehci->async_int) {
800 mehci->async_int = false;
801 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700802 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700803 }
804
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700805 if (atomic_read(&mehci->pm_usage_cnt)) {
806 atomic_set(&mehci->pm_usage_cnt, 0);
807 pm_runtime_put_noidle(mehci->dev);
808 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700809
Devin Kim476bbd72012-07-19 18:11:11 -0700810 dev_dbg(mehci->dev, "HSIC-USB exited from low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530811
812 return 0;
813}
814#endif
815
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700816static void ehci_hsic_bus_vote_w(struct work_struct *w)
817{
818 struct msm_hsic_hcd *mehci =
819 container_of(w, struct msm_hsic_hcd, bus_vote_w);
820 int ret;
821
822 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
823 mehci->bus_vote);
824 if (ret)
825 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
826 __func__, ret);
827}
828
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700829#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530830static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
831{
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700832 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530833 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700834 u32 status;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530835
836 if (atomic_read(&mehci->in_lpm)) {
837 disable_irq_nosync(hcd->irq);
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700838 dev_dbg(mehci->dev, "phy async intr\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530839 mehci->async_int = true;
840 pm_runtime_get(mehci->dev);
841 return IRQ_HANDLED;
842 }
843
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700844 status = ehci_readl(ehci, &ehci->regs->status);
845
846 if (status & STS_GPTIMER0_INTERRUPT) {
847 int timeleft;
848
849 dbg_log_event(NULL, "FPR: gpt0_isr", 0);
850
851 timeleft = GPT_CNT(ehci_readl(ehci,
852 &mehci->timer->gptimer1_ctrl));
853 if (timeleft) {
854 ehci_writel(ehci, ehci_readl(ehci,
855 &ehci->regs->command) | CMD_RUN,
856 &ehci->regs->command);
857 } else
858 mehci->resume_again = 1;
859
860 dbg_log_event(NULL, "FPR: timeleft", timeleft);
861
862 complete(&mehci->gpt0_completion);
863 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
864 }
865
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530866 return ehci_irq(hcd);
867}
868
869static int ehci_hsic_reset(struct usb_hcd *hcd)
870{
871 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700872 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530873 int retval;
874
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700875 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530876 ehci->caps = USB_CAPLENGTH;
877 ehci->regs = USB_CAPLENGTH +
878 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
879 dbg_hcs_params(ehci, "reset");
880 dbg_hcc_params(ehci, "reset");
881
882 /* cache the data to minimize the chip reads*/
883 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
884
885 hcd->has_tt = 1;
886 ehci->sbrn = HCD_USB2;
887
888 retval = ehci_halt(ehci);
889 if (retval)
890 return retval;
891
892 /* data structure init */
893 retval = ehci_init(hcd);
894 if (retval)
895 return retval;
896
897 retval = ehci_reset(ehci);
898 if (retval)
899 return retval;
900
901 /* bursts of unspecified length. */
902 writel_relaxed(0, USB_AHBBURST);
903 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530904 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530905 /* Disable streaming mode and select host mode */
906 writel_relaxed(0x13, USB_USBMODE);
907
908 ehci_port_power(ehci, 1);
909 return 0;
910}
911
Hemant Kumar45d211b2012-05-31 17:58:43 -0700912static int ehci_hsic_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
913 gfp_t mem_flags)
914{
915 dbg_log_event(urb, event_to_str(URB_SUBMIT), 0);
916 return ehci_urb_enqueue(hcd, urb, mem_flags);
917}
918
919static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
920{
921 dbg_log_event(NULL, "Suspend RH", 0);
922 return ehci_bus_suspend(hcd);
923}
924
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700925#define RESUME_RETRY_LIMIT 3
926#define RESUME_SIGNAL_TIME_MS (21 * 999)
927#define RESUME_SIGNAL_TIME_SOF_MS (23 * 999)
928static int msm_hsic_resume_thread(void *data)
929{
930 struct msm_hsic_hcd *mehci = data;
931 struct usb_hcd *hcd = hsic_to_hcd(mehci);
932 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
933 u32 temp;
934 unsigned long resume_needed = 0;
935 int retry_cnt = 0;
936 int tight_resume = 0;
937
938 dbg_log_event(NULL, "Resume RH", 0);
939
940 /* keep delay between bus states */
941 if (time_before(jiffies, ehci->next_statechange))
942 usleep_range(5000, 5000);
943
944 spin_lock_irq(&ehci->lock);
945 if (!HCD_HW_ACCESSIBLE(hcd)) {
946 spin_unlock_irq(&ehci->lock);
947 mehci->resume_status = -ESHUTDOWN;
948 complete(&mehci->rt_completion);
949 return 0;
950 }
951
952 if (unlikely(ehci->debug)) {
953 if (!dbgp_reset_prep())
954 ehci->debug = NULL;
955 else
956 dbgp_external_startup();
957 }
958
959 /* at least some APM implementations will try to deliver
960 * IRQs right away, so delay them until we're ready.
961 */
962 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
963
964 /* re-init operational registers */
965 ehci_writel(ehci, 0, &ehci->regs->segment);
966 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
967 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
968
969 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
970 if (ehci->resume_sof_bug)
971 ehci->command &= ~CMD_RUN;
972
973 /* restore CMD_RUN, framelist size, and irq threshold */
974 ehci_writel(ehci, ehci->command, &ehci->regs->command);
975
976 /* manually resume the ports we suspended during bus_suspend() */
977resume_again:
978 if (retry_cnt >= RESUME_RETRY_LIMIT) {
979 pr_info("retry count(%d) reached max, resume in tight loop\n",
980 retry_cnt);
981 tight_resume = 1;
982 }
983
984
985 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
986 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
987 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
988 temp |= PORT_RESUME;
989 set_bit(0, &resume_needed);
990 }
991 dbg_log_event(NULL, "FPR: Set", temp);
992 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
993
994 /* HSIC controller has a h/w bug due to which it can try to send SOFs
995 * (start of frames) during port resume resulting in phy lockup. HSIC hw
996 * controller in MSM clears FPR bit after driving the resume signal for
997 * 20ms. Workaround is to stop SOFs before driving resume and then start
998 * sending SOFs immediately. Need to send SOFs within 3ms of resume
999 * completion otherwise peripheral may enter undefined state. As
1000 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1001 * to time the resume sequence. If driver exceeds allowable time SOFs,
1002 * repeat the resume process.
1003 */
1004 if (ehci->resume_sof_bug && resume_needed) {
1005 if (!tight_resume) {
1006 mehci->resume_again = 0;
1007 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_MS),
1008 &mehci->timer->gptimer0_ld);
1009 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1010 &mehci->timer->gptimer0_ctrl);
1011 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1012 &ehci->regs->intr_enable);
1013
1014 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_SOF_MS),
1015 &mehci->timer->gptimer1_ld);
1016 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1017 &mehci->timer->gptimer1_ctrl);
1018
1019 spin_unlock_irq(&ehci->lock);
1020 wait_for_completion(&mehci->gpt0_completion);
1021 spin_lock_irq(&ehci->lock);
1022 } else {
1023 dbg_log_event(NULL, "FPR: Tightloop", 0);
1024 /* do the resume in a tight loop */
1025 handshake(ehci, &ehci->regs->port_status[0],
1026 PORT_RESUME, 0, 22 * 1000);
1027 ehci_writel(ehci, ehci_readl(ehci,
1028 &ehci->regs->command) | CMD_RUN,
1029 &ehci->regs->command);
1030 }
1031
1032 if (mehci->resume_again) {
1033 int temp;
1034
1035 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1036 pr_info("FPR: retry count: %d\n", retry_cnt);
1037 spin_unlock_irq(&ehci->lock);
1038 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1039 temp &= ~PORT_RWC_BITS;
1040 temp |= PORT_SUSPEND;
1041 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1042 /* Keep the bus idle for 5ms so that peripheral
1043 * can detect and initiate suspend
1044 */
1045 usleep_range(5000, 5000);
1046 dbg_log_event(NULL,
1047 "FPR: RResume",
1048 ehci_readl(ehci, &ehci->regs->port_status[0]));
1049 spin_lock_irq(&ehci->lock);
1050 mehci->resume_again = 0;
1051 retry_cnt++;
1052 goto resume_again;
1053 }
1054 }
1055
1056 dbg_log_event(NULL, "FPR: RT-Done", 0);
1057 mehci->resume_status = 1;
1058 spin_unlock_irq(&ehci->lock);
1059
1060 complete(&mehci->rt_completion);
1061
1062 return 0;
1063}
1064
Hemant Kumar45d211b2012-05-31 17:58:43 -07001065static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1066{
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001067 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1068 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1069 u32 temp;
1070 struct task_struct *resume_thread = NULL;
1071
1072 mehci->resume_status = 0;
1073 resume_thread = kthread_run(msm_hsic_resume_thread,
1074 mehci, "hsic_resume_thread");
1075 if (IS_ERR(resume_thread)) {
1076 pr_err("Error creating resume thread:%lu\n",
1077 PTR_ERR(resume_thread));
1078 return PTR_ERR(resume_thread);
1079 }
1080
1081 wait_for_completion(&mehci->rt_completion);
1082
1083 if (mehci->resume_status < 0)
1084 return mehci->resume_status;
1085
1086 dbg_log_event(NULL, "FPR: Wokeup", 0);
1087 spin_lock_irq(&ehci->lock);
1088 (void) ehci_readl(ehci, &ehci->regs->command);
1089
1090 temp = 0;
1091 if (ehci->async->qh_next.qh)
1092 temp |= CMD_ASE;
1093 if (ehci->periodic_sched)
1094 temp |= CMD_PSE;
1095 if (temp) {
1096 ehci->command |= temp;
1097 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1098 }
1099
1100 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1101 hcd->state = HC_STATE_RUNNING;
1102 ehci->rh_state = EHCI_RH_RUNNING;
1103
1104 /* Now we can safely re-enable irqs */
1105 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1106
1107 spin_unlock_irq(&ehci->lock);
1108
1109 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001110}
1111
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301112static struct hc_driver msm_hsic_driver = {
1113 .description = hcd_name,
1114 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1115 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1116
1117 /*
1118 * generic hardware linkage
1119 */
1120 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001121 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301122
1123 .reset = ehci_hsic_reset,
1124 .start = ehci_run,
1125
1126 .stop = ehci_stop,
1127 .shutdown = ehci_shutdown,
1128
1129 /*
1130 * managing i/o requests and associated device resources
1131 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001132 .urb_enqueue = ehci_hsic_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301133 .urb_dequeue = ehci_urb_dequeue,
1134 .endpoint_disable = ehci_endpoint_disable,
1135 .endpoint_reset = ehci_endpoint_reset,
1136 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1137
1138 /*
1139 * scheduling support
1140 */
1141 .get_frame_number = ehci_get_frame,
1142
1143 /*
1144 * root hub support
1145 */
1146 .hub_status_data = ehci_hub_status_data,
1147 .hub_control = ehci_hub_control,
1148 .relinquish_port = ehci_relinquish_port,
1149 .port_handed_over = ehci_port_handed_over,
1150
1151 /*
1152 * PM support
1153 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001154 .bus_suspend = ehci_hsic_bus_suspend,
1155 .bus_resume = ehci_hsic_bus_resume,
1156
1157 .log_urb_complete = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001158 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001159
1160 .enable_ulpi_control = ehci_msm_enable_ulpi_control,
1161 .disable_ulpi_control = ehci_msm_disable_ulpi_control,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301162};
1163
1164static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1165{
1166 int ret = 0;
1167
1168 if (!init)
1169 goto put_clocks;
1170
Lena Salman8c8ba382012-02-14 15:59:31 +02001171 /*core_clk is required for LINK protocol engine
1172 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001173 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1174 if (IS_ERR(mehci->core_clk)) {
1175 dev_err(mehci->dev, "failed to get core_clk\n");
1176 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301177 return ret;
1178 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301179
Lena Salman8c8ba382012-02-14 15:59:31 +02001180 /* alt_core_clk is for LINK to be used during PHY RESET
1181 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001182 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
1183 if (IS_ERR(mehci->alt_core_clk)) {
1184 dev_err(mehci->dev, "failed to core_clk\n");
1185 ret = PTR_ERR(mehci->alt_core_clk);
1186 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301187 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301188
Lena Salman8c8ba382012-02-14 15:59:31 +02001189 /* phy_clk is required for HSIC PHY operation
1190 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001191 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1192 if (IS_ERR(mehci->phy_clk)) {
1193 dev_err(mehci->dev, "failed to get phy_clk\n");
1194 ret = PTR_ERR(mehci->phy_clk);
1195 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301196 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301197
1198 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001199 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301200 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001201 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301202 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001203 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301204 }
1205 clk_set_rate(mehci->cal_clk, 10000000);
1206
1207 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001208 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301209 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001210 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301211 ret = PTR_ERR(mehci->ahb_clk);
1212 goto put_cal_clk;
1213 }
1214
Manu Gautam28b1bac2012-01-30 16:43:06 +05301215 clk_prepare_enable(mehci->core_clk);
1216 clk_prepare_enable(mehci->phy_clk);
1217 clk_prepare_enable(mehci->cal_clk);
1218 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301219
1220 return 0;
1221
1222put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001223 if (!atomic_read(&mehci->in_lpm)) {
1224 clk_disable_unprepare(mehci->core_clk);
1225 clk_disable_unprepare(mehci->phy_clk);
1226 clk_disable_unprepare(mehci->cal_clk);
1227 clk_disable_unprepare(mehci->ahb_clk);
1228 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301229 clk_put(mehci->ahb_clk);
1230put_cal_clk:
1231 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001232put_phy_clk:
1233 clk_put(mehci->phy_clk);
1234put_alt_core_clk:
1235 clk_put(mehci->alt_core_clk);
1236put_core_clk:
1237 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301238
1239 return ret;
1240}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001241static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1242{
1243 struct msm_hsic_hcd *mehci = dev_id;
1244
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001245 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001246
1247 if (mehci)
1248 msm_hsic_config_gpios(mehci, 0);
1249
1250 return IRQ_HANDLED;
1251}
1252
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001253static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1254{
1255 struct msm_hsic_hcd *mehci = data;
1256
Hemant Kumar6fd65032012-05-23 13:02:24 -07001257 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001258 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001259 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
1260 __func__, mehci->wakeup_int_cnt);
1261
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001262 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001263
Jack Phamfe441ea2012-03-23 17:03:15 -07001264 if (mehci->wakeup_irq_enabled) {
1265 mehci->wakeup_irq_enabled = 0;
1266 disable_irq_wake(irq);
1267 disable_irq_nosync(irq);
1268 }
1269
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001270 if (!atomic_read(&mehci->pm_usage_cnt)) {
1271 atomic_set(&mehci->pm_usage_cnt, 1);
1272 pm_runtime_get(mehci->dev);
1273 }
1274
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001275 return IRQ_HANDLED;
1276}
1277
Hemant Kumare6275972012-02-29 20:06:21 -08001278static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1279{
1280 if (debug_bus_voting_enabled)
1281 seq_printf(s, "enabled\n");
1282 else
1283 seq_printf(s, "disabled\n");
1284
1285 return 0;
1286}
1287
1288static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1289{
1290 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1291}
1292
1293static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1294 const char __user *ubuf, size_t count, loff_t *ppos)
1295{
1296 char buf[8];
1297 int ret;
1298 struct seq_file *s = file->private_data;
1299 struct msm_hsic_hcd *mehci = s->private;
1300
1301 memset(buf, 0x00, sizeof(buf));
1302
1303 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1304 return -EFAULT;
1305
1306 if (!strncmp(buf, "enable", 6)) {
1307 /* Do not vote here. Let hsic driver decide when to vote */
1308 debug_bus_voting_enabled = true;
1309 } else {
1310 debug_bus_voting_enabled = false;
1311 if (mehci->bus_perf_client) {
1312 ret = msm_bus_scale_client_update_request(
1313 mehci->bus_perf_client, 0);
1314 if (ret)
1315 dev_err(mehci->dev, "%s: Failed to devote "
1316 "for bus bw %d\n", __func__, ret);
1317 }
1318 }
1319
1320 return count;
1321}
1322
1323const struct file_operations ehci_hsic_msm_bus_fops = {
1324 .open = ehci_hsic_msm_bus_open,
1325 .read = seq_read,
1326 .write = ehci_hsic_msm_bus_write,
1327 .llseek = seq_lseek,
1328 .release = single_release,
1329};
1330
Hemant Kumar6fd65032012-05-23 13:02:24 -07001331static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1332{
1333 struct msm_hsic_hcd *mehci = s->private;
1334
1335 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1336
1337 return 0;
1338}
1339
1340static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1341{
1342 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1343}
1344
1345const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1346 .open = ehci_hsic_msm_wakeup_cnt_open,
1347 .read = seq_read,
1348 .llseek = seq_lseek,
1349 .release = single_release,
1350};
1351
Hemant Kumar45d211b2012-05-31 17:58:43 -07001352static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1353{
1354 unsigned long flags;
1355 unsigned i;
1356
1357 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1358
1359 i = dbg_hsic_data.idx;
1360 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1361 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1362 continue;
1363 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1364 }
1365
1366 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1367
1368 return 0;
1369}
1370
1371static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1372{
1373 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1374}
1375
1376const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1377 .open = ehci_hsic_msm_data_events_open,
1378 .read = seq_read,
1379 .llseek = seq_lseek,
1380 .release = single_release,
1381};
1382
1383static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1384{
1385 unsigned long flags;
1386 unsigned i;
1387
1388 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1389
1390 i = dbg_hsic_ctrl.idx;
1391 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1392 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1393 continue;
1394 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1395 }
1396
1397 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1398
1399 return 0;
1400}
1401
1402static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1403{
1404 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1405}
1406
1407const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1408 .open = ehci_hsic_msm_ctrl_events_open,
1409 .read = seq_read,
1410 .llseek = seq_lseek,
1411 .release = single_release,
1412};
1413
Hemant Kumare6275972012-02-29 20:06:21 -08001414static struct dentry *ehci_hsic_msm_dbg_root;
1415static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1416{
1417 struct dentry *ehci_hsic_msm_dentry;
1418
1419 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1420
1421 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1422 return -ENODEV;
1423
1424 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1425 S_IRUGO | S_IWUSR,
1426 ehci_hsic_msm_dbg_root, mehci,
1427 &ehci_hsic_msm_bus_fops);
1428
1429 if (!ehci_hsic_msm_dentry) {
1430 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1431 return -ENODEV;
1432 }
1433
Hemant Kumar6fd65032012-05-23 13:02:24 -07001434 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1435 S_IRUGO,
1436 ehci_hsic_msm_dbg_root, mehci,
1437 &ehci_hsic_msm_wakeup_cnt_fops);
1438
1439 if (!ehci_hsic_msm_dentry) {
1440 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1441 return -ENODEV;
1442 }
1443
Hemant Kumar45d211b2012-05-31 17:58:43 -07001444 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1445 S_IRUGO,
1446 ehci_hsic_msm_dbg_root, mehci,
1447 &ehci_hsic_msm_dbg_ctrl_fops);
1448
1449 if (!ehci_hsic_msm_dentry) {
1450 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1451 return -ENODEV;
1452 }
1453
1454 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1455 S_IRUGO,
1456 ehci_hsic_msm_dbg_root, mehci,
1457 &ehci_hsic_msm_dbg_data_fops);
1458
1459 if (!ehci_hsic_msm_dentry) {
1460 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1461 return -ENODEV;
1462 }
1463
Hemant Kumare6275972012-02-29 20:06:21 -08001464 return 0;
1465}
1466
1467static void ehci_hsic_msm_debugfs_cleanup(void)
1468{
1469 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1470}
1471
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301472static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1473{
1474 struct usb_hcd *hcd;
1475 struct resource *res;
1476 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301477 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301478 int ret;
1479
1480 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1481
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301482 /* After parent device's probe is executed, it will be put in suspend
1483 * mode. When child device's probe is called, driver core is not
1484 * resuming parent device due to which parent will be in suspend even
1485 * though child is active. Hence resume the parent device explicitly.
1486 */
1487 if (pdev->dev.parent)
1488 pm_runtime_get_sync(pdev->dev.parent);
1489
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301490 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1491 dev_name(&pdev->dev));
1492 if (!hcd) {
1493 dev_err(&pdev->dev, "Unable to create HCD\n");
1494 return -ENOMEM;
1495 }
1496
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301497 hcd_to_bus(hcd)->skip_resume = true;
1498
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301499 hcd->irq = platform_get_irq(pdev, 0);
1500 if (hcd->irq < 0) {
1501 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1502 ret = hcd->irq;
1503 goto put_hcd;
1504 }
1505
1506 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1507 if (!res) {
1508 dev_err(&pdev->dev, "Unable to get memory resource\n");
1509 ret = -ENODEV;
1510 goto put_hcd;
1511 }
1512
1513 hcd->rsrc_start = res->start;
1514 hcd->rsrc_len = resource_size(res);
1515 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1516 if (!hcd->regs) {
1517 dev_err(&pdev->dev, "ioremap failed\n");
1518 ret = -ENOMEM;
1519 goto put_hcd;
1520 }
1521
1522 mehci = hcd_to_hsic(hcd);
1523 mehci->dev = &pdev->dev;
Ajay Dudanic4e40db2012-08-20 14:44:40 -07001524 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301525
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001526 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001527 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001528
Hemant Kumare4040492012-06-21 17:35:42 -07001529 mehci->ehci.resume_sof_bug = 1;
1530
Ajay Dudanic4e40db2012-08-20 14:44:40 -07001531 if (pdata)
1532 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Hemant Kumar933e0402012-05-22 11:11:40 -07001533
Vamsi Krishna34f01582011-12-14 19:54:42 -08001534 res = platform_get_resource_byname(pdev,
1535 IORESOURCE_IRQ,
1536 "peripheral_status_irq");
1537 if (res)
1538 mehci->peripheral_status_irq = res->start;
1539
Hemant Kumar6fd65032012-05-23 13:02:24 -07001540 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
1541 if (res) {
1542 mehci->wakeup_gpio = res->start;
1543 mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
1544 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1545 }
1546
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301547 ret = msm_hsic_init_clocks(mehci, 1);
1548 if (ret) {
1549 dev_err(&pdev->dev, "unable to initialize clocks\n");
1550 ret = -ENODEV;
1551 goto unmap;
1552 }
1553
1554 ret = msm_hsic_init_vddcx(mehci, 1);
1555 if (ret) {
1556 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1557 ret = -ENODEV;
1558 goto deinit_clocks;
1559 }
1560
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001561 init_completion(&mehci->rt_completion);
1562 init_completion(&mehci->gpt0_completion);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301563 ret = msm_hsic_reset(mehci);
1564 if (ret) {
1565 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301566 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301567 }
1568
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001569 ehci_wq = create_singlethread_workqueue("ehci_wq");
1570 if (!ehci_wq) {
1571 dev_err(&pdev->dev, "unable to create workqueue\n");
1572 ret = -ENOMEM;
1573 goto deinit_vddcx;
1574 }
1575
1576 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1577
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301578 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1579 if (ret) {
1580 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301581 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301582 }
1583
1584 device_init_wakeup(&pdev->dev, 1);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001585 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1586 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001587
1588 if (mehci->peripheral_status_irq) {
1589 ret = request_threaded_irq(mehci->peripheral_status_irq,
1590 NULL, hsic_peripheral_status_change,
1591 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1592 | IRQF_SHARED,
1593 "hsic_peripheral_status", mehci);
1594 if (ret)
1595 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1596 __func__, mehci->peripheral_status_irq, ret);
1597 }
1598
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001599 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001600 if (mehci->wakeup_irq) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001601 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001602 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001603 "msm_hsic_wakeup", mehci);
1604 if (!ret) {
1605 disable_irq_nosync(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001606 } else {
1607 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1608 mehci->wakeup_irq, ret);
1609 mehci->wakeup_irq = 0;
1610 }
1611 }
1612
Hemant Kumare6275972012-02-29 20:06:21 -08001613 ret = ehci_hsic_msm_debugfs_init(mehci);
1614 if (ret)
1615 dev_dbg(&pdev->dev, "mode debugfs file is"
1616 "not available\n");
1617
1618 if (pdata && pdata->bus_scale_table) {
1619 mehci->bus_perf_client =
1620 msm_bus_scale_register_client(pdata->bus_scale_table);
1621 /* Configure BUS performance parameters for MAX bandwidth */
1622 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001623 mehci->bus_vote = true;
1624 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001625 } else {
1626 dev_err(&pdev->dev, "%s: Failed to register BUS "
1627 "scaling client!!\n", __func__);
1628 }
1629 }
1630
Hemant Kumar105d07f2012-07-02 15:33:07 -07001631 __mehci = mehci;
1632
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301633 /*
1634 * This pdev->dev is assigned parent of root-hub by USB core,
1635 * hence, runtime framework automatically calls this driver's
1636 * runtime APIs based on root-hub's state.
1637 */
1638 pm_runtime_set_active(&pdev->dev);
1639 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301640 /* Decrement the parent device's counter after probe.
1641 * As child is active, parent will not be put into
1642 * suspend mode.
1643 */
1644 if (pdev->dev.parent)
1645 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301646
1647 return 0;
1648
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301649unconfig_gpio:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001650 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301651 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301652deinit_vddcx:
1653 msm_hsic_init_vddcx(mehci, 0);
1654deinit_clocks:
1655 msm_hsic_init_clocks(mehci, 0);
1656unmap:
1657 iounmap(hcd->regs);
1658put_hcd:
1659 usb_put_hcd(hcd);
1660
1661 return ret;
1662}
1663
1664static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1665{
1666 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1667 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1668
Vamsi Krishna34f01582011-12-14 19:54:42 -08001669 if (mehci->peripheral_status_irq)
1670 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001671
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001672 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001673 if (mehci->wakeup_irq_enabled)
1674 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001675 free_irq(mehci->wakeup_irq, mehci);
1676 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001677
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001678 /*
1679 * If the update request is called after unregister, the request will
1680 * fail. Results are undefined if unregister is called in the middle of
1681 * update request.
1682 */
1683 mehci->bus_vote = false;
1684 cancel_work_sync(&mehci->bus_vote_w);
1685
Hemant Kumare6275972012-02-29 20:06:21 -08001686 if (mehci->bus_perf_client)
1687 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1688
1689 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301690 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301691 pm_runtime_set_suspended(&pdev->dev);
1692
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001693 destroy_workqueue(ehci_wq);
1694
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301695 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301696 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301697 msm_hsic_init_vddcx(mehci, 0);
1698
1699 msm_hsic_init_clocks(mehci, 0);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001700 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301701 iounmap(hcd->regs);
1702 usb_put_hcd(hcd);
1703
1704 return 0;
1705}
1706
1707#ifdef CONFIG_PM_SLEEP
1708static int msm_hsic_pm_suspend(struct device *dev)
1709{
Jack Phambe05fbb2012-05-16 10:56:26 -07001710 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301711 struct usb_hcd *hcd = dev_get_drvdata(dev);
1712 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1713
1714 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1715
Hemant Kumar45d211b2012-05-31 17:58:43 -07001716 dbg_log_event(NULL, "PM Suspend", 0);
1717
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301718 if (device_may_wakeup(dev))
1719 enable_irq_wake(hcd->irq);
1720
Jack Phambe05fbb2012-05-16 10:56:26 -07001721 ret = msm_hsic_suspend(mehci);
1722
1723 if (ret && device_may_wakeup(dev))
1724 disable_irq_wake(hcd->irq);
1725
1726 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001727}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301728
Jack Pham16b06f82012-08-14 20:03:59 -07001729static int msm_hsic_pm_suspend_noirq(struct device *dev)
1730{
1731 struct usb_hcd *hcd = dev_get_drvdata(dev);
1732 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1733
1734 if (mehci->async_int) {
1735 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
1736 return -EBUSY;
1737 }
1738
1739 return 0;
1740}
1741
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301742static int msm_hsic_pm_resume(struct device *dev)
1743{
1744 int ret;
1745 struct usb_hcd *hcd = dev_get_drvdata(dev);
1746 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1747
Jack Pham16b06f82012-08-14 20:03:59 -07001748 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001749 dbg_log_event(NULL, "PM Resume", 0);
1750
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301751 if (device_may_wakeup(dev))
1752 disable_irq_wake(hcd->irq);
1753
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301754 /*
1755 * Keep HSIC in Low Power Mode if system is resumed
1756 * by any other wakeup source. HSIC is resumed later
1757 * when remote wakeup is received or interface driver
1758 * start I/O.
1759 */
1760 if (!atomic_read(&mehci->pm_usage_cnt))
1761 return 0;
1762
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301763 ret = msm_hsic_resume(mehci);
1764 if (ret)
1765 return ret;
1766
1767 /* Bring the device to full powered state upon system resume */
1768 pm_runtime_disable(dev);
1769 pm_runtime_set_active(dev);
1770 pm_runtime_enable(dev);
1771
1772 return 0;
1773}
1774#endif
1775
1776#ifdef CONFIG_PM_RUNTIME
1777static int msm_hsic_runtime_idle(struct device *dev)
1778{
1779 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301780 return 0;
1781}
1782
1783static int msm_hsic_runtime_suspend(struct device *dev)
1784{
1785 struct usb_hcd *hcd = dev_get_drvdata(dev);
1786 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1787
1788 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001789
1790 dbg_log_event(NULL, "Run Time PM Suspend", 0);
1791
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301792 return msm_hsic_suspend(mehci);
1793}
1794
1795static int msm_hsic_runtime_resume(struct device *dev)
1796{
1797 struct usb_hcd *hcd = dev_get_drvdata(dev);
1798 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1799
1800 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001801
1802 dbg_log_event(NULL, "Run Time PM Resume", 0);
1803
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301804 return msm_hsic_resume(mehci);
1805}
1806#endif
1807
1808#ifdef CONFIG_PM
1809static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1810 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07001811 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301812 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1813 msm_hsic_runtime_idle)
1814};
1815#endif
1816
1817static struct platform_driver ehci_msm_hsic_driver = {
1818 .probe = ehci_hsic_msm_probe,
1819 .remove = __devexit_p(ehci_hsic_msm_remove),
1820 .driver = {
1821 .name = "msm_hsic_host",
1822#ifdef CONFIG_PM
1823 .pm = &msm_hsic_dev_pm_ops,
1824#endif
1825 },
1826};