blob: 188d5623b2805eeed144b04b8857a75526de3a49 [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>
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +053040#include <linux/pm_qos.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030041
42#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053043#include <mach/clk.h>
44#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053045#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080046#include <linux/spinlock.h>
Hemant Kumar45d211b2012-05-31 17:58:43 -070047#include <linux/cpu.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030048#include <mach/rpm-regulator.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053049
50#define MSM_USB_BASE (hcd->regs)
Hemant Kumar105d07f2012-07-02 15:33:07 -070051#define USB_REG_START_OFFSET 0x90
52#define USB_REG_END_OFFSET 0x250
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053053
Hemant Kumar2309eaa2012-08-14 16:46:42 -070054static struct workqueue_struct *ehci_wq;
Ajay Dudani11ab1d52012-08-17 17:12:26 -070055struct ehci_timer {
56#define GPT_LD(p) ((p) & 0x00FFFFFF)
57 u32 gptimer0_ld;
58#define GPT_RUN BIT(31)
59#define GPT_RESET BIT(30)
60#define GPT_MODE BIT(24)
61#define GPT_CNT(p) ((p) & 0x00FFFFFF)
62 u32 gptimer0_ctrl;
63
64 u32 gptimer1_ld;
65 u32 gptimer1_ctrl;
66};
Hemant Kumar2309eaa2012-08-14 16:46:42 -070067
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053068struct msm_hsic_hcd {
69 struct ehci_hcd ehci;
Hemant Kumar4cd49e12012-09-06 19:57:14 -070070 spinlock_t wakeup_lock;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053071 struct device *dev;
72 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080073 struct clk *core_clk;
74 struct clk *alt_core_clk;
75 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053076 struct clk *cal_clk;
77 struct regulator *hsic_vddcx;
Ajay Dudaniab3bf192012-08-28 09:58:04 -070078 bool async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053079 atomic_t in_lpm;
Ajay Dudaniab3bf192012-08-28 09:58:04 -070080 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080081 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080082 int wakeup_irq;
Hemant Kumar6fd65032012-05-23 13:02:24 -070083 int wakeup_gpio;
Jack Phamfe441ea2012-03-23 17:03:15 -070084 bool wakeup_irq_enabled;
Ajay Dudaniab3bf192012-08-28 09:58:04 -070085 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080086 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070087 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030088 enum usb_vdd_type vdd_type;
Hemant Kumar2309eaa2012-08-14 16:46:42 -070089
90 struct work_struct bus_vote_w;
91 bool bus_vote;
Ajay Dudani11ab1d52012-08-17 17:12:26 -070092
93 /* gp timer */
94 struct ehci_timer __iomem *timer;
95 struct completion gpt0_completion;
96 struct completion rt_completion;
97 int resume_status;
98 int resume_again;
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +053099
100 struct pm_qos_request pm_qos_req_dma;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530101};
102
Hemant Kumar105d07f2012-07-02 15:33:07 -0700103struct msm_hsic_hcd *__mehci;
104
Hemant Kumare6275972012-02-29 20:06:21 -0800105static bool debug_bus_voting_enabled = true;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700106
107static unsigned int enable_dbg_log = 1;
108module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
109/*by default log ep0 and efs sync ep*/
110static unsigned int ep_addr_rxdbg_mask = 9;
111module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
112static unsigned int ep_addr_txdbg_mask = 9;
113module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
114
115/* Maximum debug message length */
116#define DBG_MSG_LEN 100UL
117
118/* Maximum number of messages */
119#define DBG_MAX_MSG 256UL
120
121#define TIME_BUF_LEN 20
122
123enum event_type {
124 EVENT_UNDEF = -1,
125 URB_SUBMIT,
126 URB_COMPLETE,
127 EVENT_NONE,
128};
129
130#define EVENT_STR_LEN 5
131
132static char *event_to_str(enum event_type e)
133{
134 switch (e) {
135 case URB_SUBMIT:
136 return "S";
137 case URB_COMPLETE:
138 return "C";
139 case EVENT_NONE:
140 return "NONE";
141 default:
142 return "UNDEF";
143 }
144}
145
146static enum event_type str_to_event(const char *name)
147{
148 if (!strncasecmp("S", name, EVENT_STR_LEN))
149 return URB_SUBMIT;
150 if (!strncasecmp("C", name, EVENT_STR_LEN))
151 return URB_COMPLETE;
152 if (!strncasecmp("", name, EVENT_STR_LEN))
153 return EVENT_NONE;
154
155 return EVENT_UNDEF;
156}
157
158/*log ep0 activity*/
159static struct {
160 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
161 unsigned idx; /* index */
162 rwlock_t lck; /* lock */
163} dbg_hsic_ctrl = {
164 .idx = 0,
165 .lck = __RW_LOCK_UNLOCKED(lck)
166};
167
168static struct {
169 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
170 unsigned idx; /* index */
171 rwlock_t lck; /* lock */
172} dbg_hsic_data = {
173 .idx = 0,
174 .lck = __RW_LOCK_UNLOCKED(lck)
175};
176
177/**
178 * dbg_inc: increments debug event index
179 * @idx: buffer index
180 */
181static void dbg_inc(unsigned *idx)
182{
183 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
184}
185
186/*get_timestamp - returns time of day in us */
187static char *get_timestamp(char *tbuf)
188{
189 unsigned long long t;
190 unsigned long nanosec_rem;
191
192 t = cpu_clock(smp_processor_id());
193 nanosec_rem = do_div(t, 1000000000)/1000;
194 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
195 nanosec_rem);
196 return tbuf;
197}
198
199static int allow_dbg_log(int ep_addr)
200{
201 int dir, num;
202
203 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
204 num = ep_addr & ~USB_DIR_IN;
205 num = 1 << num;
206
207 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
208 return 1;
209 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
210 return 1;
211
212 return 0;
213}
214
215static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
216{
217 unsigned long flags;
218 int ep_addr;
219 char tbuf[TIME_BUF_LEN];
220
221 if (!enable_dbg_log)
222 return;
223
224 if (!urb) {
225 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
226 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
227 "%s: %s : %u\n", get_timestamp(tbuf), event, extra);
228 dbg_inc(&dbg_hsic_ctrl.idx);
229 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
230 return;
231 }
232
233 ep_addr = urb->ep->desc.bEndpointAddress;
234 if (!allow_dbg_log(ep_addr))
235 return;
236
237 if ((ep_addr & 0x0f) == 0x0) {
238 /*submit event*/
239 if (!str_to_event(event)) {
240 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
241 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
242 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
243 "%02x %02x %04x %04x %04x %u %d\n",
244 get_timestamp(tbuf), event, urb,
245 (ep_addr & USB_DIR_IN) ? "in" : "out",
246 urb->setup_packet[0], urb->setup_packet[1],
247 (urb->setup_packet[3] << 8) |
248 urb->setup_packet[2],
249 (urb->setup_packet[5] << 8) |
250 urb->setup_packet[4],
251 (urb->setup_packet[7] << 8) |
252 urb->setup_packet[6],
253 urb->transfer_buffer_length, urb->status);
254
255 dbg_inc(&dbg_hsic_ctrl.idx);
256 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
257 } else {
258 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
259 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
260 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d\n",
261 get_timestamp(tbuf), event, urb,
262 (ep_addr & USB_DIR_IN) ? "in" : "out",
263 urb->actual_length, extra);
264
265 dbg_inc(&dbg_hsic_ctrl.idx);
266 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
267 }
268 } else {
269 write_lock_irqsave(&dbg_hsic_data.lck, flags);
270 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
271 "%s: [%s : %p]:ep%d[%s] %u %d\n",
272 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
273 (ep_addr & USB_DIR_IN) ? "in" : "out",
274 str_to_event(event) ? urb->actual_length :
275 urb->transfer_buffer_length,
276 str_to_event(event) ? extra : urb->status);
277
278 dbg_inc(&dbg_hsic_data.idx);
279 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
280 }
281}
282
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530283static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
284{
285 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
286}
287
288static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
289{
290 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
291}
292
Hemant Kumar105d07f2012-07-02 15:33:07 -0700293static void dump_hsic_regs(struct usb_hcd *hcd)
294{
295 int i;
296 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
297
298 if (atomic_read(&mehci->in_lpm))
299 return;
300
301 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
302 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
303 readl_relaxed(hcd->regs + i),
304 readl_relaxed(hcd->regs + i + 4),
305 readl_relaxed(hcd->regs + i + 8),
306 readl_relaxed(hcd->regs + i + 0xc));
307}
308
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530309#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
310
Amit Blayd6ea6102012-06-07 16:26:24 +0300311#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700312#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
313#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530314
Lena Salman8c8ba382012-02-14 15:59:31 +0200315#define HSIC_DBG1_REG 0x38
316
Amit Blayd6ea6102012-06-07 16:26:24 +0300317static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
318 { /* VDD_CX CORNER Voting */
319 [VDD_NONE] = RPM_VREG_CORNER_NONE,
320 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
321 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
322 },
323 { /* VDD_CX Voltage Voting */
324 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
325 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
326 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
327 },
328};
329
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530330static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
331{
332 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300333 int none_vol, min_vol, max_vol;
334
335 if (!mehci->hsic_vddcx) {
336 mehci->vdd_type = VDDCX_CORNER;
337 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
338 "hsic_vdd_dig");
339 if (IS_ERR(mehci->hsic_vddcx)) {
340 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
341 "HSIC_VDDCX");
342 if (IS_ERR(mehci->hsic_vddcx)) {
343 dev_err(mehci->dev, "unable to get hsic vddcx\n");
344 return PTR_ERR(mehci->hsic_vddcx);
345 }
346 mehci->vdd_type = VDDCX;
347 }
348 }
349
350 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
351 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
352 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530353
354 if (!init)
355 goto disable_reg;
356
Amit Blayd6ea6102012-06-07 16:26:24 +0300357 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530358 if (ret) {
359 dev_err(mehci->dev, "unable to set the voltage"
360 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530361 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530362 }
363
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530364 ret = regulator_enable(mehci->hsic_vddcx);
365 if (ret) {
366 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
367 goto reg_enable_err;
368 }
369
370 return 0;
371
372disable_reg:
373 regulator_disable(mehci->hsic_vddcx);
374reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300375 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
376
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530377 return ret;
378
379}
380
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700381static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
382{
383 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Devin Kim01e5a5b2012-08-30 02:52:45 -0700384 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700385
386 /* initiate read operation */
387 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
388 USB_ULPI_VIEWPORT);
389
390 /* wait for completion */
Devin Kim01e5a5b2012-08-30 02:52:45 -0700391 while (cnt < ULPI_IO_TIMEOUT_USEC) {
392 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
393 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700394 udelay(1);
Devin Kim01e5a5b2012-08-30 02:52:45 -0700395 cnt++;
396 }
397
398 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
399 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
400 readl_relaxed(USB_ULPI_VIEWPORT));
401 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
402 readl_relaxed(USB_PORTSC),
403 readl_relaxed(USB_USBCMD),
404 readl_relaxed(USB_FRINDEX));
405
406 /*frame counter increments afte 125us*/
407 udelay(130);
408 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
409 readl_relaxed(USB_FRINDEX));
410 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700411 }
412
413 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
414}
415
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530416static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
417{
418 struct usb_hcd *hcd = hsic_to_hcd(mehci);
419 int cnt = 0;
420
421 /* initiate write operation */
422 writel_relaxed(ULPI_RUN | ULPI_WRITE |
423 ULPI_ADDR(reg) | ULPI_DATA(val),
424 USB_ULPI_VIEWPORT);
425
426 /* wait for completion */
427 while (cnt < ULPI_IO_TIMEOUT_USEC) {
428 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
429 break;
430 udelay(1);
431 cnt++;
432 }
433
434 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Devin Kim01e5a5b2012-08-30 02:52:45 -0700435 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
436 readl_relaxed(USB_ULPI_VIEWPORT));
437 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
438 readl_relaxed(USB_PORTSC),
439 readl_relaxed(USB_USBCMD),
440 readl_relaxed(USB_FRINDEX));
441
442 /*frame counter increments afte 125us*/
443 udelay(130);
444 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
445 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530446 return -ETIMEDOUT;
447 }
448
449 return 0;
450}
451
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700452#define HSIC_DBG1 0X38
453#define ULPI_MANUAL_ENABLE BIT(4)
454#define ULPI_LINESTATE_DATA BIT(5)
455#define ULPI_LINESTATE_STROBE BIT(6)
456static void ehci_msm_enable_ulpi_control(struct usb_hcd *hcd, u32 linestate)
457{
458 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
459 int val;
460
461 switch (linestate) {
462 case PORT_RESET:
463 val = ulpi_read(mehci, HSIC_DBG1);
464 val |= ULPI_MANUAL_ENABLE;
465 val &= ~(ULPI_LINESTATE_DATA | ULPI_LINESTATE_STROBE);
466 ulpi_write(mehci, val, HSIC_DBG1);
467 break;
468 default:
469 pr_info("%s: Unknown linestate:%0x\n", __func__, linestate);
470 }
471}
472
473static void ehci_msm_disable_ulpi_control(struct usb_hcd *hcd)
474{
475 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
476 int val;
477
478 val = ulpi_read(mehci, HSIC_DBG1);
479 val &= ~ULPI_MANUAL_ENABLE;
480 ulpi_write(mehci, val, HSIC_DBG1);
481}
482
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530483static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
484{
485 int rc = 0;
486 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800487 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530488
489 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800490
Lena Salman8c8ba382012-02-14 15:59:31 +0200491 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530492 return rc;
493
Vamsi Krishna34f01582011-12-14 19:54:42 -0800494 if (gpio_status == gpio_en)
495 return 0;
496
497 gpio_status = gpio_en;
498
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530499 if (!gpio_en)
500 goto free_gpio;
501
502 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
503 if (rc < 0) {
504 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
505 return rc;
506 }
507
508 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
509 if (rc < 0) {
510 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
511 goto free_strobe;
512 }
513
Hemant Kumar6fd65032012-05-23 13:02:24 -0700514 if (mehci->wakeup_gpio) {
515 rc = gpio_request(mehci->wakeup_gpio, "HSIC_WAKEUP_GPIO");
516 if (rc < 0) {
517 dev_err(mehci->dev, "gpio request failed for HSIC WAKEUP\n");
518 goto free_data;
519 }
520 }
521
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530522 return 0;
523
524free_gpio:
Hemant Kumar6fd65032012-05-23 13:02:24 -0700525 if (mehci->wakeup_gpio)
526 gpio_free(mehci->wakeup_gpio);
527free_data:
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530528 gpio_free(pdata->data);
529free_strobe:
530 gpio_free(pdata->strobe);
531
532 return rc;
533}
534
Vamsi Krishna64b48612012-06-14 16:08:11 -0700535static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530536{
537 int ret;
538
Manu Gautam5143b252012-01-05 19:25:23 -0800539 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530540 if (ret) {
Vamsi Krishna64b48612012-06-14 16:08:11 -0700541 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
542 return;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530543 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700544 clk_disable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530545
Manu Gautam5143b252012-01-05 19:25:23 -0800546 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530547 if (ret)
Vamsi Krishna64b48612012-06-14 16:08:11 -0700548 dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530549
Vamsi Krishna64b48612012-06-14 16:08:11 -0700550 usleep_range(10000, 12000);
551
552 clk_enable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530553}
554
Vamsi Krishna64b48612012-06-14 16:08:11 -0700555#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
556#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530557#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
558#define HSIC_LV_MODE 0x04
559#define HSIC_PAD_CALIBRATION 0xA8
560#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530561#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
562static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
563{
564 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530565 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200566 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530567
Vamsi Krishna64b48612012-06-14 16:08:11 -0700568 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530569
Vamsi Krishna64b48612012-06-14 16:08:11 -0700570 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530571 writel_relaxed(0x80000000, USB_PORTSC);
572
Vamsi Krishna64b48612012-06-14 16:08:11 -0700573 mb();
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530574
Lena Salman8c8ba382012-02-14 15:59:31 +0200575 /* HSIC init sequence when HSIC signals (Strobe/Data) are
576 routed via GPIOs */
577 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530578
Lena Salman8c8ba382012-02-14 15:59:31 +0200579 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
580 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530581
Vamsi Krishna64b48612012-06-14 16:08:11 -0700582 mb();
583
Lena Salman8c8ba382012-02-14 15:59:31 +0200584 /*set periodic calibration interval to ~2.048sec in
585 HSIC_IO_CAL_REG */
586 ulpi_write(mehci, 0xFF, 0x33);
587
588 /* Enable periodic IO calibration in HSIC_CFG register */
589 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
590
Vamsi Krishna64b48612012-06-14 16:08:11 -0700591 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200592 ret = msm_hsic_config_gpios(mehci, 1);
593 if (ret) {
594 dev_err(mehci->dev, " gpio configuarion failed\n");
595 return ret;
596 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700597 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO PAD_CTL register */
598 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_STROBE_GPIO_PAD_CTL);
599 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_DATA_GPIO_PAD_CTL);
600
601 mb();
602
Lena Salman8c8ba382012-02-14 15:59:31 +0200603 /* Enable HSIC mode in HSIC_CFG register */
604 ulpi_write(mehci, 0x01, 0x31);
605 } else {
606 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
607 via dedicated I/O */
608
609 /* programmable length of connect signaling (33.2ns) */
610 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
611 if (ret) {
612 pr_err("%s: Unable to program length of connect "
613 "signaling\n", __func__);
614 }
615
616 /*set periodic calibration interval to ~2.048sec in
617 HSIC_IO_CAL_REG */
618 ulpi_write(mehci, 0xFF, 0x33);
619
620 /* Enable HSIC mode in HSIC_CFG register */
621 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530622 }
623
Hemant Kumar6fd65032012-05-23 13:02:24 -0700624 /*disable auto resume*/
625 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
626
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530627 return 0;
628}
629
630#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
631#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
632
633#ifdef CONFIG_PM_SLEEP
634static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
635{
636 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530637 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530638 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300639 int none_vol, max_vol;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530640
641 if (atomic_read(&mehci->in_lpm)) {
642 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
643 return 0;
644 }
645
Hemant Kumar7f374632012-05-31 20:10:32 -0700646 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
647 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
648 __func__);
649 return -EAGAIN;
650 }
651
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530652 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700653
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700654 /* make sure we don't race against a remote wakeup */
655 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700656 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700657 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700658 enable_irq(hcd->irq);
659 return -EBUSY;
660 }
661
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530662 /*
663 * PHY may take some time or even fail to enter into low power
664 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
665 * in failure case.
666 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700667 val = readl_relaxed(USB_PORTSC);
668 val &= ~PORT_RWC_BITS;
669 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530670 writel_relaxed(val, USB_PORTSC);
671 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
672 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
673 break;
674 udelay(1);
675 cnt++;
676 }
677
678 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
679 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530680 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530681 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530682 }
683
684 /*
685 * PHY has capability to generate interrupt asynchronously in low
686 * power mode (LPM). This interrupt is level triggered. So USB IRQ
687 * line must be disabled till async interrupt enable bit is cleared
688 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
689 * block data communication from PHY.
690 */
691 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
692 ULPI_STP_CTRL, USB_USBCMD);
693
694 /*
695 * Ensure that hardware is put in low power mode before
696 * clocks are turned OFF and VDD is allowed to minimize.
697 */
698 mb();
699
Manu Gautam28b1bac2012-01-30 16:43:06 +0530700 clk_disable_unprepare(mehci->core_clk);
701 clk_disable_unprepare(mehci->phy_clk);
702 clk_disable_unprepare(mehci->cal_clk);
703 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530704
Amit Blayd6ea6102012-06-07 16:26:24 +0300705 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
706 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
707
708 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700709 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300710 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700711
Hemant Kumare6275972012-02-29 20:06:21 -0800712 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700713 mehci->bus_vote = false;
714 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800715 }
716
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530717 atomic_set(&mehci->in_lpm, 1);
718 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700719
720 mehci->wakeup_irq_enabled = 1;
721 enable_irq_wake(mehci->wakeup_irq);
722 enable_irq(mehci->wakeup_irq);
723
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700724 wake_unlock(&mehci->wlock);
725
Devin Kim476bbd72012-07-19 18:11:11 -0700726 dev_dbg(mehci->dev, "HSIC-USB in low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530727
728 return 0;
729}
730
731static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
732{
733 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530734 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530735 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300736 int min_vol, max_vol;
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700737 unsigned long flags;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530738
739 if (!atomic_read(&mehci->in_lpm)) {
740 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
741 return 0;
742 }
743
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700744 spin_lock_irqsave(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700745 if (mehci->wakeup_irq_enabled) {
746 disable_irq_wake(mehci->wakeup_irq);
747 disable_irq_nosync(mehci->wakeup_irq);
748 mehci->wakeup_irq_enabled = 0;
749 }
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700750 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700751
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700752 wake_lock(&mehci->wlock);
753
Hemant Kumare6275972012-02-29 20:06:21 -0800754 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700755 mehci->bus_vote = true;
756 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800757 }
758
Amit Blayd6ea6102012-06-07 16:26:24 +0300759 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
760 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
761
762 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700763 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300764 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700765
Manu Gautam28b1bac2012-01-30 16:43:06 +0530766 clk_prepare_enable(mehci->core_clk);
767 clk_prepare_enable(mehci->phy_clk);
768 clk_prepare_enable(mehci->cal_clk);
769 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530770
771 temp = readl_relaxed(USB_USBCMD);
772 temp &= ~ASYNC_INTR_CTRL;
773 temp &= ~ULPI_STP_CTRL;
774 writel_relaxed(temp, USB_USBCMD);
775
776 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
777 goto skip_phy_resume;
778
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700779 temp = readl_relaxed(USB_PORTSC);
780 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530781 writel_relaxed(temp, USB_PORTSC);
782 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
783 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
784 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
785 break;
786 udelay(1);
787 cnt++;
788 }
789
790 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
791 /*
792 * This is a fatal error. Reset the link and
793 * PHY to make hsic working.
794 */
795 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530796 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530797 msm_hsic_reset(mehci);
798 }
799
800skip_phy_resume:
801
Hemant Kumar6fd65032012-05-23 13:02:24 -0700802 usb_hcd_resume_root_hub(hcd);
803
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530804 atomic_set(&mehci->in_lpm, 0);
805
806 if (mehci->async_int) {
807 mehci->async_int = false;
808 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700809 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700810 }
811
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700812 if (atomic_read(&mehci->pm_usage_cnt)) {
813 atomic_set(&mehci->pm_usage_cnt, 0);
814 pm_runtime_put_noidle(mehci->dev);
815 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700816
Devin Kim476bbd72012-07-19 18:11:11 -0700817 dev_dbg(mehci->dev, "HSIC-USB exited from low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530818
819 return 0;
820}
821#endif
822
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700823static void ehci_hsic_bus_vote_w(struct work_struct *w)
824{
825 struct msm_hsic_hcd *mehci =
826 container_of(w, struct msm_hsic_hcd, bus_vote_w);
827 int ret;
828
829 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
830 mehci->bus_vote);
831 if (ret)
832 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
833 __func__, ret);
834}
835
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700836#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530837static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
838{
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700839 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530840 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700841 u32 status;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530842
843 if (atomic_read(&mehci->in_lpm)) {
844 disable_irq_nosync(hcd->irq);
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700845 dev_dbg(mehci->dev, "phy async intr\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530846 mehci->async_int = true;
847 pm_runtime_get(mehci->dev);
848 return IRQ_HANDLED;
849 }
850
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700851 status = ehci_readl(ehci, &ehci->regs->status);
852
853 if (status & STS_GPTIMER0_INTERRUPT) {
854 int timeleft;
855
856 dbg_log_event(NULL, "FPR: gpt0_isr", 0);
857
858 timeleft = GPT_CNT(ehci_readl(ehci,
859 &mehci->timer->gptimer1_ctrl));
860 if (timeleft) {
861 ehci_writel(ehci, ehci_readl(ehci,
862 &ehci->regs->command) | CMD_RUN,
863 &ehci->regs->command);
864 } else
865 mehci->resume_again = 1;
866
867 dbg_log_event(NULL, "FPR: timeleft", timeleft);
868
869 complete(&mehci->gpt0_completion);
870 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
871 }
872
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530873 return ehci_irq(hcd);
874}
875
876static int ehci_hsic_reset(struct usb_hcd *hcd)
877{
878 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700879 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530880 int retval;
881
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700882 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530883 ehci->caps = USB_CAPLENGTH;
884 ehci->regs = USB_CAPLENGTH +
885 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
886 dbg_hcs_params(ehci, "reset");
887 dbg_hcc_params(ehci, "reset");
888
889 /* cache the data to minimize the chip reads*/
890 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
891
892 hcd->has_tt = 1;
893 ehci->sbrn = HCD_USB2;
894
895 retval = ehci_halt(ehci);
896 if (retval)
897 return retval;
898
899 /* data structure init */
900 retval = ehci_init(hcd);
901 if (retval)
902 return retval;
903
904 retval = ehci_reset(ehci);
905 if (retval)
906 return retval;
907
908 /* bursts of unspecified length. */
909 writel_relaxed(0, USB_AHBBURST);
910 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530911 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530912 /* Disable streaming mode and select host mode */
913 writel_relaxed(0x13, USB_USBMODE);
914
915 ehci_port_power(ehci, 1);
916 return 0;
917}
918
Hemant Kumar45d211b2012-05-31 17:58:43 -0700919static int ehci_hsic_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
920 gfp_t mem_flags)
921{
922 dbg_log_event(urb, event_to_str(URB_SUBMIT), 0);
923 return ehci_urb_enqueue(hcd, urb, mem_flags);
924}
925
926static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
927{
928 dbg_log_event(NULL, "Suspend RH", 0);
929 return ehci_bus_suspend(hcd);
930}
931
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700932#define RESUME_RETRY_LIMIT 3
933#define RESUME_SIGNAL_TIME_MS (21 * 999)
934#define RESUME_SIGNAL_TIME_SOF_MS (23 * 999)
935static int msm_hsic_resume_thread(void *data)
936{
937 struct msm_hsic_hcd *mehci = data;
938 struct usb_hcd *hcd = hsic_to_hcd(mehci);
939 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
940 u32 temp;
941 unsigned long resume_needed = 0;
942 int retry_cnt = 0;
943 int tight_resume = 0;
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +0530944 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700945
946 dbg_log_event(NULL, "Resume RH", 0);
947
948 /* keep delay between bus states */
949 if (time_before(jiffies, ehci->next_statechange))
950 usleep_range(5000, 5000);
951
952 spin_lock_irq(&ehci->lock);
953 if (!HCD_HW_ACCESSIBLE(hcd)) {
954 spin_unlock_irq(&ehci->lock);
955 mehci->resume_status = -ESHUTDOWN;
956 complete(&mehci->rt_completion);
957 return 0;
958 }
959
960 if (unlikely(ehci->debug)) {
961 if (!dbgp_reset_prep())
962 ehci->debug = NULL;
963 else
964 dbgp_external_startup();
965 }
966
967 /* at least some APM implementations will try to deliver
968 * IRQs right away, so delay them until we're ready.
969 */
970 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
971
972 /* re-init operational registers */
973 ehci_writel(ehci, 0, &ehci->regs->segment);
974 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
975 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
976
977 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
978 if (ehci->resume_sof_bug)
979 ehci->command &= ~CMD_RUN;
980
981 /* restore CMD_RUN, framelist size, and irq threshold */
982 ehci_writel(ehci, ehci->command, &ehci->regs->command);
983
984 /* manually resume the ports we suspended during bus_suspend() */
985resume_again:
986 if (retry_cnt >= RESUME_RETRY_LIMIT) {
987 pr_info("retry count(%d) reached max, resume in tight loop\n",
988 retry_cnt);
989 tight_resume = 1;
990 }
991
992
993 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
994 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
995 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
996 temp |= PORT_RESUME;
997 set_bit(0, &resume_needed);
998 }
999 dbg_log_event(NULL, "FPR: Set", temp);
1000 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1001
1002 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1003 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1004 * controller in MSM clears FPR bit after driving the resume signal for
1005 * 20ms. Workaround is to stop SOFs before driving resume and then start
1006 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1007 * completion otherwise peripheral may enter undefined state. As
1008 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1009 * to time the resume sequence. If driver exceeds allowable time SOFs,
1010 * repeat the resume process.
1011 */
1012 if (ehci->resume_sof_bug && resume_needed) {
1013 if (!tight_resume) {
1014 mehci->resume_again = 0;
1015 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_MS),
1016 &mehci->timer->gptimer0_ld);
1017 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1018 &mehci->timer->gptimer0_ctrl);
1019 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1020 &ehci->regs->intr_enable);
1021
1022 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_SOF_MS),
1023 &mehci->timer->gptimer1_ld);
1024 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1025 &mehci->timer->gptimer1_ctrl);
1026
1027 spin_unlock_irq(&ehci->lock);
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301028 if (pdata && pdata->swfi_latency)
1029 pm_qos_update_request(&mehci->pm_qos_req_dma,
1030 pdata->swfi_latency + 1);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001031 wait_for_completion(&mehci->gpt0_completion);
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301032 if (pdata && pdata->swfi_latency)
1033 pm_qos_update_request(&mehci->pm_qos_req_dma,
1034 PM_QOS_DEFAULT_VALUE);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001035 spin_lock_irq(&ehci->lock);
1036 } else {
1037 dbg_log_event(NULL, "FPR: Tightloop", 0);
1038 /* do the resume in a tight loop */
1039 handshake(ehci, &ehci->regs->port_status[0],
1040 PORT_RESUME, 0, 22 * 1000);
1041 ehci_writel(ehci, ehci_readl(ehci,
1042 &ehci->regs->command) | CMD_RUN,
1043 &ehci->regs->command);
1044 }
1045
1046 if (mehci->resume_again) {
1047 int temp;
1048
1049 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1050 pr_info("FPR: retry count: %d\n", retry_cnt);
1051 spin_unlock_irq(&ehci->lock);
1052 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1053 temp &= ~PORT_RWC_BITS;
1054 temp |= PORT_SUSPEND;
1055 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1056 /* Keep the bus idle for 5ms so that peripheral
1057 * can detect and initiate suspend
1058 */
1059 usleep_range(5000, 5000);
1060 dbg_log_event(NULL,
1061 "FPR: RResume",
1062 ehci_readl(ehci, &ehci->regs->port_status[0]));
1063 spin_lock_irq(&ehci->lock);
1064 mehci->resume_again = 0;
1065 retry_cnt++;
1066 goto resume_again;
1067 }
1068 }
1069
1070 dbg_log_event(NULL, "FPR: RT-Done", 0);
1071 mehci->resume_status = 1;
1072 spin_unlock_irq(&ehci->lock);
1073
1074 complete(&mehci->rt_completion);
1075
1076 return 0;
1077}
1078
Hemant Kumar45d211b2012-05-31 17:58:43 -07001079static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1080{
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001081 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1082 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1083 u32 temp;
1084 struct task_struct *resume_thread = NULL;
1085
1086 mehci->resume_status = 0;
1087 resume_thread = kthread_run(msm_hsic_resume_thread,
1088 mehci, "hsic_resume_thread");
1089 if (IS_ERR(resume_thread)) {
1090 pr_err("Error creating resume thread:%lu\n",
1091 PTR_ERR(resume_thread));
1092 return PTR_ERR(resume_thread);
1093 }
1094
1095 wait_for_completion(&mehci->rt_completion);
1096
1097 if (mehci->resume_status < 0)
1098 return mehci->resume_status;
1099
1100 dbg_log_event(NULL, "FPR: Wokeup", 0);
1101 spin_lock_irq(&ehci->lock);
1102 (void) ehci_readl(ehci, &ehci->regs->command);
1103
1104 temp = 0;
1105 if (ehci->async->qh_next.qh)
1106 temp |= CMD_ASE;
1107 if (ehci->periodic_sched)
1108 temp |= CMD_PSE;
1109 if (temp) {
1110 ehci->command |= temp;
1111 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1112 }
1113
1114 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1115 hcd->state = HC_STATE_RUNNING;
1116 ehci->rh_state = EHCI_RH_RUNNING;
1117
1118 /* Now we can safely re-enable irqs */
1119 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1120
1121 spin_unlock_irq(&ehci->lock);
1122
1123 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001124}
1125
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301126static struct hc_driver msm_hsic_driver = {
1127 .description = hcd_name,
1128 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1129 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1130
1131 /*
1132 * generic hardware linkage
1133 */
1134 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001135 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301136
1137 .reset = ehci_hsic_reset,
1138 .start = ehci_run,
1139
1140 .stop = ehci_stop,
1141 .shutdown = ehci_shutdown,
1142
1143 /*
1144 * managing i/o requests and associated device resources
1145 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001146 .urb_enqueue = ehci_hsic_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301147 .urb_dequeue = ehci_urb_dequeue,
1148 .endpoint_disable = ehci_endpoint_disable,
1149 .endpoint_reset = ehci_endpoint_reset,
1150 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1151
1152 /*
1153 * scheduling support
1154 */
1155 .get_frame_number = ehci_get_frame,
1156
1157 /*
1158 * root hub support
1159 */
1160 .hub_status_data = ehci_hub_status_data,
1161 .hub_control = ehci_hub_control,
1162 .relinquish_port = ehci_relinquish_port,
1163 .port_handed_over = ehci_port_handed_over,
1164
1165 /*
1166 * PM support
1167 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001168 .bus_suspend = ehci_hsic_bus_suspend,
1169 .bus_resume = ehci_hsic_bus_resume,
1170
1171 .log_urb_complete = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001172 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001173
1174 .enable_ulpi_control = ehci_msm_enable_ulpi_control,
1175 .disable_ulpi_control = ehci_msm_disable_ulpi_control,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301176};
1177
1178static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1179{
1180 int ret = 0;
1181
1182 if (!init)
1183 goto put_clocks;
1184
Lena Salman8c8ba382012-02-14 15:59:31 +02001185 /*core_clk is required for LINK protocol engine
1186 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001187 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1188 if (IS_ERR(mehci->core_clk)) {
1189 dev_err(mehci->dev, "failed to get core_clk\n");
1190 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301191 return ret;
1192 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301193
Lena Salman8c8ba382012-02-14 15:59:31 +02001194 /* alt_core_clk is for LINK to be used during PHY RESET
1195 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001196 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
1197 if (IS_ERR(mehci->alt_core_clk)) {
1198 dev_err(mehci->dev, "failed to core_clk\n");
1199 ret = PTR_ERR(mehci->alt_core_clk);
1200 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301201 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301202
Lena Salman8c8ba382012-02-14 15:59:31 +02001203 /* phy_clk is required for HSIC PHY operation
1204 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001205 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1206 if (IS_ERR(mehci->phy_clk)) {
1207 dev_err(mehci->dev, "failed to get phy_clk\n");
1208 ret = PTR_ERR(mehci->phy_clk);
1209 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301210 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301211
1212 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001213 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301214 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001215 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301216 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001217 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301218 }
1219 clk_set_rate(mehci->cal_clk, 10000000);
1220
1221 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001222 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301223 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001224 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301225 ret = PTR_ERR(mehci->ahb_clk);
1226 goto put_cal_clk;
1227 }
1228
Manu Gautam28b1bac2012-01-30 16:43:06 +05301229 clk_prepare_enable(mehci->core_clk);
1230 clk_prepare_enable(mehci->phy_clk);
1231 clk_prepare_enable(mehci->cal_clk);
1232 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301233
1234 return 0;
1235
1236put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001237 if (!atomic_read(&mehci->in_lpm)) {
1238 clk_disable_unprepare(mehci->core_clk);
1239 clk_disable_unprepare(mehci->phy_clk);
1240 clk_disable_unprepare(mehci->cal_clk);
1241 clk_disable_unprepare(mehci->ahb_clk);
1242 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301243 clk_put(mehci->ahb_clk);
1244put_cal_clk:
1245 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001246put_phy_clk:
1247 clk_put(mehci->phy_clk);
1248put_alt_core_clk:
1249 clk_put(mehci->alt_core_clk);
1250put_core_clk:
1251 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301252
1253 return ret;
1254}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001255static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1256{
1257 struct msm_hsic_hcd *mehci = dev_id;
1258
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001259 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001260
1261 if (mehci)
1262 msm_hsic_config_gpios(mehci, 0);
1263
1264 return IRQ_HANDLED;
1265}
1266
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001267static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1268{
1269 struct msm_hsic_hcd *mehci = data;
1270
Hemant Kumar6fd65032012-05-23 13:02:24 -07001271 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001272 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001273 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
1274 __func__, mehci->wakeup_int_cnt);
1275
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001276 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001277
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001278 spin_lock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001279 if (mehci->wakeup_irq_enabled) {
1280 mehci->wakeup_irq_enabled = 0;
1281 disable_irq_wake(irq);
1282 disable_irq_nosync(irq);
1283 }
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001284 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001285
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001286 if (!atomic_read(&mehci->pm_usage_cnt)) {
1287 atomic_set(&mehci->pm_usage_cnt, 1);
1288 pm_runtime_get(mehci->dev);
1289 }
1290
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001291 return IRQ_HANDLED;
1292}
1293
Hemant Kumare6275972012-02-29 20:06:21 -08001294static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1295{
1296 if (debug_bus_voting_enabled)
1297 seq_printf(s, "enabled\n");
1298 else
1299 seq_printf(s, "disabled\n");
1300
1301 return 0;
1302}
1303
1304static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1305{
1306 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1307}
1308
1309static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1310 const char __user *ubuf, size_t count, loff_t *ppos)
1311{
1312 char buf[8];
1313 int ret;
1314 struct seq_file *s = file->private_data;
1315 struct msm_hsic_hcd *mehci = s->private;
1316
1317 memset(buf, 0x00, sizeof(buf));
1318
1319 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1320 return -EFAULT;
1321
1322 if (!strncmp(buf, "enable", 6)) {
1323 /* Do not vote here. Let hsic driver decide when to vote */
1324 debug_bus_voting_enabled = true;
1325 } else {
1326 debug_bus_voting_enabled = false;
1327 if (mehci->bus_perf_client) {
1328 ret = msm_bus_scale_client_update_request(
1329 mehci->bus_perf_client, 0);
1330 if (ret)
1331 dev_err(mehci->dev, "%s: Failed to devote "
1332 "for bus bw %d\n", __func__, ret);
1333 }
1334 }
1335
1336 return count;
1337}
1338
1339const struct file_operations ehci_hsic_msm_bus_fops = {
1340 .open = ehci_hsic_msm_bus_open,
1341 .read = seq_read,
1342 .write = ehci_hsic_msm_bus_write,
1343 .llseek = seq_lseek,
1344 .release = single_release,
1345};
1346
Hemant Kumar6fd65032012-05-23 13:02:24 -07001347static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1348{
1349 struct msm_hsic_hcd *mehci = s->private;
1350
1351 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1352
1353 return 0;
1354}
1355
1356static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1357{
1358 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1359}
1360
1361const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1362 .open = ehci_hsic_msm_wakeup_cnt_open,
1363 .read = seq_read,
1364 .llseek = seq_lseek,
1365 .release = single_release,
1366};
1367
Hemant Kumar45d211b2012-05-31 17:58:43 -07001368static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1369{
1370 unsigned long flags;
1371 unsigned i;
1372
1373 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1374
1375 i = dbg_hsic_data.idx;
1376 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1377 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1378 continue;
1379 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1380 }
1381
1382 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1383
1384 return 0;
1385}
1386
1387static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1388{
1389 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1390}
1391
1392const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1393 .open = ehci_hsic_msm_data_events_open,
1394 .read = seq_read,
1395 .llseek = seq_lseek,
1396 .release = single_release,
1397};
1398
1399static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1400{
1401 unsigned long flags;
1402 unsigned i;
1403
1404 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1405
1406 i = dbg_hsic_ctrl.idx;
1407 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1408 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1409 continue;
1410 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1411 }
1412
1413 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1414
1415 return 0;
1416}
1417
1418static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1419{
1420 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1421}
1422
1423const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1424 .open = ehci_hsic_msm_ctrl_events_open,
1425 .read = seq_read,
1426 .llseek = seq_lseek,
1427 .release = single_release,
1428};
1429
Hemant Kumare6275972012-02-29 20:06:21 -08001430static struct dentry *ehci_hsic_msm_dbg_root;
1431static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1432{
1433 struct dentry *ehci_hsic_msm_dentry;
1434
1435 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1436
1437 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1438 return -ENODEV;
1439
1440 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1441 S_IRUGO | S_IWUSR,
1442 ehci_hsic_msm_dbg_root, mehci,
1443 &ehci_hsic_msm_bus_fops);
1444
1445 if (!ehci_hsic_msm_dentry) {
1446 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1447 return -ENODEV;
1448 }
1449
Hemant Kumar6fd65032012-05-23 13:02:24 -07001450 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1451 S_IRUGO,
1452 ehci_hsic_msm_dbg_root, mehci,
1453 &ehci_hsic_msm_wakeup_cnt_fops);
1454
1455 if (!ehci_hsic_msm_dentry) {
1456 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1457 return -ENODEV;
1458 }
1459
Hemant Kumar45d211b2012-05-31 17:58:43 -07001460 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1461 S_IRUGO,
1462 ehci_hsic_msm_dbg_root, mehci,
1463 &ehci_hsic_msm_dbg_ctrl_fops);
1464
1465 if (!ehci_hsic_msm_dentry) {
1466 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1467 return -ENODEV;
1468 }
1469
1470 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1471 S_IRUGO,
1472 ehci_hsic_msm_dbg_root, mehci,
1473 &ehci_hsic_msm_dbg_data_fops);
1474
1475 if (!ehci_hsic_msm_dentry) {
1476 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1477 return -ENODEV;
1478 }
1479
Hemant Kumare6275972012-02-29 20:06:21 -08001480 return 0;
1481}
1482
1483static void ehci_hsic_msm_debugfs_cleanup(void)
1484{
1485 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1486}
1487
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301488static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1489{
1490 struct usb_hcd *hcd;
1491 struct resource *res;
1492 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301493 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301494 int ret;
1495
1496 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1497
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301498 /* After parent device's probe is executed, it will be put in suspend
1499 * mode. When child device's probe is called, driver core is not
1500 * resuming parent device due to which parent will be in suspend even
1501 * though child is active. Hence resume the parent device explicitly.
1502 */
1503 if (pdev->dev.parent)
1504 pm_runtime_get_sync(pdev->dev.parent);
1505
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301506 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1507 dev_name(&pdev->dev));
1508 if (!hcd) {
1509 dev_err(&pdev->dev, "Unable to create HCD\n");
1510 return -ENOMEM;
1511 }
1512
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301513 hcd_to_bus(hcd)->skip_resume = true;
1514
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301515 hcd->irq = platform_get_irq(pdev, 0);
1516 if (hcd->irq < 0) {
1517 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1518 ret = hcd->irq;
1519 goto put_hcd;
1520 }
1521
1522 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1523 if (!res) {
1524 dev_err(&pdev->dev, "Unable to get memory resource\n");
1525 ret = -ENODEV;
1526 goto put_hcd;
1527 }
1528
1529 hcd->rsrc_start = res->start;
1530 hcd->rsrc_len = resource_size(res);
1531 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1532 if (!hcd->regs) {
1533 dev_err(&pdev->dev, "ioremap failed\n");
1534 ret = -ENOMEM;
1535 goto put_hcd;
1536 }
1537
1538 mehci = hcd_to_hsic(hcd);
1539 mehci->dev = &pdev->dev;
Ajay Dudanic4e40db2012-08-20 14:44:40 -07001540 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301541
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001542 spin_lock_init(&mehci->wakeup_lock);
1543
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001544 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001545 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001546
Hemant Kumare4040492012-06-21 17:35:42 -07001547 mehci->ehci.resume_sof_bug = 1;
1548
Ajay Dudanic4e40db2012-08-20 14:44:40 -07001549 if (pdata)
1550 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Hemant Kumar933e0402012-05-22 11:11:40 -07001551
Vamsi Krishna34f01582011-12-14 19:54:42 -08001552 res = platform_get_resource_byname(pdev,
1553 IORESOURCE_IRQ,
1554 "peripheral_status_irq");
1555 if (res)
1556 mehci->peripheral_status_irq = res->start;
1557
Hemant Kumar6fd65032012-05-23 13:02:24 -07001558 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
1559 if (res) {
1560 mehci->wakeup_gpio = res->start;
1561 mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
1562 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1563 }
1564
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301565 ret = msm_hsic_init_clocks(mehci, 1);
1566 if (ret) {
1567 dev_err(&pdev->dev, "unable to initialize clocks\n");
1568 ret = -ENODEV;
1569 goto unmap;
1570 }
1571
1572 ret = msm_hsic_init_vddcx(mehci, 1);
1573 if (ret) {
1574 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1575 ret = -ENODEV;
1576 goto deinit_clocks;
1577 }
1578
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001579 init_completion(&mehci->rt_completion);
1580 init_completion(&mehci->gpt0_completion);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301581 ret = msm_hsic_reset(mehci);
1582 if (ret) {
1583 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301584 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301585 }
1586
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001587 ehci_wq = create_singlethread_workqueue("ehci_wq");
1588 if (!ehci_wq) {
1589 dev_err(&pdev->dev, "unable to create workqueue\n");
1590 ret = -ENOMEM;
1591 goto deinit_vddcx;
1592 }
1593
1594 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1595
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301596 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1597 if (ret) {
1598 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301599 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301600 }
1601
1602 device_init_wakeup(&pdev->dev, 1);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001603 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1604 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001605
1606 if (mehci->peripheral_status_irq) {
1607 ret = request_threaded_irq(mehci->peripheral_status_irq,
1608 NULL, hsic_peripheral_status_change,
1609 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1610 | IRQF_SHARED,
1611 "hsic_peripheral_status", mehci);
1612 if (ret)
1613 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1614 __func__, mehci->peripheral_status_irq, ret);
1615 }
1616
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001617 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001618 if (mehci->wakeup_irq) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001619 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001620 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001621 "msm_hsic_wakeup", mehci);
1622 if (!ret) {
1623 disable_irq_nosync(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001624 } else {
1625 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1626 mehci->wakeup_irq, ret);
1627 mehci->wakeup_irq = 0;
1628 }
1629 }
1630
Hemant Kumare6275972012-02-29 20:06:21 -08001631 ret = ehci_hsic_msm_debugfs_init(mehci);
1632 if (ret)
1633 dev_dbg(&pdev->dev, "mode debugfs file is"
1634 "not available\n");
1635
1636 if (pdata && pdata->bus_scale_table) {
1637 mehci->bus_perf_client =
1638 msm_bus_scale_register_client(pdata->bus_scale_table);
1639 /* Configure BUS performance parameters for MAX bandwidth */
1640 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001641 mehci->bus_vote = true;
1642 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001643 } else {
1644 dev_err(&pdev->dev, "%s: Failed to register BUS "
1645 "scaling client!!\n", __func__);
1646 }
1647 }
1648
Hemant Kumar105d07f2012-07-02 15:33:07 -07001649 __mehci = mehci;
1650
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301651 if (pdata && pdata->swfi_latency)
1652 pm_qos_add_request(&mehci->pm_qos_req_dma,
1653 PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
1654
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301655 /*
1656 * This pdev->dev is assigned parent of root-hub by USB core,
1657 * hence, runtime framework automatically calls this driver's
1658 * runtime APIs based on root-hub's state.
1659 */
1660 pm_runtime_set_active(&pdev->dev);
1661 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301662 /* Decrement the parent device's counter after probe.
1663 * As child is active, parent will not be put into
1664 * suspend mode.
1665 */
1666 if (pdev->dev.parent)
1667 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301668
1669 return 0;
1670
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301671unconfig_gpio:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001672 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301673 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301674deinit_vddcx:
1675 msm_hsic_init_vddcx(mehci, 0);
1676deinit_clocks:
1677 msm_hsic_init_clocks(mehci, 0);
1678unmap:
1679 iounmap(hcd->regs);
1680put_hcd:
1681 usb_put_hcd(hcd);
1682
1683 return ret;
1684}
1685
1686static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1687{
1688 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1689 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301690 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1691
1692 if (pdata && pdata->swfi_latency)
1693 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301694
Vamsi Krishna34f01582011-12-14 19:54:42 -08001695 if (mehci->peripheral_status_irq)
1696 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001697
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001698 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001699 if (mehci->wakeup_irq_enabled)
1700 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001701 free_irq(mehci->wakeup_irq, mehci);
1702 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001703
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001704 /*
1705 * If the update request is called after unregister, the request will
1706 * fail. Results are undefined if unregister is called in the middle of
1707 * update request.
1708 */
1709 mehci->bus_vote = false;
1710 cancel_work_sync(&mehci->bus_vote_w);
1711
Hemant Kumare6275972012-02-29 20:06:21 -08001712 if (mehci->bus_perf_client)
1713 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1714
1715 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301716 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301717 pm_runtime_set_suspended(&pdev->dev);
1718
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001719 destroy_workqueue(ehci_wq);
1720
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301721 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301722 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301723 msm_hsic_init_vddcx(mehci, 0);
1724
1725 msm_hsic_init_clocks(mehci, 0);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001726 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301727 iounmap(hcd->regs);
1728 usb_put_hcd(hcd);
1729
1730 return 0;
1731}
1732
1733#ifdef CONFIG_PM_SLEEP
1734static int msm_hsic_pm_suspend(struct device *dev)
1735{
Jack Phambe05fbb2012-05-16 10:56:26 -07001736 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301737 struct usb_hcd *hcd = dev_get_drvdata(dev);
1738 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1739
1740 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1741
Hemant Kumar45d211b2012-05-31 17:58:43 -07001742 dbg_log_event(NULL, "PM Suspend", 0);
1743
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301744 if (device_may_wakeup(dev))
1745 enable_irq_wake(hcd->irq);
1746
Jack Phambe05fbb2012-05-16 10:56:26 -07001747 ret = msm_hsic_suspend(mehci);
1748
1749 if (ret && device_may_wakeup(dev))
1750 disable_irq_wake(hcd->irq);
1751
1752 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001753}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301754
Jack Pham16b06f82012-08-14 20:03:59 -07001755static int msm_hsic_pm_suspend_noirq(struct device *dev)
1756{
1757 struct usb_hcd *hcd = dev_get_drvdata(dev);
1758 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1759
1760 if (mehci->async_int) {
1761 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
1762 return -EBUSY;
1763 }
1764
1765 return 0;
1766}
1767
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301768static int msm_hsic_pm_resume(struct device *dev)
1769{
1770 int ret;
1771 struct usb_hcd *hcd = dev_get_drvdata(dev);
1772 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1773
Jack Pham16b06f82012-08-14 20:03:59 -07001774 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001775 dbg_log_event(NULL, "PM Resume", 0);
1776
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301777 if (device_may_wakeup(dev))
1778 disable_irq_wake(hcd->irq);
1779
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301780 /*
1781 * Keep HSIC in Low Power Mode if system is resumed
1782 * by any other wakeup source. HSIC is resumed later
1783 * when remote wakeup is received or interface driver
1784 * start I/O.
1785 */
1786 if (!atomic_read(&mehci->pm_usage_cnt))
1787 return 0;
1788
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301789 ret = msm_hsic_resume(mehci);
1790 if (ret)
1791 return ret;
1792
1793 /* Bring the device to full powered state upon system resume */
1794 pm_runtime_disable(dev);
1795 pm_runtime_set_active(dev);
1796 pm_runtime_enable(dev);
1797
1798 return 0;
1799}
1800#endif
1801
1802#ifdef CONFIG_PM_RUNTIME
1803static int msm_hsic_runtime_idle(struct device *dev)
1804{
1805 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301806 return 0;
1807}
1808
1809static int msm_hsic_runtime_suspend(struct device *dev)
1810{
1811 struct usb_hcd *hcd = dev_get_drvdata(dev);
1812 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1813
1814 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001815
1816 dbg_log_event(NULL, "Run Time PM Suspend", 0);
1817
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301818 return msm_hsic_suspend(mehci);
1819}
1820
1821static int msm_hsic_runtime_resume(struct device *dev)
1822{
1823 struct usb_hcd *hcd = dev_get_drvdata(dev);
1824 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1825
1826 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001827
1828 dbg_log_event(NULL, "Run Time PM Resume", 0);
1829
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301830 return msm_hsic_resume(mehci);
1831}
1832#endif
1833
1834#ifdef CONFIG_PM
1835static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1836 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07001837 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301838 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1839 msm_hsic_runtime_idle)
1840};
1841#endif
1842
1843static struct platform_driver ehci_msm_hsic_driver = {
1844 .probe = ehci_hsic_msm_probe,
1845 .remove = __devexit_p(ehci_hsic_msm_remove),
1846 .driver = {
1847 .name = "msm_hsic_host",
1848#ifdef CONFIG_PM
1849 .pm = &msm_hsic_dev_pm_ops,
1850#endif
1851 },
1852};