blob: 7d125987dca3e5d63247d5800cd9826e66550ada [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;
Ofir Cohen4cc55372012-11-20 11:17:24 +020079 struct regulator *hsic_gdsc;
Sudhir Sharma1673e302012-08-27 17:37:24 -070080 bool async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053081 atomic_t in_lpm;
Sudhir Sharma1673e302012-08-27 17:37:24 -070082 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080083 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080084 int wakeup_irq;
Jack Phamfe441ea2012-03-23 17:03:15 -070085 bool wakeup_irq_enabled;
Sudhir Sharma1673e302012-08-27 17:37:24 -070086 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080087 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070088 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030089 enum usb_vdd_type vdd_type;
Hemant Kumar2309eaa2012-08-14 16:46:42 -070090
91 struct work_struct bus_vote_w;
92 bool bus_vote;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070093
94 /* gp timer */
95 struct ehci_timer __iomem *timer;
96 struct completion gpt0_completion;
97 struct completion rt_completion;
98 int resume_status;
99 int resume_again;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +0530100
101 struct pm_qos_request pm_qos_req_dma;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530102};
103
Hemant Kumar105d07f2012-07-02 15:33:07 -0700104struct msm_hsic_hcd *__mehci;
105
Hemant Kumare6275972012-02-29 20:06:21 -0800106static bool debug_bus_voting_enabled = true;
Ofir Cohen4cc55372012-11-20 11:17:24 +0200107static u64 ehci_msm_hsic_dma_mask = DMA_BIT_MASK(32);
108
Hemant Kumar45d211b2012-05-31 17:58:43 -0700109
Hemant Kumar4d50a432012-08-15 09:06:35 -0700110static unsigned int enable_payload_log = 1;
111module_param(enable_payload_log, uint, S_IRUGO | S_IWUSR);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700112static unsigned int enable_dbg_log = 1;
113module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
114/*by default log ep0 and efs sync ep*/
115static unsigned int ep_addr_rxdbg_mask = 9;
116module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
117static unsigned int ep_addr_txdbg_mask = 9;
118module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
119
120/* Maximum debug message length */
Hemant Kumar4d50a432012-08-15 09:06:35 -0700121#define DBG_MSG_LEN 128UL
Hemant Kumar45d211b2012-05-31 17:58:43 -0700122
123/* Maximum number of messages */
124#define DBG_MAX_MSG 256UL
125
126#define TIME_BUF_LEN 20
Hemant Kumar4d50a432012-08-15 09:06:35 -0700127#define HEX_DUMP_LEN 72
Hemant Kumar45d211b2012-05-31 17:58:43 -0700128
129enum event_type {
130 EVENT_UNDEF = -1,
131 URB_SUBMIT,
132 URB_COMPLETE,
133 EVENT_NONE,
134};
135
136#define EVENT_STR_LEN 5
137
Hemant Kumar45d211b2012-05-31 17:58:43 -0700138static enum event_type str_to_event(const char *name)
139{
140 if (!strncasecmp("S", name, EVENT_STR_LEN))
141 return URB_SUBMIT;
142 if (!strncasecmp("C", name, EVENT_STR_LEN))
143 return URB_COMPLETE;
144 if (!strncasecmp("", name, EVENT_STR_LEN))
145 return EVENT_NONE;
146
147 return EVENT_UNDEF;
148}
149
150/*log ep0 activity*/
151static struct {
152 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
153 unsigned idx; /* index */
154 rwlock_t lck; /* lock */
155} dbg_hsic_ctrl = {
156 .idx = 0,
157 .lck = __RW_LOCK_UNLOCKED(lck)
158};
159
160static struct {
161 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
162 unsigned idx; /* index */
163 rwlock_t lck; /* lock */
164} dbg_hsic_data = {
165 .idx = 0,
166 .lck = __RW_LOCK_UNLOCKED(lck)
167};
168
169/**
170 * dbg_inc: increments debug event index
171 * @idx: buffer index
172 */
173static void dbg_inc(unsigned *idx)
174{
175 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
176}
177
178/*get_timestamp - returns time of day in us */
179static char *get_timestamp(char *tbuf)
180{
181 unsigned long long t;
182 unsigned long nanosec_rem;
183
184 t = cpu_clock(smp_processor_id());
185 nanosec_rem = do_div(t, 1000000000)/1000;
186 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
187 nanosec_rem);
188 return tbuf;
189}
190
191static int allow_dbg_log(int ep_addr)
192{
193 int dir, num;
194
195 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
196 num = ep_addr & ~USB_DIR_IN;
197 num = 1 << num;
198
199 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
200 return 1;
201 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
202 return 1;
203
204 return 0;
205}
206
Hemant Kumar4d50a432012-08-15 09:06:35 -0700207static char *get_hex_data(char *dbuf, struct urb *urb, int event, int status)
208{
209 int ep_addr = urb->ep->desc.bEndpointAddress;
210 char *ubuf = urb->transfer_buffer;
211 size_t len = event ? \
212 urb->actual_length : urb->transfer_buffer_length;
213
214 if (status == -EINPROGRESS)
215 status = 0;
216
217 /*Only dump ep in completions and epout submissions*/
218 if (len && !status &&
219 (((ep_addr & USB_DIR_IN) && event) ||
220 (!(ep_addr & USB_DIR_IN) && !event))) {
221 if (len >= 32)
222 len = 32;
223 hex_dump_to_buffer(ubuf, len, 32, 4, dbuf, HEX_DUMP_LEN, 0);
224 } else {
225 dbuf = "";
226 }
227
228 return dbuf;
229}
230
Hemant Kumar45d211b2012-05-31 17:58:43 -0700231static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
232{
233 unsigned long flags;
234 int ep_addr;
235 char tbuf[TIME_BUF_LEN];
Hemant Kumar4d50a432012-08-15 09:06:35 -0700236 char dbuf[HEX_DUMP_LEN];
Hemant Kumar45d211b2012-05-31 17:58:43 -0700237
238 if (!enable_dbg_log)
239 return;
240
241 if (!urb) {
242 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
243 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700244 "%s: %s : %u", get_timestamp(tbuf), event, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700245 dbg_inc(&dbg_hsic_ctrl.idx);
246 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
247 return;
248 }
249
250 ep_addr = urb->ep->desc.bEndpointAddress;
251 if (!allow_dbg_log(ep_addr))
252 return;
253
254 if ((ep_addr & 0x0f) == 0x0) {
255 /*submit event*/
256 if (!str_to_event(event)) {
257 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
258 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
259 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
Hemant Kumar4d50a432012-08-15 09:06:35 -0700260 "%02x %02x %04x %04x %04x %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700261 get_timestamp(tbuf), event, urb,
262 (ep_addr & USB_DIR_IN) ? "in" : "out",
263 urb->setup_packet[0], urb->setup_packet[1],
264 (urb->setup_packet[3] << 8) |
265 urb->setup_packet[2],
266 (urb->setup_packet[5] << 8) |
267 urb->setup_packet[4],
268 (urb->setup_packet[7] << 8) |
269 urb->setup_packet[6],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700270 urb->transfer_buffer_length, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700271
272 dbg_inc(&dbg_hsic_ctrl.idx);
273 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
274 } else {
275 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
276 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700277 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700278 get_timestamp(tbuf), event, urb,
279 (ep_addr & USB_DIR_IN) ? "in" : "out",
280 urb->actual_length, extra);
281
282 dbg_inc(&dbg_hsic_ctrl.idx);
283 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
284 }
285 } else {
286 write_lock_irqsave(&dbg_hsic_data.lck, flags);
287 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700288 "%s: [%s : %p]:ep%d[%s] %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700289 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
290 (ep_addr & USB_DIR_IN) ? "in" : "out",
291 str_to_event(event) ? urb->actual_length :
Hemant Kumar4d50a432012-08-15 09:06:35 -0700292 urb->transfer_buffer_length, extra,
293 enable_payload_log ? get_hex_data(dbuf, urb,
294 str_to_event(event), extra) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700295
296 dbg_inc(&dbg_hsic_data.idx);
297 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
298 }
299}
300
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530301static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
302{
303 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
304}
305
306static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
307{
308 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
309}
310
Hemant Kumar105d07f2012-07-02 15:33:07 -0700311static void dump_hsic_regs(struct usb_hcd *hcd)
312{
313 int i;
314 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
315
316 if (atomic_read(&mehci->in_lpm))
317 return;
318
319 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
320 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
321 readl_relaxed(hcd->regs + i),
322 readl_relaxed(hcd->regs + i + 4),
323 readl_relaxed(hcd->regs + i + 8),
324 readl_relaxed(hcd->regs + i + 0xc));
325}
326
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530327#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
328
Amit Blayd6ea6102012-06-07 16:26:24 +0300329#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Hemant Kumar3b743cd2012-10-17 13:48:10 -0700330#define USB_PHY_VDD_DIG_VOL_MIN 945000 /* uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700331#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530332
Lena Salman8c8ba382012-02-14 15:59:31 +0200333#define HSIC_DBG1_REG 0x38
334
Amit Blayd6ea6102012-06-07 16:26:24 +0300335static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
336 { /* VDD_CX CORNER Voting */
337 [VDD_NONE] = RPM_VREG_CORNER_NONE,
338 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
339 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
340 },
341 { /* VDD_CX Voltage Voting */
342 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
343 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
344 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
345 },
346};
347
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530348static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
349{
350 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300351 int none_vol, min_vol, max_vol;
352
353 if (!mehci->hsic_vddcx) {
354 mehci->vdd_type = VDDCX_CORNER;
355 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
356 "hsic_vdd_dig");
357 if (IS_ERR(mehci->hsic_vddcx)) {
358 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
359 "HSIC_VDDCX");
360 if (IS_ERR(mehci->hsic_vddcx)) {
361 dev_err(mehci->dev, "unable to get hsic vddcx\n");
362 return PTR_ERR(mehci->hsic_vddcx);
363 }
364 mehci->vdd_type = VDDCX;
365 }
366 }
367
368 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
369 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
370 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530371
372 if (!init)
373 goto disable_reg;
374
Amit Blayd6ea6102012-06-07 16:26:24 +0300375 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530376 if (ret) {
377 dev_err(mehci->dev, "unable to set the voltage"
378 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530379 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530380 }
381
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530382 ret = regulator_enable(mehci->hsic_vddcx);
383 if (ret) {
384 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
385 goto reg_enable_err;
386 }
387
388 return 0;
389
390disable_reg:
391 regulator_disable(mehci->hsic_vddcx);
392reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300393 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
394
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530395 return ret;
396
397}
398
Ofir Cohen4cc55372012-11-20 11:17:24 +0200399/* Global Distributed Switch Controller (GDSC) init */
400static int msm_hsic_init_gdsc(struct msm_hsic_hcd *mehci, int init)
401{
402 int ret = 0;
403
404 if (IS_ERR(mehci->hsic_gdsc))
405 return 0;
406
407 if (!mehci->hsic_gdsc) {
408 mehci->hsic_gdsc = devm_regulator_get(mehci->dev,
409 "HSIC_GDSC");
410 if (IS_ERR(mehci->hsic_gdsc))
411 return 0;
412 }
413
414 if (init) {
415 ret = regulator_enable(mehci->hsic_gdsc);
416 if (ret) {
417 dev_err(mehci->dev, "unable to enable hsic gdsc\n");
418 return ret;
419 }
420 } else {
421 regulator_disable(mehci->hsic_gdsc);
422 }
423
424 return 0;
425
426}
427
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700428static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
429{
430 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700431 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700432
433 /* initiate read operation */
434 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
435 USB_ULPI_VIEWPORT);
436
437 /* wait for completion */
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700438 while (cnt < ULPI_IO_TIMEOUT_USEC) {
439 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
440 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700441 udelay(1);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700442 cnt++;
443 }
444
445 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
446 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
447 readl_relaxed(USB_ULPI_VIEWPORT));
448 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
449 readl_relaxed(USB_PORTSC),
450 readl_relaxed(USB_USBCMD),
451 readl_relaxed(USB_FRINDEX));
452
453 /*frame counter increments afte 125us*/
454 udelay(130);
455 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
456 readl_relaxed(USB_FRINDEX));
457 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700458 }
459
460 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
461}
462
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530463static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
464{
465 struct usb_hcd *hcd = hsic_to_hcd(mehci);
466 int cnt = 0;
467
468 /* initiate write operation */
469 writel_relaxed(ULPI_RUN | ULPI_WRITE |
470 ULPI_ADDR(reg) | ULPI_DATA(val),
471 USB_ULPI_VIEWPORT);
472
473 /* wait for completion */
474 while (cnt < ULPI_IO_TIMEOUT_USEC) {
475 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
476 break;
477 udelay(1);
478 cnt++;
479 }
480
481 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700482 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
483 readl_relaxed(USB_ULPI_VIEWPORT));
484 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
485 readl_relaxed(USB_PORTSC),
486 readl_relaxed(USB_USBCMD),
487 readl_relaxed(USB_FRINDEX));
488
489 /*frame counter increments afte 125us*/
490 udelay(130);
491 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
492 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530493 return -ETIMEDOUT;
494 }
495
496 return 0;
497}
498
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700499#define HSIC_DBG1 0X38
500#define ULPI_MANUAL_ENABLE BIT(4)
501#define ULPI_LINESTATE_DATA BIT(5)
502#define ULPI_LINESTATE_STROBE BIT(6)
503static void ehci_msm_enable_ulpi_control(struct usb_hcd *hcd, u32 linestate)
504{
505 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
506 int val;
507
508 switch (linestate) {
509 case PORT_RESET:
510 val = ulpi_read(mehci, HSIC_DBG1);
511 val |= ULPI_MANUAL_ENABLE;
512 val &= ~(ULPI_LINESTATE_DATA | ULPI_LINESTATE_STROBE);
513 ulpi_write(mehci, val, HSIC_DBG1);
514 break;
515 default:
516 pr_info("%s: Unknown linestate:%0x\n", __func__, linestate);
517 }
518}
519
520static void ehci_msm_disable_ulpi_control(struct usb_hcd *hcd)
521{
522 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
523 int val;
524
525 val = ulpi_read(mehci, HSIC_DBG1);
526 val &= ~ULPI_MANUAL_ENABLE;
527 ulpi_write(mehci, val, HSIC_DBG1);
528}
529
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530530static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
531{
532 int rc = 0;
533 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800534 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530535
536 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800537
Lena Salman8c8ba382012-02-14 15:59:31 +0200538 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530539 return rc;
540
Vamsi Krishna34f01582011-12-14 19:54:42 -0800541 if (gpio_status == gpio_en)
542 return 0;
543
544 gpio_status = gpio_en;
545
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530546 if (!gpio_en)
547 goto free_gpio;
548
549 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
550 if (rc < 0) {
551 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
552 return rc;
553 }
554
555 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
556 if (rc < 0) {
557 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
558 goto free_strobe;
Hemant Kumar6fd65032012-05-23 13:02:24 -0700559 }
560
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530561 return 0;
562
563free_gpio:
564 gpio_free(pdata->data);
565free_strobe:
566 gpio_free(pdata->strobe);
567
568 return rc;
569}
570
Vamsi Krishna64b48612012-06-14 16:08:11 -0700571static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530572{
573 int ret;
574
Manu Gautam5143b252012-01-05 19:25:23 -0800575 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530576 if (ret) {
Vamsi Krishna64b48612012-06-14 16:08:11 -0700577 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
578 return;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530579 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700580 clk_disable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530581
Manu Gautam5143b252012-01-05 19:25:23 -0800582 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530583 if (ret)
Vamsi Krishna64b48612012-06-14 16:08:11 -0700584 dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530585
Vamsi Krishna64b48612012-06-14 16:08:11 -0700586 usleep_range(10000, 12000);
587
588 clk_enable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530589}
590
Vamsi Krishna64b48612012-06-14 16:08:11 -0700591#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
592#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530593#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
594#define HSIC_LV_MODE 0x04
595#define HSIC_PAD_CALIBRATION 0xA8
596#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530597#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
Ofir Cohen5dddb152012-11-14 11:18:50 +0200598
599static void msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530600{
601 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530602
Vamsi Krishna64b48612012-06-14 16:08:11 -0700603 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530604
Vamsi Krishna64b48612012-06-14 16:08:11 -0700605 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530606 writel_relaxed(0x80000000, USB_PORTSC);
Vamsi Krishna64b48612012-06-14 16:08:11 -0700607 mb();
Ofir Cohen5dddb152012-11-14 11:18:50 +0200608}
609
610static int msm_hsic_start(struct msm_hsic_hcd *mehci)
611{
612 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
613 int ret;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530614
Lena Salman8c8ba382012-02-14 15:59:31 +0200615 /* HSIC init sequence when HSIC signals (Strobe/Data) are
616 routed via GPIOs */
617 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530618
Lena Salman8c8ba382012-02-14 15:59:31 +0200619 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
620 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530621
Vamsi Krishna64b48612012-06-14 16:08:11 -0700622 mb();
623
Lena Salman8c8ba382012-02-14 15:59:31 +0200624 /*set periodic calibration interval to ~2.048sec in
625 HSIC_IO_CAL_REG */
626 ulpi_write(mehci, 0xFF, 0x33);
627
628 /* Enable periodic IO calibration in HSIC_CFG register */
629 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
630
Vamsi Krishna64b48612012-06-14 16:08:11 -0700631 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200632 ret = msm_hsic_config_gpios(mehci, 1);
633 if (ret) {
634 dev_err(mehci->dev, " gpio configuarion failed\n");
635 return ret;
636 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700637 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO PAD_CTL register */
638 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_STROBE_GPIO_PAD_CTL);
639 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_DATA_GPIO_PAD_CTL);
640
641 mb();
642
Lena Salman8c8ba382012-02-14 15:59:31 +0200643 /* Enable HSIC mode in HSIC_CFG register */
644 ulpi_write(mehci, 0x01, 0x31);
645 } else {
646 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
647 via dedicated I/O */
648
649 /* programmable length of connect signaling (33.2ns) */
650 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
651 if (ret) {
652 pr_err("%s: Unable to program length of connect "
653 "signaling\n", __func__);
654 }
655
656 /*set periodic calibration interval to ~2.048sec in
657 HSIC_IO_CAL_REG */
658 ulpi_write(mehci, 0xFF, 0x33);
659
660 /* Enable HSIC mode in HSIC_CFG register */
661 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530662 }
663
Hemant Kumar6fd65032012-05-23 13:02:24 -0700664 /*disable auto resume*/
665 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
666
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530667 return 0;
668}
669
670#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
671#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
672
673#ifdef CONFIG_PM_SLEEP
Ofir Cohen5dddb152012-11-14 11:18:50 +0200674static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
675{
676 /* reset HSIC phy */
677 msm_hsic_phy_reset(mehci);
678
679 /* HSIC init procedure (caliberation) */
680 return msm_hsic_start(mehci);
681}
682
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530683static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
684{
685 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530686 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530687 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300688 int none_vol, max_vol;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700689 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530690
691 if (atomic_read(&mehci->in_lpm)) {
692 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
693 return 0;
694 }
695
696 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700697
Sudhir Sharma1673e302012-08-27 17:37:24 -0700698 /* make sure we don't race against a remote wakeup */
699 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700700 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Sudhir Sharma1673e302012-08-27 17:37:24 -0700701 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700702 enable_irq(hcd->irq);
703 return -EBUSY;
704 }
705
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530706 /*
707 * PHY may take some time or even fail to enter into low power
708 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
709 * in failure case.
710 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700711 val = readl_relaxed(USB_PORTSC);
712 val &= ~PORT_RWC_BITS;
713 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530714 writel_relaxed(val, USB_PORTSC);
715 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
716 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
717 break;
718 udelay(1);
719 cnt++;
720 }
721
722 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
723 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530724 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530725 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530726 }
727
728 /*
729 * PHY has capability to generate interrupt asynchronously in low
730 * power mode (LPM). This interrupt is level triggered. So USB IRQ
731 * line must be disabled till async interrupt enable bit is cleared
732 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
733 * block data communication from PHY.
734 */
735 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
736 ULPI_STP_CTRL, USB_USBCMD);
737
738 /*
739 * Ensure that hardware is put in low power mode before
740 * clocks are turned OFF and VDD is allowed to minimize.
741 */
742 mb();
743
Manu Gautam28b1bac2012-01-30 16:43:06 +0530744 clk_disable_unprepare(mehci->core_clk);
745 clk_disable_unprepare(mehci->phy_clk);
746 clk_disable_unprepare(mehci->cal_clk);
747 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530748
Amit Blayd6ea6102012-06-07 16:26:24 +0300749 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
750 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
751
752 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700753 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300754 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700755
Hemant Kumare6275972012-02-29 20:06:21 -0800756 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700757 mehci->bus_vote = false;
758 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800759 }
760
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530761 atomic_set(&mehci->in_lpm, 1);
762 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700763
764 mehci->wakeup_irq_enabled = 1;
765 enable_irq_wake(mehci->wakeup_irq);
766 enable_irq(mehci->wakeup_irq);
767
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700768 if (pdata && pdata->standalone_latency)
769 pm_qos_update_request(&mehci->pm_qos_req_dma,
770 PM_QOS_DEFAULT_VALUE);
771
Sudhir Sharma1673e302012-08-27 17:37:24 -0700772 wake_unlock(&mehci->wlock);
773
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530774 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
775
776 return 0;
777}
778
779static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
780{
781 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530782 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530783 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300784 int min_vol, max_vol;
Hemant Kumard343c012012-09-06 19:57:14 -0700785 unsigned long flags;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700786 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530787
788 if (!atomic_read(&mehci->in_lpm)) {
789 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
790 return 0;
791 }
792
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700793 if (pdata && pdata->standalone_latency)
794 pm_qos_update_request(&mehci->pm_qos_req_dma,
795 pdata->standalone_latency + 1);
796
Hemant Kumard343c012012-09-06 19:57:14 -0700797 spin_lock_irqsave(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700798 if (mehci->wakeup_irq_enabled) {
799 disable_irq_wake(mehci->wakeup_irq);
800 disable_irq_nosync(mehci->wakeup_irq);
801 mehci->wakeup_irq_enabled = 0;
802 }
Hemant Kumard343c012012-09-06 19:57:14 -0700803 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700804
Sudhir Sharma1673e302012-08-27 17:37:24 -0700805 wake_lock(&mehci->wlock);
806
Hemant Kumare6275972012-02-29 20:06:21 -0800807 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700808 mehci->bus_vote = true;
809 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800810 }
811
Amit Blayd6ea6102012-06-07 16:26:24 +0300812 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
813 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
814
815 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700816 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300817 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700818
Manu Gautam28b1bac2012-01-30 16:43:06 +0530819 clk_prepare_enable(mehci->core_clk);
820 clk_prepare_enable(mehci->phy_clk);
821 clk_prepare_enable(mehci->cal_clk);
822 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530823
824 temp = readl_relaxed(USB_USBCMD);
825 temp &= ~ASYNC_INTR_CTRL;
826 temp &= ~ULPI_STP_CTRL;
827 writel_relaxed(temp, USB_USBCMD);
828
829 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
830 goto skip_phy_resume;
831
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700832 temp = readl_relaxed(USB_PORTSC);
833 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530834 writel_relaxed(temp, USB_PORTSC);
835 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
836 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
837 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
838 break;
839 udelay(1);
840 cnt++;
841 }
842
843 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
844 /*
845 * This is a fatal error. Reset the link and
846 * PHY to make hsic working.
847 */
848 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530849 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530850 msm_hsic_reset(mehci);
851 }
852
853skip_phy_resume:
854
Hemant Kumar6fd65032012-05-23 13:02:24 -0700855 usb_hcd_resume_root_hub(hcd);
856
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530857 atomic_set(&mehci->in_lpm, 0);
858
859 if (mehci->async_int) {
860 mehci->async_int = false;
861 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700862 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700863 }
864
Sudhir Sharma1673e302012-08-27 17:37:24 -0700865 if (atomic_read(&mehci->pm_usage_cnt)) {
866 atomic_set(&mehci->pm_usage_cnt, 0);
867 pm_runtime_put_noidle(mehci->dev);
868 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700869
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530870 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
871
872 return 0;
873}
874#endif
875
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700876static void ehci_hsic_bus_vote_w(struct work_struct *w)
877{
878 struct msm_hsic_hcd *mehci =
879 container_of(w, struct msm_hsic_hcd, bus_vote_w);
880 int ret;
881
882 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
883 mehci->bus_vote);
884 if (ret)
885 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
886 __func__, ret);
887}
888
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700889#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530890static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
891{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700892 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530893 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700894 u32 status;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530895
896 if (atomic_read(&mehci->in_lpm)) {
897 disable_irq_nosync(hcd->irq);
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700898 dev_dbg(mehci->dev, "phy async intr\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530899 mehci->async_int = true;
900 pm_runtime_get(mehci->dev);
901 return IRQ_HANDLED;
902 }
903
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700904 status = ehci_readl(ehci, &ehci->regs->status);
905
906 if (status & STS_GPTIMER0_INTERRUPT) {
907 int timeleft;
908
909 dbg_log_event(NULL, "FPR: gpt0_isr", 0);
910
911 timeleft = GPT_CNT(ehci_readl(ehci,
912 &mehci->timer->gptimer1_ctrl));
913 if (timeleft) {
914 ehci_writel(ehci, ehci_readl(ehci,
915 &ehci->regs->command) | CMD_RUN,
916 &ehci->regs->command);
917 } else
918 mehci->resume_again = 1;
919
920 dbg_log_event(NULL, "FPR: timeleft", timeleft);
921
922 complete(&mehci->gpt0_completion);
923 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
924 }
925
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530926 return ehci_irq(hcd);
927}
928
929static int ehci_hsic_reset(struct usb_hcd *hcd)
930{
931 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700932 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530933 int retval;
934
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700935 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530936 ehci->caps = USB_CAPLENGTH;
937 ehci->regs = USB_CAPLENGTH +
938 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
939 dbg_hcs_params(ehci, "reset");
940 dbg_hcc_params(ehci, "reset");
941
942 /* cache the data to minimize the chip reads*/
943 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
944
945 hcd->has_tt = 1;
946 ehci->sbrn = HCD_USB2;
947
948 retval = ehci_halt(ehci);
949 if (retval)
950 return retval;
951
952 /* data structure init */
953 retval = ehci_init(hcd);
954 if (retval)
955 return retval;
956
957 retval = ehci_reset(ehci);
958 if (retval)
959 return retval;
960
961 /* bursts of unspecified length. */
962 writel_relaxed(0, USB_AHBBURST);
963 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530964 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530965 /* Disable streaming mode and select host mode */
966 writel_relaxed(0x13, USB_USBMODE);
967
968 ehci_port_power(ehci, 1);
969 return 0;
970}
971
Jack Phamc0d41732012-09-28 17:45:38 -0700972#ifdef CONFIG_PM
973
Hemant Kumar45d211b2012-05-31 17:58:43 -0700974static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
975{
Pavankumar Kondetia723f742012-09-14 14:02:36 +0530976 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
977
978 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
979 dbg_log_event(NULL, "RH suspend attempt failed", 0);
980 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
981 __func__);
982 return -EAGAIN;
983 }
984
Hemant Kumar45d211b2012-05-31 17:58:43 -0700985 dbg_log_event(NULL, "Suspend RH", 0);
986 return ehci_bus_suspend(hcd);
987}
988
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700989#define RESUME_RETRY_LIMIT 3
990#define RESUME_SIGNAL_TIME_MS (21 * 999)
991#define RESUME_SIGNAL_TIME_SOF_MS (23 * 999)
992static int msm_hsic_resume_thread(void *data)
993{
994 struct msm_hsic_hcd *mehci = data;
995 struct usb_hcd *hcd = hsic_to_hcd(mehci);
996 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
997 u32 temp;
998 unsigned long resume_needed = 0;
999 int retry_cnt = 0;
1000 int tight_resume = 0;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301001 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001002
1003 dbg_log_event(NULL, "Resume RH", 0);
1004
1005 /* keep delay between bus states */
1006 if (time_before(jiffies, ehci->next_statechange))
1007 usleep_range(5000, 5000);
1008
1009 spin_lock_irq(&ehci->lock);
1010 if (!HCD_HW_ACCESSIBLE(hcd)) {
1011 spin_unlock_irq(&ehci->lock);
1012 mehci->resume_status = -ESHUTDOWN;
1013 complete(&mehci->rt_completion);
1014 return 0;
1015 }
1016
1017 if (unlikely(ehci->debug)) {
1018 if (!dbgp_reset_prep())
1019 ehci->debug = NULL;
1020 else
1021 dbgp_external_startup();
1022 }
1023
1024 /* at least some APM implementations will try to deliver
1025 * IRQs right away, so delay them until we're ready.
1026 */
1027 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
1028
1029 /* re-init operational registers */
1030 ehci_writel(ehci, 0, &ehci->regs->segment);
1031 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
1032 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
1033
1034 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
1035 if (ehci->resume_sof_bug)
1036 ehci->command &= ~CMD_RUN;
1037
1038 /* restore CMD_RUN, framelist size, and irq threshold */
1039 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1040
1041 /* manually resume the ports we suspended during bus_suspend() */
1042resume_again:
1043 if (retry_cnt >= RESUME_RETRY_LIMIT) {
1044 pr_info("retry count(%d) reached max, resume in tight loop\n",
1045 retry_cnt);
1046 tight_resume = 1;
1047 }
1048
1049
1050 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1051 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
1052 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
1053 temp |= PORT_RESUME;
1054 set_bit(0, &resume_needed);
1055 }
1056 dbg_log_event(NULL, "FPR: Set", temp);
1057 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1058
1059 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1060 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1061 * controller in MSM clears FPR bit after driving the resume signal for
1062 * 20ms. Workaround is to stop SOFs before driving resume and then start
1063 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1064 * completion otherwise peripheral may enter undefined state. As
1065 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1066 * to time the resume sequence. If driver exceeds allowable time SOFs,
1067 * repeat the resume process.
1068 */
1069 if (ehci->resume_sof_bug && resume_needed) {
1070 if (!tight_resume) {
1071 mehci->resume_again = 0;
1072 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_MS),
1073 &mehci->timer->gptimer0_ld);
1074 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1075 &mehci->timer->gptimer0_ctrl);
1076 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1077 &ehci->regs->intr_enable);
1078
1079 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_SOF_MS),
1080 &mehci->timer->gptimer1_ld);
1081 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1082 &mehci->timer->gptimer1_ctrl);
1083
1084 spin_unlock_irq(&ehci->lock);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301085 if (pdata && pdata->swfi_latency)
1086 pm_qos_update_request(&mehci->pm_qos_req_dma,
1087 pdata->swfi_latency + 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001088 wait_for_completion(&mehci->gpt0_completion);
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001089 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301090 pm_qos_update_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001091 pdata->standalone_latency + 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001092 spin_lock_irq(&ehci->lock);
1093 } else {
1094 dbg_log_event(NULL, "FPR: Tightloop", 0);
1095 /* do the resume in a tight loop */
1096 handshake(ehci, &ehci->regs->port_status[0],
1097 PORT_RESUME, 0, 22 * 1000);
1098 ehci_writel(ehci, ehci_readl(ehci,
1099 &ehci->regs->command) | CMD_RUN,
1100 &ehci->regs->command);
1101 }
1102
1103 if (mehci->resume_again) {
1104 int temp;
1105
1106 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1107 pr_info("FPR: retry count: %d\n", retry_cnt);
1108 spin_unlock_irq(&ehci->lock);
1109 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1110 temp &= ~PORT_RWC_BITS;
1111 temp |= PORT_SUSPEND;
1112 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1113 /* Keep the bus idle for 5ms so that peripheral
1114 * can detect and initiate suspend
1115 */
1116 usleep_range(5000, 5000);
1117 dbg_log_event(NULL,
1118 "FPR: RResume",
1119 ehci_readl(ehci, &ehci->regs->port_status[0]));
1120 spin_lock_irq(&ehci->lock);
1121 mehci->resume_again = 0;
1122 retry_cnt++;
1123 goto resume_again;
1124 }
1125 }
1126
1127 dbg_log_event(NULL, "FPR: RT-Done", 0);
1128 mehci->resume_status = 1;
1129 spin_unlock_irq(&ehci->lock);
1130
1131 complete(&mehci->rt_completion);
1132
1133 return 0;
1134}
1135
Hemant Kumar45d211b2012-05-31 17:58:43 -07001136static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1137{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001138 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1139 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1140 u32 temp;
1141 struct task_struct *resume_thread = NULL;
1142
1143 mehci->resume_status = 0;
1144 resume_thread = kthread_run(msm_hsic_resume_thread,
1145 mehci, "hsic_resume_thread");
1146 if (IS_ERR(resume_thread)) {
1147 pr_err("Error creating resume thread:%lu\n",
1148 PTR_ERR(resume_thread));
1149 return PTR_ERR(resume_thread);
1150 }
1151
1152 wait_for_completion(&mehci->rt_completion);
1153
1154 if (mehci->resume_status < 0)
1155 return mehci->resume_status;
1156
1157 dbg_log_event(NULL, "FPR: Wokeup", 0);
1158 spin_lock_irq(&ehci->lock);
1159 (void) ehci_readl(ehci, &ehci->regs->command);
1160
1161 temp = 0;
1162 if (ehci->async->qh_next.qh)
1163 temp |= CMD_ASE;
1164 if (ehci->periodic_sched)
1165 temp |= CMD_PSE;
1166 if (temp) {
1167 ehci->command |= temp;
1168 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1169 }
1170
1171 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1172 hcd->state = HC_STATE_RUNNING;
1173 ehci->rh_state = EHCI_RH_RUNNING;
1174
1175 /* Now we can safely re-enable irqs */
1176 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1177
1178 spin_unlock_irq(&ehci->lock);
1179
1180 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001181}
1182
Jack Phamc0d41732012-09-28 17:45:38 -07001183#else
1184
1185#define ehci_hsic_bus_suspend NULL
1186#define ehci_hsic_bus_resume NULL
1187
1188#endif /* CONFIG_PM */
1189
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001190static void ehci_msm_set_autosuspend_delay(struct usb_device *dev)
1191{
1192 if (!dev->parent) /*for root hub no delay*/
1193 pm_runtime_set_autosuspend_delay(&dev->dev, 0);
1194 else
1195 pm_runtime_set_autosuspend_delay(&dev->dev, 200);
1196}
1197
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301198static struct hc_driver msm_hsic_driver = {
1199 .description = hcd_name,
1200 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1201 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1202
1203 /*
1204 * generic hardware linkage
1205 */
1206 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001207 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301208
1209 .reset = ehci_hsic_reset,
1210 .start = ehci_run,
1211
1212 .stop = ehci_stop,
1213 .shutdown = ehci_shutdown,
1214
1215 /*
1216 * managing i/o requests and associated device resources
1217 */
Hemant Kumar4d50a432012-08-15 09:06:35 -07001218 .urb_enqueue = ehci_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301219 .urb_dequeue = ehci_urb_dequeue,
1220 .endpoint_disable = ehci_endpoint_disable,
1221 .endpoint_reset = ehci_endpoint_reset,
1222 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1223
1224 /*
1225 * scheduling support
1226 */
1227 .get_frame_number = ehci_get_frame,
1228
1229 /*
1230 * root hub support
1231 */
1232 .hub_status_data = ehci_hub_status_data,
1233 .hub_control = ehci_hub_control,
1234 .relinquish_port = ehci_relinquish_port,
1235 .port_handed_over = ehci_port_handed_over,
1236
1237 /*
1238 * PM support
1239 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001240 .bus_suspend = ehci_hsic_bus_suspend,
1241 .bus_resume = ehci_hsic_bus_resume,
1242
Hemant Kumar4d50a432012-08-15 09:06:35 -07001243 .log_urb = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001244 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001245
1246 .enable_ulpi_control = ehci_msm_enable_ulpi_control,
1247 .disable_ulpi_control = ehci_msm_disable_ulpi_control,
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001248
1249 .set_autosuspend_delay = ehci_msm_set_autosuspend_delay,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301250};
1251
1252static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1253{
1254 int ret = 0;
1255
1256 if (!init)
1257 goto put_clocks;
1258
Lena Salman8c8ba382012-02-14 15:59:31 +02001259 /*core_clk is required for LINK protocol engine
1260 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001261 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1262 if (IS_ERR(mehci->core_clk)) {
1263 dev_err(mehci->dev, "failed to get core_clk\n");
1264 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301265 return ret;
1266 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301267
Lena Salman8c8ba382012-02-14 15:59:31 +02001268 /* alt_core_clk is for LINK to be used during PHY RESET
1269 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001270 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
1271 if (IS_ERR(mehci->alt_core_clk)) {
1272 dev_err(mehci->dev, "failed to core_clk\n");
1273 ret = PTR_ERR(mehci->alt_core_clk);
1274 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301275 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301276
Lena Salman8c8ba382012-02-14 15:59:31 +02001277 /* phy_clk is required for HSIC PHY operation
1278 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001279 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1280 if (IS_ERR(mehci->phy_clk)) {
1281 dev_err(mehci->dev, "failed to get phy_clk\n");
1282 ret = PTR_ERR(mehci->phy_clk);
1283 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301284 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301285
1286 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001287 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301288 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001289 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301290 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001291 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301292 }
1293 clk_set_rate(mehci->cal_clk, 10000000);
1294
1295 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001296 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301297 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001298 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301299 ret = PTR_ERR(mehci->ahb_clk);
1300 goto put_cal_clk;
1301 }
1302
Manu Gautam28b1bac2012-01-30 16:43:06 +05301303 clk_prepare_enable(mehci->core_clk);
1304 clk_prepare_enable(mehci->phy_clk);
1305 clk_prepare_enable(mehci->cal_clk);
1306 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301307
1308 return 0;
1309
1310put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001311 if (!atomic_read(&mehci->in_lpm)) {
1312 clk_disable_unprepare(mehci->core_clk);
1313 clk_disable_unprepare(mehci->phy_clk);
1314 clk_disable_unprepare(mehci->cal_clk);
1315 clk_disable_unprepare(mehci->ahb_clk);
1316 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301317 clk_put(mehci->ahb_clk);
1318put_cal_clk:
1319 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001320put_phy_clk:
1321 clk_put(mehci->phy_clk);
1322put_alt_core_clk:
1323 clk_put(mehci->alt_core_clk);
1324put_core_clk:
1325 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301326
1327 return ret;
1328}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001329static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1330{
1331 struct msm_hsic_hcd *mehci = dev_id;
1332
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001333 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001334
1335 if (mehci)
1336 msm_hsic_config_gpios(mehci, 0);
1337
1338 return IRQ_HANDLED;
1339}
1340
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001341static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1342{
1343 struct msm_hsic_hcd *mehci = data;
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301344 int ret;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001345
Hemant Kumar6fd65032012-05-23 13:02:24 -07001346 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001347 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001348 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
1349 __func__, mehci->wakeup_int_cnt);
1350
Sudhir Sharma1673e302012-08-27 17:37:24 -07001351 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001352
Hemant Kumard343c012012-09-06 19:57:14 -07001353 spin_lock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001354 if (mehci->wakeup_irq_enabled) {
1355 mehci->wakeup_irq_enabled = 0;
1356 disable_irq_wake(irq);
1357 disable_irq_nosync(irq);
1358 }
Hemant Kumard343c012012-09-06 19:57:14 -07001359 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001360
Sudhir Sharma1673e302012-08-27 17:37:24 -07001361 if (!atomic_read(&mehci->pm_usage_cnt)) {
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301362 ret = pm_runtime_get(mehci->dev);
1363 /*
1364 * HSIC runtime resume can race with us.
1365 * if we are active (ret == 1) or resuming
1366 * (ret == -EINPROGRESS), decrement the
1367 * PM usage counter before returning.
1368 */
1369 if ((ret == 1) || (ret == -EINPROGRESS))
1370 pm_runtime_put_noidle(mehci->dev);
1371 else
1372 atomic_set(&mehci->pm_usage_cnt, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001373 }
1374
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001375 return IRQ_HANDLED;
1376}
1377
Hemant Kumare6275972012-02-29 20:06:21 -08001378static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1379{
1380 if (debug_bus_voting_enabled)
1381 seq_printf(s, "enabled\n");
1382 else
1383 seq_printf(s, "disabled\n");
1384
1385 return 0;
1386}
1387
1388static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1389{
1390 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1391}
1392
1393static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1394 const char __user *ubuf, size_t count, loff_t *ppos)
1395{
1396 char buf[8];
1397 int ret;
1398 struct seq_file *s = file->private_data;
1399 struct msm_hsic_hcd *mehci = s->private;
1400
1401 memset(buf, 0x00, sizeof(buf));
1402
1403 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1404 return -EFAULT;
1405
1406 if (!strncmp(buf, "enable", 6)) {
1407 /* Do not vote here. Let hsic driver decide when to vote */
1408 debug_bus_voting_enabled = true;
1409 } else {
1410 debug_bus_voting_enabled = false;
1411 if (mehci->bus_perf_client) {
1412 ret = msm_bus_scale_client_update_request(
1413 mehci->bus_perf_client, 0);
1414 if (ret)
1415 dev_err(mehci->dev, "%s: Failed to devote "
1416 "for bus bw %d\n", __func__, ret);
1417 }
1418 }
1419
1420 return count;
1421}
1422
1423const struct file_operations ehci_hsic_msm_bus_fops = {
1424 .open = ehci_hsic_msm_bus_open,
1425 .read = seq_read,
1426 .write = ehci_hsic_msm_bus_write,
1427 .llseek = seq_lseek,
1428 .release = single_release,
1429};
1430
Hemant Kumar6fd65032012-05-23 13:02:24 -07001431static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1432{
1433 struct msm_hsic_hcd *mehci = s->private;
1434
1435 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1436
1437 return 0;
1438}
1439
1440static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1441{
1442 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1443}
1444
1445const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1446 .open = ehci_hsic_msm_wakeup_cnt_open,
1447 .read = seq_read,
1448 .llseek = seq_lseek,
1449 .release = single_release,
1450};
1451
Hemant Kumar45d211b2012-05-31 17:58:43 -07001452static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1453{
1454 unsigned long flags;
1455 unsigned i;
1456
1457 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1458
1459 i = dbg_hsic_data.idx;
1460 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1461 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1462 continue;
1463 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1464 }
1465
1466 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1467
1468 return 0;
1469}
1470
1471static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1472{
1473 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1474}
1475
1476const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1477 .open = ehci_hsic_msm_data_events_open,
1478 .read = seq_read,
1479 .llseek = seq_lseek,
1480 .release = single_release,
1481};
1482
1483static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1484{
1485 unsigned long flags;
1486 unsigned i;
1487
1488 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1489
1490 i = dbg_hsic_ctrl.idx;
1491 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1492 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1493 continue;
1494 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1495 }
1496
1497 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1498
1499 return 0;
1500}
1501
1502static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1503{
1504 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1505}
1506
1507const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1508 .open = ehci_hsic_msm_ctrl_events_open,
1509 .read = seq_read,
1510 .llseek = seq_lseek,
1511 .release = single_release,
1512};
1513
Hemant Kumare6275972012-02-29 20:06:21 -08001514static struct dentry *ehci_hsic_msm_dbg_root;
1515static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1516{
1517 struct dentry *ehci_hsic_msm_dentry;
1518
1519 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1520
1521 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1522 return -ENODEV;
1523
1524 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1525 S_IRUGO | S_IWUSR,
1526 ehci_hsic_msm_dbg_root, mehci,
1527 &ehci_hsic_msm_bus_fops);
1528
1529 if (!ehci_hsic_msm_dentry) {
1530 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1531 return -ENODEV;
1532 }
1533
Hemant Kumar6fd65032012-05-23 13:02:24 -07001534 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1535 S_IRUGO,
1536 ehci_hsic_msm_dbg_root, mehci,
1537 &ehci_hsic_msm_wakeup_cnt_fops);
1538
1539 if (!ehci_hsic_msm_dentry) {
1540 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1541 return -ENODEV;
1542 }
1543
Hemant Kumar45d211b2012-05-31 17:58:43 -07001544 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1545 S_IRUGO,
1546 ehci_hsic_msm_dbg_root, mehci,
1547 &ehci_hsic_msm_dbg_ctrl_fops);
1548
1549 if (!ehci_hsic_msm_dentry) {
1550 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1551 return -ENODEV;
1552 }
1553
1554 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1555 S_IRUGO,
1556 ehci_hsic_msm_dbg_root, mehci,
1557 &ehci_hsic_msm_dbg_data_fops);
1558
1559 if (!ehci_hsic_msm_dentry) {
1560 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1561 return -ENODEV;
1562 }
1563
Hemant Kumare6275972012-02-29 20:06:21 -08001564 return 0;
1565}
1566
1567static void ehci_hsic_msm_debugfs_cleanup(void)
1568{
1569 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1570}
1571
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301572static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1573{
1574 struct usb_hcd *hcd;
1575 struct resource *res;
1576 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301577 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301578 int ret;
1579
1580 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1581
Ofir Cohen4cc55372012-11-20 11:17:24 +02001582 if (!pdev->dev.dma_mask)
1583 pdev->dev.dma_mask = &ehci_msm_hsic_dma_mask;
1584 if (!pdev->dev.coherent_dma_mask)
1585 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
1586
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301587 /* After parent device's probe is executed, it will be put in suspend
1588 * mode. When child device's probe is called, driver core is not
1589 * resuming parent device due to which parent will be in suspend even
1590 * though child is active. Hence resume the parent device explicitly.
1591 */
1592 if (pdev->dev.parent)
1593 pm_runtime_get_sync(pdev->dev.parent);
1594
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301595 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1596 dev_name(&pdev->dev));
1597 if (!hcd) {
1598 dev_err(&pdev->dev, "Unable to create HCD\n");
1599 return -ENOMEM;
1600 }
1601
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301602 hcd_to_bus(hcd)->skip_resume = true;
1603
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301604 hcd->irq = platform_get_irq(pdev, 0);
1605 if (hcd->irq < 0) {
1606 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1607 ret = hcd->irq;
1608 goto put_hcd;
1609 }
1610
1611 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1612 if (!res) {
1613 dev_err(&pdev->dev, "Unable to get memory resource\n");
1614 ret = -ENODEV;
1615 goto put_hcd;
1616 }
1617
1618 hcd->rsrc_start = res->start;
1619 hcd->rsrc_len = resource_size(res);
1620 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1621 if (!hcd->regs) {
1622 dev_err(&pdev->dev, "ioremap failed\n");
1623 ret = -ENOMEM;
1624 goto put_hcd;
1625 }
1626
1627 mehci = hcd_to_hsic(hcd);
1628 mehci->dev = &pdev->dev;
Hemant Kumar30d361c2012-08-20 14:44:40 -07001629 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301630
Hemant Kumard343c012012-09-06 19:57:14 -07001631 spin_lock_init(&mehci->wakeup_lock);
1632
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001633 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001634 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001635
Hemant Kumare4040492012-06-21 17:35:42 -07001636 mehci->ehci.resume_sof_bug = 1;
1637
Hemant Kumar30d361c2012-08-20 14:44:40 -07001638 if (pdata)
1639 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Hemant Kumar933e0402012-05-22 11:11:40 -07001640
Ofir Cohen4cc55372012-11-20 11:17:24 +02001641 ret = msm_hsic_init_gdsc(mehci, 1);
1642 if (ret) {
1643 dev_err(&pdev->dev, "unable to initialize GDSC\n");
1644 ret = -ENODEV;
1645 goto put_hcd;
1646 }
1647
Vamsi Krishna34f01582011-12-14 19:54:42 -08001648 res = platform_get_resource_byname(pdev,
1649 IORESOURCE_IRQ,
1650 "peripheral_status_irq");
1651 if (res)
1652 mehci->peripheral_status_irq = res->start;
1653
Jack Pham0cc75c42012-10-10 02:03:50 +02001654 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "wakeup");
Hemant Kumar6fd65032012-05-23 13:02:24 -07001655 if (res) {
Jack Pham0cc75c42012-10-10 02:03:50 +02001656 mehci->wakeup_irq = res->start;
Hemant Kumar6fd65032012-05-23 13:02:24 -07001657 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1658 }
1659
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301660 ret = msm_hsic_init_clocks(mehci, 1);
1661 if (ret) {
1662 dev_err(&pdev->dev, "unable to initialize clocks\n");
1663 ret = -ENODEV;
1664 goto unmap;
1665 }
1666
1667 ret = msm_hsic_init_vddcx(mehci, 1);
1668 if (ret) {
1669 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1670 ret = -ENODEV;
1671 goto deinit_clocks;
1672 }
1673
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001674 init_completion(&mehci->rt_completion);
1675 init_completion(&mehci->gpt0_completion);
Ofir Cohen5dddb152012-11-14 11:18:50 +02001676
1677 msm_hsic_phy_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301678
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001679 ehci_wq = create_singlethread_workqueue("ehci_wq");
1680 if (!ehci_wq) {
1681 dev_err(&pdev->dev, "unable to create workqueue\n");
1682 ret = -ENOMEM;
1683 goto deinit_vddcx;
1684 }
1685
1686 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1687
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301688 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1689 if (ret) {
1690 dev_err(&pdev->dev, "unable to register HCD\n");
Ofir Cohen5dddb152012-11-14 11:18:50 +02001691 goto destroy_wq;
1692 }
1693
1694 ret = msm_hsic_start(mehci);
1695 if (ret) {
1696 dev_err(&pdev->dev, "unable to initialize PHY\n");
1697 goto destroy_wq;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301698 }
1699
1700 device_init_wakeup(&pdev->dev, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001701 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1702 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001703
1704 if (mehci->peripheral_status_irq) {
1705 ret = request_threaded_irq(mehci->peripheral_status_irq,
1706 NULL, hsic_peripheral_status_change,
1707 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1708 | IRQF_SHARED,
1709 "hsic_peripheral_status", mehci);
1710 if (ret)
1711 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1712 __func__, mehci->peripheral_status_irq, ret);
1713 }
1714
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001715 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001716 if (mehci->wakeup_irq) {
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07001717 /* In case if wakeup gpio is pulled high at this point
1718 * remote wakeup interrupt fires right after request_irq.
1719 * Remote wake up interrupt only needs to be enabled when
1720 * HSIC bus goes to suspend.
1721 */
1722 irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001723 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001724 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001725 "msm_hsic_wakeup", mehci);
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07001726 if (ret) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001727 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1728 mehci->wakeup_irq, ret);
1729 mehci->wakeup_irq = 0;
1730 }
1731 }
1732
Hemant Kumare6275972012-02-29 20:06:21 -08001733 ret = ehci_hsic_msm_debugfs_init(mehci);
1734 if (ret)
1735 dev_dbg(&pdev->dev, "mode debugfs file is"
1736 "not available\n");
1737
1738 if (pdata && pdata->bus_scale_table) {
1739 mehci->bus_perf_client =
1740 msm_bus_scale_register_client(pdata->bus_scale_table);
1741 /* Configure BUS performance parameters for MAX bandwidth */
1742 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001743 mehci->bus_vote = true;
1744 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001745 } else {
1746 dev_err(&pdev->dev, "%s: Failed to register BUS "
1747 "scaling client!!\n", __func__);
1748 }
1749 }
1750
Hemant Kumar105d07f2012-07-02 15:33:07 -07001751 __mehci = mehci;
1752
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001753 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301754 pm_qos_add_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001755 PM_QOS_CPU_DMA_LATENCY, pdata->standalone_latency + 1);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301756
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301757 /*
1758 * This pdev->dev is assigned parent of root-hub by USB core,
1759 * hence, runtime framework automatically calls this driver's
1760 * runtime APIs based on root-hub's state.
1761 */
1762 pm_runtime_set_active(&pdev->dev);
1763 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301764 /* Decrement the parent device's counter after probe.
1765 * As child is active, parent will not be put into
1766 * suspend mode.
1767 */
1768 if (pdev->dev.parent)
1769 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301770
1771 return 0;
1772
Ofir Cohen5dddb152012-11-14 11:18:50 +02001773destroy_wq:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001774 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301775deinit_vddcx:
1776 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02001777 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301778deinit_clocks:
1779 msm_hsic_init_clocks(mehci, 0);
1780unmap:
1781 iounmap(hcd->regs);
1782put_hcd:
1783 usb_put_hcd(hcd);
1784
1785 return ret;
1786}
1787
1788static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1789{
1790 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1791 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301792 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1793
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001794 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301795 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301796
Vamsi Krishna34f01582011-12-14 19:54:42 -08001797 if (mehci->peripheral_status_irq)
1798 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001799
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001800 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001801 if (mehci->wakeup_irq_enabled)
1802 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001803 free_irq(mehci->wakeup_irq, mehci);
1804 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001805
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001806 /*
1807 * If the update request is called after unregister, the request will
1808 * fail. Results are undefined if unregister is called in the middle of
1809 * update request.
1810 */
1811 mehci->bus_vote = false;
1812 cancel_work_sync(&mehci->bus_vote_w);
1813
Hemant Kumare6275972012-02-29 20:06:21 -08001814 if (mehci->bus_perf_client)
1815 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1816
1817 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301818 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301819 pm_runtime_set_suspended(&pdev->dev);
1820
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001821 destroy_workqueue(ehci_wq);
1822
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301823 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301824 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301825 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02001826 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301827
1828 msm_hsic_init_clocks(mehci, 0);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001829 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301830 iounmap(hcd->regs);
1831 usb_put_hcd(hcd);
1832
1833 return 0;
1834}
1835
1836#ifdef CONFIG_PM_SLEEP
1837static int msm_hsic_pm_suspend(struct device *dev)
1838{
Jack Phambe05fbb2012-05-16 10:56:26 -07001839 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301840 struct usb_hcd *hcd = dev_get_drvdata(dev);
1841 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1842
1843 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1844
Hemant Kumar45d211b2012-05-31 17:58:43 -07001845 dbg_log_event(NULL, "PM Suspend", 0);
1846
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301847 if (device_may_wakeup(dev))
1848 enable_irq_wake(hcd->irq);
1849
Jack Phambe05fbb2012-05-16 10:56:26 -07001850 ret = msm_hsic_suspend(mehci);
1851
1852 if (ret && device_may_wakeup(dev))
1853 disable_irq_wake(hcd->irq);
1854
1855 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001856}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301857
Jack Pham16b06f82012-08-14 20:03:59 -07001858static int msm_hsic_pm_suspend_noirq(struct device *dev)
1859{
1860 struct usb_hcd *hcd = dev_get_drvdata(dev);
1861 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1862
1863 if (mehci->async_int) {
1864 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
1865 return -EBUSY;
1866 }
1867
1868 return 0;
1869}
1870
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301871static int msm_hsic_pm_resume(struct device *dev)
1872{
1873 int ret;
1874 struct usb_hcd *hcd = dev_get_drvdata(dev);
1875 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1876
Jack Pham16b06f82012-08-14 20:03:59 -07001877 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001878 dbg_log_event(NULL, "PM Resume", 0);
1879
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301880 if (device_may_wakeup(dev))
1881 disable_irq_wake(hcd->irq);
1882
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301883 /*
1884 * Keep HSIC in Low Power Mode if system is resumed
1885 * by any other wakeup source. HSIC is resumed later
1886 * when remote wakeup is received or interface driver
1887 * start I/O.
1888 */
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05301889 if (!atomic_read(&mehci->pm_usage_cnt) &&
1890 pm_runtime_suspended(dev))
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301891 return 0;
1892
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301893 ret = msm_hsic_resume(mehci);
1894 if (ret)
1895 return ret;
1896
1897 /* Bring the device to full powered state upon system resume */
1898 pm_runtime_disable(dev);
1899 pm_runtime_set_active(dev);
1900 pm_runtime_enable(dev);
1901
1902 return 0;
1903}
1904#endif
1905
1906#ifdef CONFIG_PM_RUNTIME
1907static int msm_hsic_runtime_idle(struct device *dev)
1908{
1909 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301910 return 0;
1911}
1912
1913static int msm_hsic_runtime_suspend(struct device *dev)
1914{
1915 struct usb_hcd *hcd = dev_get_drvdata(dev);
1916 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1917
1918 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001919
1920 dbg_log_event(NULL, "Run Time PM Suspend", 0);
1921
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301922 return msm_hsic_suspend(mehci);
1923}
1924
1925static int msm_hsic_runtime_resume(struct device *dev)
1926{
1927 struct usb_hcd *hcd = dev_get_drvdata(dev);
1928 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1929
1930 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001931
1932 dbg_log_event(NULL, "Run Time PM Resume", 0);
1933
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301934 return msm_hsic_resume(mehci);
1935}
1936#endif
1937
1938#ifdef CONFIG_PM
1939static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1940 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07001941 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301942 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1943 msm_hsic_runtime_idle)
1944};
1945#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02001946static const struct of_device_id hsic_host_dt_match[] = {
1947 { .compatible = "qcom,hsic-host",
1948 },
1949 {}
1950};
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301951static struct platform_driver ehci_msm_hsic_driver = {
1952 .probe = ehci_hsic_msm_probe,
1953 .remove = __devexit_p(ehci_hsic_msm_remove),
1954 .driver = {
1955 .name = "msm_hsic_host",
1956#ifdef CONFIG_PM
1957 .pm = &msm_hsic_dev_pm_ops,
1958#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02001959 .of_match_table = hsic_host_dt_match,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301960 },
1961};