blob: 2d69a9868c02577dea82d42b795f5c400941d5f2 [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>
Sudhir Sharma1673e302012-08-27 17:37:24 -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>
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -070038#include <linux/irq.h>
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070039#include <linux/kthread.h>
40#include <linux/wait.h>
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +053041#include <linux/pm_qos.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030042
43#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053044#include <mach/clk.h>
45#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053046#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080047#include <linux/spinlock.h>
Hemant Kumar45d211b2012-05-31 17:58:43 -070048#include <linux/cpu.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030049#include <mach/rpm-regulator.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053050
51#define MSM_USB_BASE (hcd->regs)
Hemant Kumar105d07f2012-07-02 15:33:07 -070052#define USB_REG_START_OFFSET 0x90
53#define USB_REG_END_OFFSET 0x250
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053054
Hemant Kumar2309eaa2012-08-14 16:46:42 -070055static struct workqueue_struct *ehci_wq;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070056struct ehci_timer {
57#define GPT_LD(p) ((p) & 0x00FFFFFF)
58 u32 gptimer0_ld;
59#define GPT_RUN BIT(31)
60#define GPT_RESET BIT(30)
61#define GPT_MODE BIT(24)
62#define GPT_CNT(p) ((p) & 0x00FFFFFF)
63 u32 gptimer0_ctrl;
64
65 u32 gptimer1_ld;
66 u32 gptimer1_ctrl;
67};
Hemant Kumar2309eaa2012-08-14 16:46:42 -070068
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053069struct msm_hsic_hcd {
70 struct ehci_hcd ehci;
Hemant Kumard343c012012-09-06 19:57:14 -070071 spinlock_t wakeup_lock;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053072 struct device *dev;
73 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080074 struct clk *core_clk;
75 struct clk *alt_core_clk;
76 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053077 struct clk *cal_clk;
78 struct regulator *hsic_vddcx;
Sudhir Sharma1673e302012-08-27 17:37:24 -070079 bool async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053080 atomic_t in_lpm;
Sudhir Sharma1673e302012-08-27 17:37:24 -070081 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080082 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080083 int wakeup_irq;
Jack Phamfe441ea2012-03-23 17:03:15 -070084 bool wakeup_irq_enabled;
Sudhir Sharma1673e302012-08-27 17:37:24 -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;
Vamsi Krishnafce1bd22012-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 Kondeti4f5dc3b2012-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
Hemant Kumar4d50a432012-08-15 09:06:35 -0700107static unsigned int enable_payload_log = 1;
108module_param(enable_payload_log, uint, S_IRUGO | S_IWUSR);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700109static unsigned int enable_dbg_log = 1;
110module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
111/*by default log ep0 and efs sync ep*/
112static unsigned int ep_addr_rxdbg_mask = 9;
113module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
114static unsigned int ep_addr_txdbg_mask = 9;
115module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
116
117/* Maximum debug message length */
Hemant Kumar4d50a432012-08-15 09:06:35 -0700118#define DBG_MSG_LEN 128UL
Hemant Kumar45d211b2012-05-31 17:58:43 -0700119
120/* Maximum number of messages */
121#define DBG_MAX_MSG 256UL
122
123#define TIME_BUF_LEN 20
Hemant Kumar4d50a432012-08-15 09:06:35 -0700124#define HEX_DUMP_LEN 72
Hemant Kumar45d211b2012-05-31 17:58:43 -0700125
126enum event_type {
127 EVENT_UNDEF = -1,
128 URB_SUBMIT,
129 URB_COMPLETE,
130 EVENT_NONE,
131};
132
133#define EVENT_STR_LEN 5
134
Hemant Kumar45d211b2012-05-31 17:58:43 -0700135static enum event_type str_to_event(const char *name)
136{
137 if (!strncasecmp("S", name, EVENT_STR_LEN))
138 return URB_SUBMIT;
139 if (!strncasecmp("C", name, EVENT_STR_LEN))
140 return URB_COMPLETE;
141 if (!strncasecmp("", name, EVENT_STR_LEN))
142 return EVENT_NONE;
143
144 return EVENT_UNDEF;
145}
146
147/*log ep0 activity*/
148static struct {
149 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
150 unsigned idx; /* index */
151 rwlock_t lck; /* lock */
152} dbg_hsic_ctrl = {
153 .idx = 0,
154 .lck = __RW_LOCK_UNLOCKED(lck)
155};
156
157static struct {
158 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
159 unsigned idx; /* index */
160 rwlock_t lck; /* lock */
161} dbg_hsic_data = {
162 .idx = 0,
163 .lck = __RW_LOCK_UNLOCKED(lck)
164};
165
166/**
167 * dbg_inc: increments debug event index
168 * @idx: buffer index
169 */
170static void dbg_inc(unsigned *idx)
171{
172 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
173}
174
175/*get_timestamp - returns time of day in us */
176static char *get_timestamp(char *tbuf)
177{
178 unsigned long long t;
179 unsigned long nanosec_rem;
180
181 t = cpu_clock(smp_processor_id());
182 nanosec_rem = do_div(t, 1000000000)/1000;
183 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
184 nanosec_rem);
185 return tbuf;
186}
187
188static int allow_dbg_log(int ep_addr)
189{
190 int dir, num;
191
192 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
193 num = ep_addr & ~USB_DIR_IN;
194 num = 1 << num;
195
196 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
197 return 1;
198 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
199 return 1;
200
201 return 0;
202}
203
Hemant Kumar4d50a432012-08-15 09:06:35 -0700204static char *get_hex_data(char *dbuf, struct urb *urb, int event, int status)
205{
206 int ep_addr = urb->ep->desc.bEndpointAddress;
207 char *ubuf = urb->transfer_buffer;
208 size_t len = event ? \
209 urb->actual_length : urb->transfer_buffer_length;
210
211 if (status == -EINPROGRESS)
212 status = 0;
213
214 /*Only dump ep in completions and epout submissions*/
215 if (len && !status &&
216 (((ep_addr & USB_DIR_IN) && event) ||
217 (!(ep_addr & USB_DIR_IN) && !event))) {
218 if (len >= 32)
219 len = 32;
220 hex_dump_to_buffer(ubuf, len, 32, 4, dbuf, HEX_DUMP_LEN, 0);
221 } else {
222 dbuf = "";
223 }
224
225 return dbuf;
226}
227
Hemant Kumar45d211b2012-05-31 17:58:43 -0700228static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
229{
230 unsigned long flags;
231 int ep_addr;
232 char tbuf[TIME_BUF_LEN];
Hemant Kumar4d50a432012-08-15 09:06:35 -0700233 char dbuf[HEX_DUMP_LEN];
Hemant Kumar45d211b2012-05-31 17:58:43 -0700234
235 if (!enable_dbg_log)
236 return;
237
238 if (!urb) {
239 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
240 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700241 "%s: %s : %u", get_timestamp(tbuf), event, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700242 dbg_inc(&dbg_hsic_ctrl.idx);
243 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
244 return;
245 }
246
247 ep_addr = urb->ep->desc.bEndpointAddress;
248 if (!allow_dbg_log(ep_addr))
249 return;
250
251 if ((ep_addr & 0x0f) == 0x0) {
252 /*submit event*/
253 if (!str_to_event(event)) {
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] "
Hemant Kumar4d50a432012-08-15 09:06:35 -0700257 "%02x %02x %04x %04x %04x %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700258 get_timestamp(tbuf), event, urb,
259 (ep_addr & USB_DIR_IN) ? "in" : "out",
260 urb->setup_packet[0], urb->setup_packet[1],
261 (urb->setup_packet[3] << 8) |
262 urb->setup_packet[2],
263 (urb->setup_packet[5] << 8) |
264 urb->setup_packet[4],
265 (urb->setup_packet[7] << 8) |
266 urb->setup_packet[6],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700267 urb->transfer_buffer_length, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700268
269 dbg_inc(&dbg_hsic_ctrl.idx);
270 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
271 } else {
272 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
273 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700274 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700275 get_timestamp(tbuf), event, urb,
276 (ep_addr & USB_DIR_IN) ? "in" : "out",
277 urb->actual_length, extra);
278
279 dbg_inc(&dbg_hsic_ctrl.idx);
280 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
281 }
282 } else {
283 write_lock_irqsave(&dbg_hsic_data.lck, flags);
284 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700285 "%s: [%s : %p]:ep%d[%s] %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700286 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
287 (ep_addr & USB_DIR_IN) ? "in" : "out",
288 str_to_event(event) ? urb->actual_length :
Hemant Kumar4d50a432012-08-15 09:06:35 -0700289 urb->transfer_buffer_length, extra,
290 enable_payload_log ? get_hex_data(dbuf, urb,
291 str_to_event(event), extra) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700292
293 dbg_inc(&dbg_hsic_data.idx);
294 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
295 }
296}
297
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530298static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
299{
300 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
301}
302
303static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
304{
305 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
306}
307
Hemant Kumar105d07f2012-07-02 15:33:07 -0700308static void dump_hsic_regs(struct usb_hcd *hcd)
309{
310 int i;
311 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
312
313 if (atomic_read(&mehci->in_lpm))
314 return;
315
316 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
317 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
318 readl_relaxed(hcd->regs + i),
319 readl_relaxed(hcd->regs + i + 4),
320 readl_relaxed(hcd->regs + i + 8),
321 readl_relaxed(hcd->regs + i + 0xc));
322}
323
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530324#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
325
Amit Blayd6ea6102012-06-07 16:26:24 +0300326#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Hemant Kumar3b743cd2012-10-17 13:48:10 -0700327#define USB_PHY_VDD_DIG_VOL_MIN 945000 /* uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700328#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530329
Lena Salman8c8ba382012-02-14 15:59:31 +0200330#define HSIC_DBG1_REG 0x38
331
Amit Blayd6ea6102012-06-07 16:26:24 +0300332static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
333 { /* VDD_CX CORNER Voting */
334 [VDD_NONE] = RPM_VREG_CORNER_NONE,
335 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
336 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
337 },
338 { /* VDD_CX Voltage Voting */
339 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
340 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
341 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
342 },
343};
344
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530345static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
346{
347 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300348 int none_vol, min_vol, max_vol;
349
350 if (!mehci->hsic_vddcx) {
351 mehci->vdd_type = VDDCX_CORNER;
352 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
353 "hsic_vdd_dig");
354 if (IS_ERR(mehci->hsic_vddcx)) {
355 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
356 "HSIC_VDDCX");
357 if (IS_ERR(mehci->hsic_vddcx)) {
358 dev_err(mehci->dev, "unable to get hsic vddcx\n");
359 return PTR_ERR(mehci->hsic_vddcx);
360 }
361 mehci->vdd_type = VDDCX;
362 }
363 }
364
365 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
366 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
367 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530368
369 if (!init)
370 goto disable_reg;
371
Amit Blayd6ea6102012-06-07 16:26:24 +0300372 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530373 if (ret) {
374 dev_err(mehci->dev, "unable to set the voltage"
375 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530376 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530377 }
378
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530379 ret = regulator_enable(mehci->hsic_vddcx);
380 if (ret) {
381 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
382 goto reg_enable_err;
383 }
384
385 return 0;
386
387disable_reg:
388 regulator_disable(mehci->hsic_vddcx);
389reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300390 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
391
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530392 return ret;
393
394}
395
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700396static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
397{
398 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700399 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700400
401 /* initiate read operation */
402 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
403 USB_ULPI_VIEWPORT);
404
405 /* wait for completion */
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700406 while (cnt < ULPI_IO_TIMEOUT_USEC) {
407 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
408 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700409 udelay(1);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700410 cnt++;
411 }
412
413 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
414 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
415 readl_relaxed(USB_ULPI_VIEWPORT));
416 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
417 readl_relaxed(USB_PORTSC),
418 readl_relaxed(USB_USBCMD),
419 readl_relaxed(USB_FRINDEX));
420
421 /*frame counter increments afte 125us*/
422 udelay(130);
423 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
424 readl_relaxed(USB_FRINDEX));
425 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700426 }
427
428 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
429}
430
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530431static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
432{
433 struct usb_hcd *hcd = hsic_to_hcd(mehci);
434 int cnt = 0;
435
436 /* initiate write operation */
437 writel_relaxed(ULPI_RUN | ULPI_WRITE |
438 ULPI_ADDR(reg) | ULPI_DATA(val),
439 USB_ULPI_VIEWPORT);
440
441 /* wait for completion */
442 while (cnt < ULPI_IO_TIMEOUT_USEC) {
443 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
444 break;
445 udelay(1);
446 cnt++;
447 }
448
449 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700450 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
451 readl_relaxed(USB_ULPI_VIEWPORT));
452 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
453 readl_relaxed(USB_PORTSC),
454 readl_relaxed(USB_USBCMD),
455 readl_relaxed(USB_FRINDEX));
456
457 /*frame counter increments afte 125us*/
458 udelay(130);
459 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
460 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530461 return -ETIMEDOUT;
462 }
463
464 return 0;
465}
466
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700467#define HSIC_DBG1 0X38
468#define ULPI_MANUAL_ENABLE BIT(4)
469#define ULPI_LINESTATE_DATA BIT(5)
470#define ULPI_LINESTATE_STROBE BIT(6)
471static void ehci_msm_enable_ulpi_control(struct usb_hcd *hcd, u32 linestate)
472{
473 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
474 int val;
475
476 switch (linestate) {
477 case PORT_RESET:
478 val = ulpi_read(mehci, HSIC_DBG1);
479 val |= ULPI_MANUAL_ENABLE;
480 val &= ~(ULPI_LINESTATE_DATA | ULPI_LINESTATE_STROBE);
481 ulpi_write(mehci, val, HSIC_DBG1);
482 break;
483 default:
484 pr_info("%s: Unknown linestate:%0x\n", __func__, linestate);
485 }
486}
487
488static void ehci_msm_disable_ulpi_control(struct usb_hcd *hcd)
489{
490 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
491 int val;
492
493 val = ulpi_read(mehci, HSIC_DBG1);
494 val &= ~ULPI_MANUAL_ENABLE;
495 ulpi_write(mehci, val, HSIC_DBG1);
496}
497
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530498static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
499{
500 int rc = 0;
501 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800502 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530503
504 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800505
Lena Salman8c8ba382012-02-14 15:59:31 +0200506 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530507 return rc;
508
Vamsi Krishna34f01582011-12-14 19:54:42 -0800509 if (gpio_status == gpio_en)
510 return 0;
511
512 gpio_status = gpio_en;
513
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530514 if (!gpio_en)
515 goto free_gpio;
516
517 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
518 if (rc < 0) {
519 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
520 return rc;
521 }
522
523 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
524 if (rc < 0) {
525 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
526 goto free_strobe;
Hemant Kumar6fd65032012-05-23 13:02:24 -0700527 }
528
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530529 return 0;
530
531free_gpio:
532 gpio_free(pdata->data);
533free_strobe:
534 gpio_free(pdata->strobe);
535
536 return rc;
537}
538
Vamsi Krishna64b48612012-06-14 16:08:11 -0700539static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530540{
541 int ret;
542
Manu Gautam5143b252012-01-05 19:25:23 -0800543 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530544 if (ret) {
Vamsi Krishna64b48612012-06-14 16:08:11 -0700545 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
546 return;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530547 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700548 clk_disable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530549
Manu Gautam5143b252012-01-05 19:25:23 -0800550 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530551 if (ret)
Vamsi Krishna64b48612012-06-14 16:08:11 -0700552 dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530553
Vamsi Krishna64b48612012-06-14 16:08:11 -0700554 usleep_range(10000, 12000);
555
556 clk_enable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530557}
558
Vamsi Krishna64b48612012-06-14 16:08:11 -0700559#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
560#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530561#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
562#define HSIC_LV_MODE 0x04
563#define HSIC_PAD_CALIBRATION 0xA8
564#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530565#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
566static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
567{
568 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530569 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200570 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530571
Vamsi Krishna64b48612012-06-14 16:08:11 -0700572 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530573
Vamsi Krishna64b48612012-06-14 16:08:11 -0700574 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530575 writel_relaxed(0x80000000, USB_PORTSC);
576
Vamsi Krishna64b48612012-06-14 16:08:11 -0700577 mb();
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530578
Lena Salman8c8ba382012-02-14 15:59:31 +0200579 /* HSIC init sequence when HSIC signals (Strobe/Data) are
580 routed via GPIOs */
581 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530582
Lena Salman8c8ba382012-02-14 15:59:31 +0200583 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
584 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530585
Vamsi Krishna64b48612012-06-14 16:08:11 -0700586 mb();
587
Lena Salman8c8ba382012-02-14 15:59:31 +0200588 /*set periodic calibration interval to ~2.048sec in
589 HSIC_IO_CAL_REG */
590 ulpi_write(mehci, 0xFF, 0x33);
591
592 /* Enable periodic IO calibration in HSIC_CFG register */
593 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
594
Vamsi Krishna64b48612012-06-14 16:08:11 -0700595 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200596 ret = msm_hsic_config_gpios(mehci, 1);
597 if (ret) {
598 dev_err(mehci->dev, " gpio configuarion failed\n");
599 return ret;
600 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700601 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO PAD_CTL register */
602 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_STROBE_GPIO_PAD_CTL);
603 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_DATA_GPIO_PAD_CTL);
604
605 mb();
606
Lena Salman8c8ba382012-02-14 15:59:31 +0200607 /* Enable HSIC mode in HSIC_CFG register */
608 ulpi_write(mehci, 0x01, 0x31);
609 } else {
610 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
611 via dedicated I/O */
612
613 /* programmable length of connect signaling (33.2ns) */
614 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
615 if (ret) {
616 pr_err("%s: Unable to program length of connect "
617 "signaling\n", __func__);
618 }
619
620 /*set periodic calibration interval to ~2.048sec in
621 HSIC_IO_CAL_REG */
622 ulpi_write(mehci, 0xFF, 0x33);
623
624 /* Enable HSIC mode in HSIC_CFG register */
625 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530626 }
627
Hemant Kumar6fd65032012-05-23 13:02:24 -0700628 /*disable auto resume*/
629 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
630
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530631 return 0;
632}
633
634#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
635#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
636
637#ifdef CONFIG_PM_SLEEP
638static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
639{
640 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530641 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530642 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300643 int none_vol, max_vol;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700644 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530645
646 if (atomic_read(&mehci->in_lpm)) {
647 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
648 return 0;
649 }
650
651 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700652
Sudhir Sharma1673e302012-08-27 17:37:24 -0700653 /* make sure we don't race against a remote wakeup */
654 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700655 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Sudhir Sharma1673e302012-08-27 17:37:24 -0700656 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700657 enable_irq(hcd->irq);
658 return -EBUSY;
659 }
660
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530661 /*
662 * PHY may take some time or even fail to enter into low power
663 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
664 * in failure case.
665 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700666 val = readl_relaxed(USB_PORTSC);
667 val &= ~PORT_RWC_BITS;
668 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530669 writel_relaxed(val, USB_PORTSC);
670 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
671 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
672 break;
673 udelay(1);
674 cnt++;
675 }
676
677 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
678 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530679 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530680 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530681 }
682
683 /*
684 * PHY has capability to generate interrupt asynchronously in low
685 * power mode (LPM). This interrupt is level triggered. So USB IRQ
686 * line must be disabled till async interrupt enable bit is cleared
687 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
688 * block data communication from PHY.
689 */
690 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
691 ULPI_STP_CTRL, USB_USBCMD);
692
693 /*
694 * Ensure that hardware is put in low power mode before
695 * clocks are turned OFF and VDD is allowed to minimize.
696 */
697 mb();
698
Manu Gautam28b1bac2012-01-30 16:43:06 +0530699 clk_disable_unprepare(mehci->core_clk);
700 clk_disable_unprepare(mehci->phy_clk);
701 clk_disable_unprepare(mehci->cal_clk);
702 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530703
Amit Blayd6ea6102012-06-07 16:26:24 +0300704 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
705 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
706
707 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700708 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300709 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700710
Hemant Kumare6275972012-02-29 20:06:21 -0800711 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700712 mehci->bus_vote = false;
713 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800714 }
715
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530716 atomic_set(&mehci->in_lpm, 1);
717 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700718
719 mehci->wakeup_irq_enabled = 1;
720 enable_irq_wake(mehci->wakeup_irq);
721 enable_irq(mehci->wakeup_irq);
722
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700723 if (pdata && pdata->standalone_latency)
724 pm_qos_update_request(&mehci->pm_qos_req_dma,
725 PM_QOS_DEFAULT_VALUE);
726
Sudhir Sharma1673e302012-08-27 17:37:24 -0700727 wake_unlock(&mehci->wlock);
728
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530729 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
730
731 return 0;
732}
733
734static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
735{
736 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530737 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530738 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300739 int min_vol, max_vol;
Hemant Kumard343c012012-09-06 19:57:14 -0700740 unsigned long flags;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700741 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530742
743 if (!atomic_read(&mehci->in_lpm)) {
744 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
745 return 0;
746 }
747
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700748 if (pdata && pdata->standalone_latency)
749 pm_qos_update_request(&mehci->pm_qos_req_dma,
750 pdata->standalone_latency + 1);
751
Hemant Kumard343c012012-09-06 19:57:14 -0700752 spin_lock_irqsave(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700753 if (mehci->wakeup_irq_enabled) {
754 disable_irq_wake(mehci->wakeup_irq);
755 disable_irq_nosync(mehci->wakeup_irq);
756 mehci->wakeup_irq_enabled = 0;
757 }
Hemant Kumard343c012012-09-06 19:57:14 -0700758 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700759
Sudhir Sharma1673e302012-08-27 17:37:24 -0700760 wake_lock(&mehci->wlock);
761
Hemant Kumare6275972012-02-29 20:06:21 -0800762 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700763 mehci->bus_vote = true;
764 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800765 }
766
Amit Blayd6ea6102012-06-07 16:26:24 +0300767 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
768 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
769
770 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700771 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300772 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700773
Manu Gautam28b1bac2012-01-30 16:43:06 +0530774 clk_prepare_enable(mehci->core_clk);
775 clk_prepare_enable(mehci->phy_clk);
776 clk_prepare_enable(mehci->cal_clk);
777 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530778
779 temp = readl_relaxed(USB_USBCMD);
780 temp &= ~ASYNC_INTR_CTRL;
781 temp &= ~ULPI_STP_CTRL;
782 writel_relaxed(temp, USB_USBCMD);
783
784 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
785 goto skip_phy_resume;
786
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700787 temp = readl_relaxed(USB_PORTSC);
788 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530789 writel_relaxed(temp, USB_PORTSC);
790 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
791 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
792 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
793 break;
794 udelay(1);
795 cnt++;
796 }
797
798 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
799 /*
800 * This is a fatal error. Reset the link and
801 * PHY to make hsic working.
802 */
803 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530804 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530805 msm_hsic_reset(mehci);
806 }
807
808skip_phy_resume:
809
Hemant Kumar6fd65032012-05-23 13:02:24 -0700810 usb_hcd_resume_root_hub(hcd);
811
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530812 atomic_set(&mehci->in_lpm, 0);
813
814 if (mehci->async_int) {
815 mehci->async_int = false;
816 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700817 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700818 }
819
Sudhir Sharma1673e302012-08-27 17:37:24 -0700820 if (atomic_read(&mehci->pm_usage_cnt)) {
821 atomic_set(&mehci->pm_usage_cnt, 0);
822 pm_runtime_put_noidle(mehci->dev);
823 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700824
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530825 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
826
827 return 0;
828}
829#endif
830
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700831static void ehci_hsic_bus_vote_w(struct work_struct *w)
832{
833 struct msm_hsic_hcd *mehci =
834 container_of(w, struct msm_hsic_hcd, bus_vote_w);
835 int ret;
836
837 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
838 mehci->bus_vote);
839 if (ret)
840 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
841 __func__, ret);
842}
843
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700844#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530845static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
846{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700847 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530848 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700849 u32 status;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530850
851 if (atomic_read(&mehci->in_lpm)) {
852 disable_irq_nosync(hcd->irq);
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700853 dev_dbg(mehci->dev, "phy async intr\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530854 mehci->async_int = true;
855 pm_runtime_get(mehci->dev);
856 return IRQ_HANDLED;
857 }
858
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700859 status = ehci_readl(ehci, &ehci->regs->status);
860
861 if (status & STS_GPTIMER0_INTERRUPT) {
862 int timeleft;
863
864 dbg_log_event(NULL, "FPR: gpt0_isr", 0);
865
866 timeleft = GPT_CNT(ehci_readl(ehci,
867 &mehci->timer->gptimer1_ctrl));
868 if (timeleft) {
869 ehci_writel(ehci, ehci_readl(ehci,
870 &ehci->regs->command) | CMD_RUN,
871 &ehci->regs->command);
872 } else
873 mehci->resume_again = 1;
874
875 dbg_log_event(NULL, "FPR: timeleft", timeleft);
876
877 complete(&mehci->gpt0_completion);
878 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
879 }
880
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530881 return ehci_irq(hcd);
882}
883
884static int ehci_hsic_reset(struct usb_hcd *hcd)
885{
886 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700887 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530888 int retval;
889
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700890 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530891 ehci->caps = USB_CAPLENGTH;
892 ehci->regs = USB_CAPLENGTH +
893 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
894 dbg_hcs_params(ehci, "reset");
895 dbg_hcc_params(ehci, "reset");
896
897 /* cache the data to minimize the chip reads*/
898 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
899
900 hcd->has_tt = 1;
901 ehci->sbrn = HCD_USB2;
902
903 retval = ehci_halt(ehci);
904 if (retval)
905 return retval;
906
907 /* data structure init */
908 retval = ehci_init(hcd);
909 if (retval)
910 return retval;
911
912 retval = ehci_reset(ehci);
913 if (retval)
914 return retval;
915
916 /* bursts of unspecified length. */
917 writel_relaxed(0, USB_AHBBURST);
918 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530919 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530920 /* Disable streaming mode and select host mode */
921 writel_relaxed(0x13, USB_USBMODE);
922
923 ehci_port_power(ehci, 1);
924 return 0;
925}
926
Jack Phamc0d41732012-09-28 17:45:38 -0700927#ifdef CONFIG_PM
928
Hemant Kumar45d211b2012-05-31 17:58:43 -0700929static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
930{
Pavankumar Kondetia723f742012-09-14 14:02:36 +0530931 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
932
933 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
934 dbg_log_event(NULL, "RH suspend attempt failed", 0);
935 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
936 __func__);
937 return -EAGAIN;
938 }
939
Hemant Kumar45d211b2012-05-31 17:58:43 -0700940 dbg_log_event(NULL, "Suspend RH", 0);
941 return ehci_bus_suspend(hcd);
942}
943
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700944#define RESUME_RETRY_LIMIT 3
945#define RESUME_SIGNAL_TIME_MS (21 * 999)
946#define RESUME_SIGNAL_TIME_SOF_MS (23 * 999)
947static int msm_hsic_resume_thread(void *data)
948{
949 struct msm_hsic_hcd *mehci = data;
950 struct usb_hcd *hcd = hsic_to_hcd(mehci);
951 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
952 u32 temp;
953 unsigned long resume_needed = 0;
954 int retry_cnt = 0;
955 int tight_resume = 0;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +0530956 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700957
958 dbg_log_event(NULL, "Resume RH", 0);
959
960 /* keep delay between bus states */
961 if (time_before(jiffies, ehci->next_statechange))
962 usleep_range(5000, 5000);
963
964 spin_lock_irq(&ehci->lock);
965 if (!HCD_HW_ACCESSIBLE(hcd)) {
966 spin_unlock_irq(&ehci->lock);
967 mehci->resume_status = -ESHUTDOWN;
968 complete(&mehci->rt_completion);
969 return 0;
970 }
971
972 if (unlikely(ehci->debug)) {
973 if (!dbgp_reset_prep())
974 ehci->debug = NULL;
975 else
976 dbgp_external_startup();
977 }
978
979 /* at least some APM implementations will try to deliver
980 * IRQs right away, so delay them until we're ready.
981 */
982 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
983
984 /* re-init operational registers */
985 ehci_writel(ehci, 0, &ehci->regs->segment);
986 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
987 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
988
989 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
990 if (ehci->resume_sof_bug)
991 ehci->command &= ~CMD_RUN;
992
993 /* restore CMD_RUN, framelist size, and irq threshold */
994 ehci_writel(ehci, ehci->command, &ehci->regs->command);
995
996 /* manually resume the ports we suspended during bus_suspend() */
997resume_again:
998 if (retry_cnt >= RESUME_RETRY_LIMIT) {
999 pr_info("retry count(%d) reached max, resume in tight loop\n",
1000 retry_cnt);
1001 tight_resume = 1;
1002 }
1003
1004
1005 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1006 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
1007 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
1008 temp |= PORT_RESUME;
1009 set_bit(0, &resume_needed);
1010 }
1011 dbg_log_event(NULL, "FPR: Set", temp);
1012 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1013
1014 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1015 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1016 * controller in MSM clears FPR bit after driving the resume signal for
1017 * 20ms. Workaround is to stop SOFs before driving resume and then start
1018 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1019 * completion otherwise peripheral may enter undefined state. As
1020 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1021 * to time the resume sequence. If driver exceeds allowable time SOFs,
1022 * repeat the resume process.
1023 */
1024 if (ehci->resume_sof_bug && resume_needed) {
1025 if (!tight_resume) {
1026 mehci->resume_again = 0;
1027 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_MS),
1028 &mehci->timer->gptimer0_ld);
1029 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1030 &mehci->timer->gptimer0_ctrl);
1031 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1032 &ehci->regs->intr_enable);
1033
1034 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_SOF_MS),
1035 &mehci->timer->gptimer1_ld);
1036 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1037 &mehci->timer->gptimer1_ctrl);
1038
1039 spin_unlock_irq(&ehci->lock);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301040 if (pdata && pdata->swfi_latency)
1041 pm_qos_update_request(&mehci->pm_qos_req_dma,
1042 pdata->swfi_latency + 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001043 wait_for_completion(&mehci->gpt0_completion);
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001044 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301045 pm_qos_update_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001046 pdata->standalone_latency + 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001047 spin_lock_irq(&ehci->lock);
1048 } else {
1049 dbg_log_event(NULL, "FPR: Tightloop", 0);
1050 /* do the resume in a tight loop */
1051 handshake(ehci, &ehci->regs->port_status[0],
1052 PORT_RESUME, 0, 22 * 1000);
1053 ehci_writel(ehci, ehci_readl(ehci,
1054 &ehci->regs->command) | CMD_RUN,
1055 &ehci->regs->command);
1056 }
1057
1058 if (mehci->resume_again) {
1059 int temp;
1060
1061 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1062 pr_info("FPR: retry count: %d\n", retry_cnt);
1063 spin_unlock_irq(&ehci->lock);
1064 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1065 temp &= ~PORT_RWC_BITS;
1066 temp |= PORT_SUSPEND;
1067 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1068 /* Keep the bus idle for 5ms so that peripheral
1069 * can detect and initiate suspend
1070 */
1071 usleep_range(5000, 5000);
1072 dbg_log_event(NULL,
1073 "FPR: RResume",
1074 ehci_readl(ehci, &ehci->regs->port_status[0]));
1075 spin_lock_irq(&ehci->lock);
1076 mehci->resume_again = 0;
1077 retry_cnt++;
1078 goto resume_again;
1079 }
1080 }
1081
1082 dbg_log_event(NULL, "FPR: RT-Done", 0);
1083 mehci->resume_status = 1;
1084 spin_unlock_irq(&ehci->lock);
1085
1086 complete(&mehci->rt_completion);
1087
1088 return 0;
1089}
1090
Hemant Kumar45d211b2012-05-31 17:58:43 -07001091static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1092{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001093 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1094 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1095 u32 temp;
1096 struct task_struct *resume_thread = NULL;
1097
1098 mehci->resume_status = 0;
1099 resume_thread = kthread_run(msm_hsic_resume_thread,
1100 mehci, "hsic_resume_thread");
1101 if (IS_ERR(resume_thread)) {
1102 pr_err("Error creating resume thread:%lu\n",
1103 PTR_ERR(resume_thread));
1104 return PTR_ERR(resume_thread);
1105 }
1106
1107 wait_for_completion(&mehci->rt_completion);
1108
1109 if (mehci->resume_status < 0)
1110 return mehci->resume_status;
1111
1112 dbg_log_event(NULL, "FPR: Wokeup", 0);
1113 spin_lock_irq(&ehci->lock);
1114 (void) ehci_readl(ehci, &ehci->regs->command);
1115
1116 temp = 0;
1117 if (ehci->async->qh_next.qh)
1118 temp |= CMD_ASE;
1119 if (ehci->periodic_sched)
1120 temp |= CMD_PSE;
1121 if (temp) {
1122 ehci->command |= temp;
1123 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1124 }
1125
1126 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1127 hcd->state = HC_STATE_RUNNING;
1128 ehci->rh_state = EHCI_RH_RUNNING;
1129
1130 /* Now we can safely re-enable irqs */
1131 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1132
1133 spin_unlock_irq(&ehci->lock);
1134
1135 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001136}
1137
Jack Phamc0d41732012-09-28 17:45:38 -07001138#else
1139
1140#define ehci_hsic_bus_suspend NULL
1141#define ehci_hsic_bus_resume NULL
1142
1143#endif /* CONFIG_PM */
1144
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001145static void ehci_msm_set_autosuspend_delay(struct usb_device *dev)
1146{
1147 if (!dev->parent) /*for root hub no delay*/
1148 pm_runtime_set_autosuspend_delay(&dev->dev, 0);
1149 else
1150 pm_runtime_set_autosuspend_delay(&dev->dev, 200);
1151}
1152
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301153static struct hc_driver msm_hsic_driver = {
1154 .description = hcd_name,
1155 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1156 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1157
1158 /*
1159 * generic hardware linkage
1160 */
1161 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001162 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301163
1164 .reset = ehci_hsic_reset,
1165 .start = ehci_run,
1166
1167 .stop = ehci_stop,
1168 .shutdown = ehci_shutdown,
1169
1170 /*
1171 * managing i/o requests and associated device resources
1172 */
Hemant Kumar4d50a432012-08-15 09:06:35 -07001173 .urb_enqueue = ehci_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301174 .urb_dequeue = ehci_urb_dequeue,
1175 .endpoint_disable = ehci_endpoint_disable,
1176 .endpoint_reset = ehci_endpoint_reset,
1177 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1178
1179 /*
1180 * scheduling support
1181 */
1182 .get_frame_number = ehci_get_frame,
1183
1184 /*
1185 * root hub support
1186 */
1187 .hub_status_data = ehci_hub_status_data,
1188 .hub_control = ehci_hub_control,
1189 .relinquish_port = ehci_relinquish_port,
1190 .port_handed_over = ehci_port_handed_over,
1191
1192 /*
1193 * PM support
1194 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001195 .bus_suspend = ehci_hsic_bus_suspend,
1196 .bus_resume = ehci_hsic_bus_resume,
1197
Hemant Kumar4d50a432012-08-15 09:06:35 -07001198 .log_urb = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001199 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001200
1201 .enable_ulpi_control = ehci_msm_enable_ulpi_control,
1202 .disable_ulpi_control = ehci_msm_disable_ulpi_control,
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001203
1204 .set_autosuspend_delay = ehci_msm_set_autosuspend_delay,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301205};
1206
1207static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1208{
1209 int ret = 0;
1210
1211 if (!init)
1212 goto put_clocks;
1213
Lena Salman8c8ba382012-02-14 15:59:31 +02001214 /*core_clk is required for LINK protocol engine
1215 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001216 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1217 if (IS_ERR(mehci->core_clk)) {
1218 dev_err(mehci->dev, "failed to get core_clk\n");
1219 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301220 return ret;
1221 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301222
Lena Salman8c8ba382012-02-14 15:59:31 +02001223 /* alt_core_clk is for LINK to be used during PHY RESET
1224 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001225 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
1226 if (IS_ERR(mehci->alt_core_clk)) {
1227 dev_err(mehci->dev, "failed to core_clk\n");
1228 ret = PTR_ERR(mehci->alt_core_clk);
1229 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301230 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301231
Lena Salman8c8ba382012-02-14 15:59:31 +02001232 /* phy_clk is required for HSIC PHY operation
1233 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001234 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1235 if (IS_ERR(mehci->phy_clk)) {
1236 dev_err(mehci->dev, "failed to get phy_clk\n");
1237 ret = PTR_ERR(mehci->phy_clk);
1238 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301239 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301240
1241 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001242 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301243 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001244 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301245 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001246 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301247 }
1248 clk_set_rate(mehci->cal_clk, 10000000);
1249
1250 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001251 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301252 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001253 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301254 ret = PTR_ERR(mehci->ahb_clk);
1255 goto put_cal_clk;
1256 }
1257
Manu Gautam28b1bac2012-01-30 16:43:06 +05301258 clk_prepare_enable(mehci->core_clk);
1259 clk_prepare_enable(mehci->phy_clk);
1260 clk_prepare_enable(mehci->cal_clk);
1261 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301262
1263 return 0;
1264
1265put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001266 if (!atomic_read(&mehci->in_lpm)) {
1267 clk_disable_unprepare(mehci->core_clk);
1268 clk_disable_unprepare(mehci->phy_clk);
1269 clk_disable_unprepare(mehci->cal_clk);
1270 clk_disable_unprepare(mehci->ahb_clk);
1271 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301272 clk_put(mehci->ahb_clk);
1273put_cal_clk:
1274 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001275put_phy_clk:
1276 clk_put(mehci->phy_clk);
1277put_alt_core_clk:
1278 clk_put(mehci->alt_core_clk);
1279put_core_clk:
1280 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301281
1282 return ret;
1283}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001284static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1285{
1286 struct msm_hsic_hcd *mehci = dev_id;
1287
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001288 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001289
1290 if (mehci)
1291 msm_hsic_config_gpios(mehci, 0);
1292
1293 return IRQ_HANDLED;
1294}
1295
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001296static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1297{
1298 struct msm_hsic_hcd *mehci = data;
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301299 int ret;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001300
Hemant Kumar6fd65032012-05-23 13:02:24 -07001301 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001302 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001303 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
1304 __func__, mehci->wakeup_int_cnt);
1305
Sudhir Sharma1673e302012-08-27 17:37:24 -07001306 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001307
Hemant Kumard343c012012-09-06 19:57:14 -07001308 spin_lock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001309 if (mehci->wakeup_irq_enabled) {
1310 mehci->wakeup_irq_enabled = 0;
1311 disable_irq_wake(irq);
1312 disable_irq_nosync(irq);
1313 }
Hemant Kumard343c012012-09-06 19:57:14 -07001314 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001315
Sudhir Sharma1673e302012-08-27 17:37:24 -07001316 if (!atomic_read(&mehci->pm_usage_cnt)) {
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301317 ret = pm_runtime_get(mehci->dev);
1318 /*
1319 * HSIC runtime resume can race with us.
1320 * if we are active (ret == 1) or resuming
1321 * (ret == -EINPROGRESS), decrement the
1322 * PM usage counter before returning.
1323 */
1324 if ((ret == 1) || (ret == -EINPROGRESS))
1325 pm_runtime_put_noidle(mehci->dev);
1326 else
1327 atomic_set(&mehci->pm_usage_cnt, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001328 }
1329
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001330 return IRQ_HANDLED;
1331}
1332
Hemant Kumare6275972012-02-29 20:06:21 -08001333static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1334{
1335 if (debug_bus_voting_enabled)
1336 seq_printf(s, "enabled\n");
1337 else
1338 seq_printf(s, "disabled\n");
1339
1340 return 0;
1341}
1342
1343static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1344{
1345 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1346}
1347
1348static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1349 const char __user *ubuf, size_t count, loff_t *ppos)
1350{
1351 char buf[8];
1352 int ret;
1353 struct seq_file *s = file->private_data;
1354 struct msm_hsic_hcd *mehci = s->private;
1355
1356 memset(buf, 0x00, sizeof(buf));
1357
1358 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1359 return -EFAULT;
1360
1361 if (!strncmp(buf, "enable", 6)) {
1362 /* Do not vote here. Let hsic driver decide when to vote */
1363 debug_bus_voting_enabled = true;
1364 } else {
1365 debug_bus_voting_enabled = false;
1366 if (mehci->bus_perf_client) {
1367 ret = msm_bus_scale_client_update_request(
1368 mehci->bus_perf_client, 0);
1369 if (ret)
1370 dev_err(mehci->dev, "%s: Failed to devote "
1371 "for bus bw %d\n", __func__, ret);
1372 }
1373 }
1374
1375 return count;
1376}
1377
1378const struct file_operations ehci_hsic_msm_bus_fops = {
1379 .open = ehci_hsic_msm_bus_open,
1380 .read = seq_read,
1381 .write = ehci_hsic_msm_bus_write,
1382 .llseek = seq_lseek,
1383 .release = single_release,
1384};
1385
Hemant Kumar6fd65032012-05-23 13:02:24 -07001386static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1387{
1388 struct msm_hsic_hcd *mehci = s->private;
1389
1390 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1391
1392 return 0;
1393}
1394
1395static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1396{
1397 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1398}
1399
1400const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1401 .open = ehci_hsic_msm_wakeup_cnt_open,
1402 .read = seq_read,
1403 .llseek = seq_lseek,
1404 .release = single_release,
1405};
1406
Hemant Kumar45d211b2012-05-31 17:58:43 -07001407static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1408{
1409 unsigned long flags;
1410 unsigned i;
1411
1412 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1413
1414 i = dbg_hsic_data.idx;
1415 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1416 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1417 continue;
1418 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1419 }
1420
1421 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1422
1423 return 0;
1424}
1425
1426static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1427{
1428 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1429}
1430
1431const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1432 .open = ehci_hsic_msm_data_events_open,
1433 .read = seq_read,
1434 .llseek = seq_lseek,
1435 .release = single_release,
1436};
1437
1438static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1439{
1440 unsigned long flags;
1441 unsigned i;
1442
1443 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1444
1445 i = dbg_hsic_ctrl.idx;
1446 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1447 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1448 continue;
1449 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1450 }
1451
1452 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1453
1454 return 0;
1455}
1456
1457static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1458{
1459 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1460}
1461
1462const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1463 .open = ehci_hsic_msm_ctrl_events_open,
1464 .read = seq_read,
1465 .llseek = seq_lseek,
1466 .release = single_release,
1467};
1468
Hemant Kumare6275972012-02-29 20:06:21 -08001469static struct dentry *ehci_hsic_msm_dbg_root;
1470static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1471{
1472 struct dentry *ehci_hsic_msm_dentry;
1473
1474 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1475
1476 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1477 return -ENODEV;
1478
1479 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1480 S_IRUGO | S_IWUSR,
1481 ehci_hsic_msm_dbg_root, mehci,
1482 &ehci_hsic_msm_bus_fops);
1483
1484 if (!ehci_hsic_msm_dentry) {
1485 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1486 return -ENODEV;
1487 }
1488
Hemant Kumar6fd65032012-05-23 13:02:24 -07001489 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1490 S_IRUGO,
1491 ehci_hsic_msm_dbg_root, mehci,
1492 &ehci_hsic_msm_wakeup_cnt_fops);
1493
1494 if (!ehci_hsic_msm_dentry) {
1495 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1496 return -ENODEV;
1497 }
1498
Hemant Kumar45d211b2012-05-31 17:58:43 -07001499 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1500 S_IRUGO,
1501 ehci_hsic_msm_dbg_root, mehci,
1502 &ehci_hsic_msm_dbg_ctrl_fops);
1503
1504 if (!ehci_hsic_msm_dentry) {
1505 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1506 return -ENODEV;
1507 }
1508
1509 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1510 S_IRUGO,
1511 ehci_hsic_msm_dbg_root, mehci,
1512 &ehci_hsic_msm_dbg_data_fops);
1513
1514 if (!ehci_hsic_msm_dentry) {
1515 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1516 return -ENODEV;
1517 }
1518
Hemant Kumare6275972012-02-29 20:06:21 -08001519 return 0;
1520}
1521
1522static void ehci_hsic_msm_debugfs_cleanup(void)
1523{
1524 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1525}
1526
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301527static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1528{
1529 struct usb_hcd *hcd;
1530 struct resource *res;
1531 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301532 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301533 int ret;
1534
1535 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1536
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301537 /* After parent device's probe is executed, it will be put in suspend
1538 * mode. When child device's probe is called, driver core is not
1539 * resuming parent device due to which parent will be in suspend even
1540 * though child is active. Hence resume the parent device explicitly.
1541 */
1542 if (pdev->dev.parent)
1543 pm_runtime_get_sync(pdev->dev.parent);
1544
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301545 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1546 dev_name(&pdev->dev));
1547 if (!hcd) {
1548 dev_err(&pdev->dev, "Unable to create HCD\n");
1549 return -ENOMEM;
1550 }
1551
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301552 hcd_to_bus(hcd)->skip_resume = true;
1553
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301554 hcd->irq = platform_get_irq(pdev, 0);
1555 if (hcd->irq < 0) {
1556 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1557 ret = hcd->irq;
1558 goto put_hcd;
1559 }
1560
1561 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1562 if (!res) {
1563 dev_err(&pdev->dev, "Unable to get memory resource\n");
1564 ret = -ENODEV;
1565 goto put_hcd;
1566 }
1567
1568 hcd->rsrc_start = res->start;
1569 hcd->rsrc_len = resource_size(res);
1570 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1571 if (!hcd->regs) {
1572 dev_err(&pdev->dev, "ioremap failed\n");
1573 ret = -ENOMEM;
1574 goto put_hcd;
1575 }
1576
1577 mehci = hcd_to_hsic(hcd);
1578 mehci->dev = &pdev->dev;
Hemant Kumar30d361c2012-08-20 14:44:40 -07001579 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301580
Hemant Kumard343c012012-09-06 19:57:14 -07001581 spin_lock_init(&mehci->wakeup_lock);
1582
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001583 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001584 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001585
Hemant Kumare4040492012-06-21 17:35:42 -07001586 mehci->ehci.resume_sof_bug = 1;
1587
Hemant Kumar30d361c2012-08-20 14:44:40 -07001588 if (pdata)
1589 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Hemant Kumar933e0402012-05-22 11:11:40 -07001590
Vamsi Krishna34f01582011-12-14 19:54:42 -08001591 res = platform_get_resource_byname(pdev,
1592 IORESOURCE_IRQ,
1593 "peripheral_status_irq");
1594 if (res)
1595 mehci->peripheral_status_irq = res->start;
1596
Jack Pham0cc75c42012-10-10 02:03:50 +02001597 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "wakeup");
Hemant Kumar6fd65032012-05-23 13:02:24 -07001598 if (res) {
Jack Pham0cc75c42012-10-10 02:03:50 +02001599 mehci->wakeup_irq = res->start;
Hemant Kumar6fd65032012-05-23 13:02:24 -07001600 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1601 }
1602
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301603 ret = msm_hsic_init_clocks(mehci, 1);
1604 if (ret) {
1605 dev_err(&pdev->dev, "unable to initialize clocks\n");
1606 ret = -ENODEV;
1607 goto unmap;
1608 }
1609
1610 ret = msm_hsic_init_vddcx(mehci, 1);
1611 if (ret) {
1612 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1613 ret = -ENODEV;
1614 goto deinit_clocks;
1615 }
1616
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001617 init_completion(&mehci->rt_completion);
1618 init_completion(&mehci->gpt0_completion);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301619 ret = msm_hsic_reset(mehci);
1620 if (ret) {
1621 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301622 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301623 }
1624
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001625 ehci_wq = create_singlethread_workqueue("ehci_wq");
1626 if (!ehci_wq) {
1627 dev_err(&pdev->dev, "unable to create workqueue\n");
1628 ret = -ENOMEM;
1629 goto deinit_vddcx;
1630 }
1631
1632 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1633
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301634 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1635 if (ret) {
1636 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301637 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301638 }
1639
1640 device_init_wakeup(&pdev->dev, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001641 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1642 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001643
1644 if (mehci->peripheral_status_irq) {
1645 ret = request_threaded_irq(mehci->peripheral_status_irq,
1646 NULL, hsic_peripheral_status_change,
1647 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1648 | IRQF_SHARED,
1649 "hsic_peripheral_status", mehci);
1650 if (ret)
1651 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1652 __func__, mehci->peripheral_status_irq, ret);
1653 }
1654
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001655 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001656 if (mehci->wakeup_irq) {
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07001657 /* In case if wakeup gpio is pulled high at this point
1658 * remote wakeup interrupt fires right after request_irq.
1659 * Remote wake up interrupt only needs to be enabled when
1660 * HSIC bus goes to suspend.
1661 */
1662 irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001663 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001664 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001665 "msm_hsic_wakeup", mehci);
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07001666 if (ret) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001667 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1668 mehci->wakeup_irq, ret);
1669 mehci->wakeup_irq = 0;
1670 }
1671 }
1672
Hemant Kumare6275972012-02-29 20:06:21 -08001673 ret = ehci_hsic_msm_debugfs_init(mehci);
1674 if (ret)
1675 dev_dbg(&pdev->dev, "mode debugfs file is"
1676 "not available\n");
1677
1678 if (pdata && pdata->bus_scale_table) {
1679 mehci->bus_perf_client =
1680 msm_bus_scale_register_client(pdata->bus_scale_table);
1681 /* Configure BUS performance parameters for MAX bandwidth */
1682 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001683 mehci->bus_vote = true;
1684 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001685 } else {
1686 dev_err(&pdev->dev, "%s: Failed to register BUS "
1687 "scaling client!!\n", __func__);
1688 }
1689 }
1690
Hemant Kumar105d07f2012-07-02 15:33:07 -07001691 __mehci = mehci;
1692
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001693 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301694 pm_qos_add_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001695 PM_QOS_CPU_DMA_LATENCY, pdata->standalone_latency + 1);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301696
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301697 /*
1698 * This pdev->dev is assigned parent of root-hub by USB core,
1699 * hence, runtime framework automatically calls this driver's
1700 * runtime APIs based on root-hub's state.
1701 */
1702 pm_runtime_set_active(&pdev->dev);
1703 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301704 /* Decrement the parent device's counter after probe.
1705 * As child is active, parent will not be put into
1706 * suspend mode.
1707 */
1708 if (pdev->dev.parent)
1709 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301710
1711 return 0;
1712
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301713unconfig_gpio:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001714 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301715 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301716deinit_vddcx:
1717 msm_hsic_init_vddcx(mehci, 0);
1718deinit_clocks:
1719 msm_hsic_init_clocks(mehci, 0);
1720unmap:
1721 iounmap(hcd->regs);
1722put_hcd:
1723 usb_put_hcd(hcd);
1724
1725 return ret;
1726}
1727
1728static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1729{
1730 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1731 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301732 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1733
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001734 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301735 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301736
Vamsi Krishna34f01582011-12-14 19:54:42 -08001737 if (mehci->peripheral_status_irq)
1738 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001739
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001740 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001741 if (mehci->wakeup_irq_enabled)
1742 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001743 free_irq(mehci->wakeup_irq, mehci);
1744 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001745
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001746 /*
1747 * If the update request is called after unregister, the request will
1748 * fail. Results are undefined if unregister is called in the middle of
1749 * update request.
1750 */
1751 mehci->bus_vote = false;
1752 cancel_work_sync(&mehci->bus_vote_w);
1753
Hemant Kumare6275972012-02-29 20:06:21 -08001754 if (mehci->bus_perf_client)
1755 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1756
1757 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301758 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301759 pm_runtime_set_suspended(&pdev->dev);
1760
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001761 destroy_workqueue(ehci_wq);
1762
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301763 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301764 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301765 msm_hsic_init_vddcx(mehci, 0);
1766
1767 msm_hsic_init_clocks(mehci, 0);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001768 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301769 iounmap(hcd->regs);
1770 usb_put_hcd(hcd);
1771
1772 return 0;
1773}
1774
1775#ifdef CONFIG_PM_SLEEP
1776static int msm_hsic_pm_suspend(struct device *dev)
1777{
Jack Phambe05fbb2012-05-16 10:56:26 -07001778 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301779 struct usb_hcd *hcd = dev_get_drvdata(dev);
1780 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1781
1782 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1783
Hemant Kumar45d211b2012-05-31 17:58:43 -07001784 dbg_log_event(NULL, "PM Suspend", 0);
1785
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301786 if (device_may_wakeup(dev))
1787 enable_irq_wake(hcd->irq);
1788
Jack Phambe05fbb2012-05-16 10:56:26 -07001789 ret = msm_hsic_suspend(mehci);
1790
1791 if (ret && device_may_wakeup(dev))
1792 disable_irq_wake(hcd->irq);
1793
1794 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001795}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301796
Jack Pham16b06f82012-08-14 20:03:59 -07001797static int msm_hsic_pm_suspend_noirq(struct device *dev)
1798{
1799 struct usb_hcd *hcd = dev_get_drvdata(dev);
1800 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1801
1802 if (mehci->async_int) {
1803 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
1804 return -EBUSY;
1805 }
1806
1807 return 0;
1808}
1809
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301810static int msm_hsic_pm_resume(struct device *dev)
1811{
1812 int ret;
1813 struct usb_hcd *hcd = dev_get_drvdata(dev);
1814 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1815
Jack Pham16b06f82012-08-14 20:03:59 -07001816 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001817 dbg_log_event(NULL, "PM Resume", 0);
1818
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301819 if (device_may_wakeup(dev))
1820 disable_irq_wake(hcd->irq);
1821
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301822 /*
1823 * Keep HSIC in Low Power Mode if system is resumed
1824 * by any other wakeup source. HSIC is resumed later
1825 * when remote wakeup is received or interface driver
1826 * start I/O.
1827 */
1828 if (!atomic_read(&mehci->pm_usage_cnt))
1829 return 0;
1830
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301831 ret = msm_hsic_resume(mehci);
1832 if (ret)
1833 return ret;
1834
1835 /* Bring the device to full powered state upon system resume */
1836 pm_runtime_disable(dev);
1837 pm_runtime_set_active(dev);
1838 pm_runtime_enable(dev);
1839
1840 return 0;
1841}
1842#endif
1843
1844#ifdef CONFIG_PM_RUNTIME
1845static int msm_hsic_runtime_idle(struct device *dev)
1846{
1847 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301848 return 0;
1849}
1850
1851static int msm_hsic_runtime_suspend(struct device *dev)
1852{
1853 struct usb_hcd *hcd = dev_get_drvdata(dev);
1854 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1855
1856 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001857
1858 dbg_log_event(NULL, "Run Time PM Suspend", 0);
1859
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301860 return msm_hsic_suspend(mehci);
1861}
1862
1863static int msm_hsic_runtime_resume(struct device *dev)
1864{
1865 struct usb_hcd *hcd = dev_get_drvdata(dev);
1866 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1867
1868 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001869
1870 dbg_log_event(NULL, "Run Time PM Resume", 0);
1871
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301872 return msm_hsic_resume(mehci);
1873}
1874#endif
1875
1876#ifdef CONFIG_PM
1877static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1878 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07001879 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301880 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1881 msm_hsic_runtime_idle)
1882};
1883#endif
1884
1885static struct platform_driver ehci_msm_hsic_driver = {
1886 .probe = ehci_hsic_msm_probe,
1887 .remove = __devexit_p(ehci_hsic_msm_remove),
1888 .driver = {
1889 .name = "msm_hsic_host",
1890#ifdef CONFIG_PM
1891 .pm = &msm_hsic_dev_pm_ops,
1892#endif
1893 },
1894};