blob: 48b4484ba67738e44f240653bc209e8a8c581f2b [file] [log] [blame]
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301/* ehci-msm-hsic.c - HSUSB Host Controller Driver Implementation
2 *
Pavankumar Kondetibbd05822013-01-28 17:04:39 +05303 * Copyright (c) 2011-2013, Linux Foundation. All rights reserved.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05304 *
5 * Partly derived from ehci-fsl.c and ehci-hcd.c
6 * Copyright (c) 2000-2004 by David Brownell
7 * Copyright (c) 2005 MontaVista Software
8 *
9 * All source code in this file is licensed under the following license except
10 * where indicated.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published
14 * by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * See the GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, you can find it at http://www.fsf.org
23 */
24
25#include <linux/platform_device.h>
26#include <linux/clk.h>
27#include <linux/err.h>
Hemant Kumare6275972012-02-29 20:06:21 -080028#include <linux/debugfs.h>
29#include <linux/seq_file.h>
Ajay Dudaniab3bf192012-08-28 09:58:04 -070030#include <linux/wakelock.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053031#include <linux/pm_runtime.h>
32#include <linux/regulator/consumer.h>
33
34#include <linux/usb/msm_hsusb_hw.h>
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +053035#include <linux/usb/msm_hsusb.h>
36#include <linux/gpio.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030037#include <linux/spinlock.h>
Ajay Dudani11ab1d52012-08-17 17:12:26 -070038#include <linux/kthread.h>
39#include <linux/wait.h>
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +053040#include <linux/pm_qos.h>
Hemant Kumar5e386632012-08-30 14:23:38 -070041#include <linux/irq.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;
Ajay Dudani11ab1d52012-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 Kumar4cd49e12012-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;
Pavankumar Kondetibbd05822013-01-28 17:04:39 +053079 atomic_t async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053080 atomic_t in_lpm;
Ajay Dudaniab3bf192012-08-28 09:58:04 -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;
Hemant Kumar6fd65032012-05-23 13:02:24 -070084 int wakeup_gpio;
Jack Phamfe441ea2012-03-23 17:03:15 -070085 bool wakeup_irq_enabled;
Ajay Dudaniab3bf192012-08-28 09:58:04 -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;
Ajay Dudani11ab1d52012-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 Kondeti9ecc39c2013-01-29 14:41:58 +0530100 int bus_reset;
101 int reset_again;
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +0530102
103 struct pm_qos_request pm_qos_req_dma;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530104};
105
Hemant Kumar105d07f2012-07-02 15:33:07 -0700106struct msm_hsic_hcd *__mehci;
107
Hemant Kumare6275972012-02-29 20:06:21 -0800108static bool debug_bus_voting_enabled = true;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700109
Hemant Kumardf2d84d2012-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 Kumardf2d84d2012-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 Kumardf2d84d2012-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 Kumardf2d84d2012-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 Kumardf2d84d2012-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 Kumardf2d84d2012-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 Kumardf2d84d2012-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 Kumardf2d84d2012-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 Kumardf2d84d2012-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 Kumardf2d84d2012-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 Kumardf2d84d2012-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 Kumar266d9d52012-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
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530399static int __maybe_unused ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700400{
401 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Devin Kim01e5a5b2012-08-30 02:52:45 -0700402 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700403
404 /* initiate read operation */
405 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
406 USB_ULPI_VIEWPORT);
407
408 /* wait for completion */
Devin Kim01e5a5b2012-08-30 02:52:45 -0700409 while (cnt < ULPI_IO_TIMEOUT_USEC) {
410 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
411 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700412 udelay(1);
Devin Kim01e5a5b2012-08-30 02:52:45 -0700413 cnt++;
414 }
415
416 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
417 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
418 readl_relaxed(USB_ULPI_VIEWPORT));
419 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
420 readl_relaxed(USB_PORTSC),
421 readl_relaxed(USB_USBCMD),
422 readl_relaxed(USB_FRINDEX));
423
424 /*frame counter increments afte 125us*/
425 udelay(130);
426 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
427 readl_relaxed(USB_FRINDEX));
428 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700429 }
430
431 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
432}
433
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530434static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
435{
436 struct usb_hcd *hcd = hsic_to_hcd(mehci);
437 int cnt = 0;
438
439 /* initiate write operation */
440 writel_relaxed(ULPI_RUN | ULPI_WRITE |
441 ULPI_ADDR(reg) | ULPI_DATA(val),
442 USB_ULPI_VIEWPORT);
443
444 /* wait for completion */
445 while (cnt < ULPI_IO_TIMEOUT_USEC) {
446 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
447 break;
448 udelay(1);
449 cnt++;
450 }
451
452 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Devin Kim01e5a5b2012-08-30 02:52:45 -0700453 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
454 readl_relaxed(USB_ULPI_VIEWPORT));
455 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
456 readl_relaxed(USB_PORTSC),
457 readl_relaxed(USB_USBCMD),
458 readl_relaxed(USB_FRINDEX));
459
460 /*frame counter increments afte 125us*/
461 udelay(130);
462 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
463 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530464 return -ETIMEDOUT;
465 }
466
467 return 0;
468}
469
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530470static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
471{
472 int rc = 0;
473 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800474 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530475
476 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800477
Lena Salman8c8ba382012-02-14 15:59:31 +0200478 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530479 return rc;
480
Vamsi Krishna34f01582011-12-14 19:54:42 -0800481 if (gpio_status == gpio_en)
482 return 0;
483
484 gpio_status = gpio_en;
485
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530486 if (!gpio_en)
487 goto free_gpio;
488
489 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
490 if (rc < 0) {
491 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
492 return rc;
493 }
494
495 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
496 if (rc < 0) {
497 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
498 goto free_strobe;
499 }
500
Hemant Kumar6fd65032012-05-23 13:02:24 -0700501 if (mehci->wakeup_gpio) {
502 rc = gpio_request(mehci->wakeup_gpio, "HSIC_WAKEUP_GPIO");
503 if (rc < 0) {
504 dev_err(mehci->dev, "gpio request failed for HSIC WAKEUP\n");
505 goto free_data;
506 }
507 }
508
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530509 return 0;
510
511free_gpio:
Hemant Kumar6fd65032012-05-23 13:02:24 -0700512 if (mehci->wakeup_gpio)
513 gpio_free(mehci->wakeup_gpio);
514free_data:
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530515 gpio_free(pdata->data);
516free_strobe:
517 gpio_free(pdata->strobe);
518
519 return rc;
520}
521
Vamsi Krishna64b48612012-06-14 16:08:11 -0700522static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530523{
524 int ret;
525
Manu Gautam5143b252012-01-05 19:25:23 -0800526 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530527 if (ret) {
Vamsi Krishna64b48612012-06-14 16:08:11 -0700528 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
529 return;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530530 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700531 clk_disable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530532
Manu Gautam5143b252012-01-05 19:25:23 -0800533 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530534 if (ret)
Vamsi Krishna64b48612012-06-14 16:08:11 -0700535 dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530536
Vamsi Krishna64b48612012-06-14 16:08:11 -0700537 usleep_range(10000, 12000);
538
539 clk_enable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530540}
541
Vamsi Krishna64b48612012-06-14 16:08:11 -0700542#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
543#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530544#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
545#define HSIC_LV_MODE 0x04
546#define HSIC_PAD_CALIBRATION 0xA8
547#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530548#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
549static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
550{
551 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530552 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200553 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530554
Vamsi Krishna64b48612012-06-14 16:08:11 -0700555 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530556
Vamsi Krishna64b48612012-06-14 16:08:11 -0700557 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530558 writel_relaxed(0x80000000, USB_PORTSC);
559
Vamsi Krishna64b48612012-06-14 16:08:11 -0700560 mb();
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530561
Lena Salman8c8ba382012-02-14 15:59:31 +0200562 /* HSIC init sequence when HSIC signals (Strobe/Data) are
563 routed via GPIOs */
564 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530565
Lena Salman8c8ba382012-02-14 15:59:31 +0200566 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
567 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530568
Vamsi Krishna64b48612012-06-14 16:08:11 -0700569 mb();
570
Lena Salman8c8ba382012-02-14 15:59:31 +0200571 /*set periodic calibration interval to ~2.048sec in
572 HSIC_IO_CAL_REG */
573 ulpi_write(mehci, 0xFF, 0x33);
574
575 /* Enable periodic IO calibration in HSIC_CFG register */
576 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
577
Vamsi Krishna64b48612012-06-14 16:08:11 -0700578 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200579 ret = msm_hsic_config_gpios(mehci, 1);
580 if (ret) {
581 dev_err(mehci->dev, " gpio configuarion failed\n");
582 return ret;
583 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700584 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO PAD_CTL register */
585 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_STROBE_GPIO_PAD_CTL);
586 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_DATA_GPIO_PAD_CTL);
587
588 mb();
589
Lena Salman8c8ba382012-02-14 15:59:31 +0200590 /* Enable HSIC mode in HSIC_CFG register */
591 ulpi_write(mehci, 0x01, 0x31);
592 } else {
593 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
594 via dedicated I/O */
595
596 /* programmable length of connect signaling (33.2ns) */
597 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
598 if (ret) {
599 pr_err("%s: Unable to program length of connect "
600 "signaling\n", __func__);
601 }
602
603 /*set periodic calibration interval to ~2.048sec in
604 HSIC_IO_CAL_REG */
605 ulpi_write(mehci, 0xFF, 0x33);
606
607 /* Enable HSIC mode in HSIC_CFG register */
608 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530609 }
610
Hemant Kumar6fd65032012-05-23 13:02:24 -0700611 /*disable auto resume*/
612 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
613
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530614 return 0;
615}
616
617#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
618#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
619
620#ifdef CONFIG_PM_SLEEP
621static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
622{
623 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530624 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530625 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300626 int none_vol, max_vol;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530627
628 if (atomic_read(&mehci->in_lpm)) {
629 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
630 return 0;
631 }
632
633 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700634
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700635 /* make sure we don't race against a remote wakeup */
636 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700637 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700638 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700639 enable_irq(hcd->irq);
640 return -EBUSY;
641 }
642
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530643 /*
644 * PHY may take some time or even fail to enter into low power
645 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
646 * in failure case.
647 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700648 val = readl_relaxed(USB_PORTSC);
649 val &= ~PORT_RWC_BITS;
650 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530651 writel_relaxed(val, USB_PORTSC);
652 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
653 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
654 break;
655 udelay(1);
656 cnt++;
657 }
658
659 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
660 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530661 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530662 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530663 }
664
665 /*
666 * PHY has capability to generate interrupt asynchronously in low
667 * power mode (LPM). This interrupt is level triggered. So USB IRQ
668 * line must be disabled till async interrupt enable bit is cleared
669 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
Pavankumar Kondeti1c1d82b2013-01-28 21:37:59 +0530670 * block data communication from PHY. Enable asynchronous interrupt
671 * only when wakeup gpio IRQ is not present.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530672 */
Pavankumar Kondeti1c1d82b2013-01-28 21:37:59 +0530673 if (mehci->wakeup_irq)
674 writel_relaxed(readl_relaxed(USB_USBCMD) |
675 ULPI_STP_CTRL, USB_USBCMD);
676 else
677 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530678 ULPI_STP_CTRL, USB_USBCMD);
679
680 /*
681 * Ensure that hardware is put in low power mode before
682 * clocks are turned OFF and VDD is allowed to minimize.
683 */
684 mb();
685
Manu Gautam28b1bac2012-01-30 16:43:06 +0530686 clk_disable_unprepare(mehci->core_clk);
687 clk_disable_unprepare(mehci->phy_clk);
688 clk_disable_unprepare(mehci->cal_clk);
689 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530690
Amit Blayd6ea6102012-06-07 16:26:24 +0300691 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
692 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
693
694 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700695 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300696 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700697
Hemant Kumare6275972012-02-29 20:06:21 -0800698 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700699 mehci->bus_vote = false;
700 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800701 }
702
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530703 atomic_set(&mehci->in_lpm, 1);
704 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700705
706 mehci->wakeup_irq_enabled = 1;
707 enable_irq_wake(mehci->wakeup_irq);
708 enable_irq(mehci->wakeup_irq);
709
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700710 wake_unlock(&mehci->wlock);
711
Devin Kim476bbd72012-07-19 18:11:11 -0700712 dev_dbg(mehci->dev, "HSIC-USB in low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530713
714 return 0;
715}
716
717static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
718{
719 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530720 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530721 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300722 int min_vol, max_vol;
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700723 unsigned long flags;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530724
725 if (!atomic_read(&mehci->in_lpm)) {
726 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
727 return 0;
728 }
729
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530730 /* Handles race with Async interrupt */
731 disable_irq(hcd->irq);
732
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700733 spin_lock_irqsave(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700734 if (mehci->wakeup_irq_enabled) {
735 disable_irq_wake(mehci->wakeup_irq);
736 disable_irq_nosync(mehci->wakeup_irq);
737 mehci->wakeup_irq_enabled = 0;
738 }
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700739 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700740
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700741 wake_lock(&mehci->wlock);
742
Hemant Kumare6275972012-02-29 20:06:21 -0800743 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700744 mehci->bus_vote = true;
745 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800746 }
747
Amit Blayd6ea6102012-06-07 16:26:24 +0300748 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
749 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
750
751 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700752 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300753 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700754
Manu Gautam28b1bac2012-01-30 16:43:06 +0530755 clk_prepare_enable(mehci->core_clk);
756 clk_prepare_enable(mehci->phy_clk);
757 clk_prepare_enable(mehci->cal_clk);
758 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530759
760 temp = readl_relaxed(USB_USBCMD);
761 temp &= ~ASYNC_INTR_CTRL;
762 temp &= ~ULPI_STP_CTRL;
763 writel_relaxed(temp, USB_USBCMD);
764
765 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
766 goto skip_phy_resume;
767
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700768 temp = readl_relaxed(USB_PORTSC);
769 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530770 writel_relaxed(temp, USB_PORTSC);
771 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
772 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
773 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
774 break;
775 udelay(1);
776 cnt++;
777 }
778
779 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
780 /*
781 * This is a fatal error. Reset the link and
782 * PHY to make hsic working.
783 */
784 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530785 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530786 msm_hsic_reset(mehci);
787 }
788
789skip_phy_resume:
790
Hemant Kumar6fd65032012-05-23 13:02:24 -0700791 usb_hcd_resume_root_hub(hcd);
792
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530793 atomic_set(&mehci->in_lpm, 0);
794
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530795 if (atomic_read(&mehci->async_int)) {
796 atomic_set(&mehci->async_int, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530797 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700798 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700799 }
800
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700801 if (atomic_read(&mehci->pm_usage_cnt)) {
802 atomic_set(&mehci->pm_usage_cnt, 0);
803 pm_runtime_put_noidle(mehci->dev);
804 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700805
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530806 enable_irq(hcd->irq);
Devin Kim476bbd72012-07-19 18:11:11 -0700807 dev_dbg(mehci->dev, "HSIC-USB exited from low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530808
809 return 0;
810}
811#endif
812
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700813static void ehci_hsic_bus_vote_w(struct work_struct *w)
814{
815 struct msm_hsic_hcd *mehci =
816 container_of(w, struct msm_hsic_hcd, bus_vote_w);
817 int ret;
818
819 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
820 mehci->bus_vote);
821 if (ret)
822 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
823 __func__, ret);
824}
825
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530826static int msm_hsic_reset_done(struct usb_hcd *hcd)
827{
828 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
829 u32 __iomem *status_reg = &ehci->regs->port_status[0];
830 int ret;
831
832 ehci_writel(ehci, ehci_readl(ehci, status_reg) & ~(PORT_RWC_BITS |
833 PORT_RESET), status_reg);
834
835 ret = handshake(ehci, status_reg, PORT_RESET, 0, 1 * 1000);
836
837 if (ret)
838 pr_err("reset handshake failed in %s\n", __func__);
839 else
840 ehci_writel(ehci, ehci_readl(ehci, &ehci->regs->command) |
841 CMD_RUN, &ehci->regs->command);
842
843 return ret;
844}
845
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700846#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530847static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
848{
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700849 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530850 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700851 u32 status;
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530852 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530853
854 if (atomic_read(&mehci->in_lpm)) {
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700855 dev_dbg(mehci->dev, "phy async intr\n");
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530856 dbg_log_event(NULL, "Async IRQ", 0);
857 ret = pm_runtime_get(mehci->dev);
858 if ((ret == 1) || (ret == -EINPROGRESS)) {
859 pm_runtime_put_noidle(mehci->dev);
860 } else {
861 disable_irq_nosync(hcd->irq);
862 atomic_set(&mehci->async_int, 1);
863 }
864
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530865 return IRQ_HANDLED;
866 }
867
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700868 status = ehci_readl(ehci, &ehci->regs->status);
869
870 if (status & STS_GPTIMER0_INTERRUPT) {
871 int timeleft;
872
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530873 dbg_log_event(NULL, "FPR: gpt0_isr", mehci->bus_reset);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700874
875 timeleft = GPT_CNT(ehci_readl(ehci,
876 &mehci->timer->gptimer1_ctrl));
877 if (timeleft) {
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530878 if (mehci->bus_reset) {
879 ret = msm_hsic_reset_done(hcd);
880 if (ret) {
881 mehci->reset_again = 1;
882 dbg_log_event(NULL, "RESET: fail", 0);
883 }
884 } else {
885 ehci_writel(ehci, ehci_readl(ehci,
886 &ehci->regs->command) | CMD_RUN,
887 &ehci->regs->command);
888 }
889 } else {
890 if (mehci->bus_reset)
891 mehci->reset_again = 1;
892 else
893 mehci->resume_again = 1;
894 }
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700895
896 dbg_log_event(NULL, "FPR: timeleft", timeleft);
897
898 complete(&mehci->gpt0_completion);
899 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
900 }
901
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530902 return ehci_irq(hcd);
903}
904
905static int ehci_hsic_reset(struct usb_hcd *hcd)
906{
907 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700908 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530909 int retval;
910
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700911 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530912 ehci->caps = USB_CAPLENGTH;
913 ehci->regs = USB_CAPLENGTH +
914 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
915 dbg_hcs_params(ehci, "reset");
916 dbg_hcc_params(ehci, "reset");
917
918 /* cache the data to minimize the chip reads*/
919 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
920
921 hcd->has_tt = 1;
922 ehci->sbrn = HCD_USB2;
923
924 retval = ehci_halt(ehci);
925 if (retval)
926 return retval;
927
928 /* data structure init */
929 retval = ehci_init(hcd);
930 if (retval)
931 return retval;
932
933 retval = ehci_reset(ehci);
934 if (retval)
935 return retval;
936
937 /* bursts of unspecified length. */
938 writel_relaxed(0, USB_AHBBURST);
939 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530940 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530941 /* Disable streaming mode and select host mode */
942 writel_relaxed(0x13, USB_USBMODE);
943
944 ehci_port_power(ehci, 1);
945 return 0;
946}
947
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530948#define RESET_RETRY_LIMIT 3
949#define RESET_SIGNAL_TIME_SOF_USEC (50 * 1000)
950#define RESET_SIGNAL_TIME_USEC (20 * 1000)
951static void ehci_hsic_reset_sof_bug_handler(struct usb_hcd *hcd, u32 val)
952{
953 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
954 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
955 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
956 u32 __iomem *status_reg = &ehci->regs->port_status[0];
Pavankumar Kondeti37493632013-03-05 09:43:22 +0530957 u32 cmd;
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530958 unsigned long flags;
959 int retries = 0, ret, cnt = RESET_SIGNAL_TIME_USEC;
960
961 if (pdata && pdata->swfi_latency)
962 pm_qos_update_request(&mehci->pm_qos_req_dma,
963 pdata->swfi_latency + 1);
964
965 mehci->bus_reset = 1;
Pavankumar Kondeti37493632013-03-05 09:43:22 +0530966
967 /* Halt the controller */
968 cmd = ehci_readl(ehci, &ehci->regs->command);
969 cmd &= ~CMD_RUN;
970 ehci_writel(ehci, cmd, &ehci->regs->command);
971 ret = handshake(ehci, &ehci->regs->status, STS_HALT,
972 STS_HALT, 16 * 125);
973 if (ret) {
974 pr_err("halt handshake fatal error\n");
975 dbg_log_event(NULL, "HALT: fatal", 0);
976 goto fail;
977 }
978
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530979retry:
980 retries++;
981 dbg_log_event(NULL, "RESET: start", retries);
982 pr_debug("reset begin %d\n", retries);
983 mehci->reset_again = 0;
984 spin_lock_irqsave(&ehci->lock, flags);
985 ehci_writel(ehci, val, status_reg);
986 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_USEC - 1),
987 &mehci->timer->gptimer0_ld);
988 ehci_writel(ehci, GPT_RESET | GPT_RUN,
989 &mehci->timer->gptimer0_ctrl);
990 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
991 &ehci->regs->intr_enable);
992
993 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_SOF_USEC - 1),
994 &mehci->timer->gptimer1_ld);
995 ehci_writel(ehci, GPT_RESET | GPT_RUN,
996 &mehci->timer->gptimer1_ctrl);
997
998 spin_unlock_irqrestore(&ehci->lock, flags);
999 wait_for_completion(&mehci->gpt0_completion);
1000
1001 if (!mehci->reset_again)
1002 goto done;
1003
1004 if (handshake(ehci, status_reg, PORT_RESET, 0, 10 * 1000)) {
1005 pr_err("reset handshake fatal error\n");
1006 dbg_log_event(NULL, "RESET: fatal", retries);
1007 goto fail;
1008 }
1009
1010 if (retries < RESET_RETRY_LIMIT)
1011 goto retry;
1012
1013 /* complete reset in tight loop */
1014 pr_info("RESET in tight loop\n");
1015 dbg_log_event(NULL, "RESET: tight", 0);
1016
1017 spin_lock_irqsave(&ehci->lock, flags);
1018 ehci_writel(ehci, val, status_reg);
1019 while (cnt--)
1020 udelay(1);
1021 ret = msm_hsic_reset_done(hcd);
1022 spin_unlock_irqrestore(&ehci->lock, flags);
1023 if (ret) {
1024 pr_err("RESET in tight loop failed\n");
1025 dbg_log_event(NULL, "RESET: tight failed", 0);
1026 goto fail;
1027 }
1028
1029done:
1030 dbg_log_event(NULL, "RESET: done", retries);
1031 pr_debug("reset completed\n");
1032fail:
1033 mehci->bus_reset = 0;
1034 if (pdata && pdata->swfi_latency)
1035 pm_qos_update_request(&mehci->pm_qos_req_dma,
1036 PM_QOS_DEFAULT_VALUE);
1037}
1038
Hemant Kumar45d211b2012-05-31 17:58:43 -07001039static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
1040{
Pavankumar Kondeti3c137392012-09-14 14:02:36 +05301041 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1042
1043 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
1044 dbg_log_event(NULL, "RH suspend attempt failed", 0);
1045 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
1046 __func__);
1047 return -EAGAIN;
1048 }
1049
Hemant Kumar45d211b2012-05-31 17:58:43 -07001050 dbg_log_event(NULL, "Suspend RH", 0);
1051 return ehci_bus_suspend(hcd);
1052}
1053
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001054#define RESUME_RETRY_LIMIT 3
Pavankumar Kondetic91a92a2013-01-29 19:08:12 +05301055#define RESUME_SIGNAL_TIME_USEC (21 * 1000)
1056#define RESUME_SIGNAL_TIME_SOF_USEC (23 * 1000)
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001057static int msm_hsic_resume_thread(void *data)
1058{
1059 struct msm_hsic_hcd *mehci = data;
1060 struct usb_hcd *hcd = hsic_to_hcd(mehci);
1061 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1062 u32 temp;
1063 unsigned long resume_needed = 0;
1064 int retry_cnt = 0;
1065 int tight_resume = 0;
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301066 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001067
1068 dbg_log_event(NULL, "Resume RH", 0);
1069
1070 /* keep delay between bus states */
1071 if (time_before(jiffies, ehci->next_statechange))
1072 usleep_range(5000, 5000);
1073
1074 spin_lock_irq(&ehci->lock);
1075 if (!HCD_HW_ACCESSIBLE(hcd)) {
1076 spin_unlock_irq(&ehci->lock);
1077 mehci->resume_status = -ESHUTDOWN;
1078 complete(&mehci->rt_completion);
1079 return 0;
1080 }
1081
1082 if (unlikely(ehci->debug)) {
1083 if (!dbgp_reset_prep())
1084 ehci->debug = NULL;
1085 else
1086 dbgp_external_startup();
1087 }
1088
1089 /* at least some APM implementations will try to deliver
1090 * IRQs right away, so delay them until we're ready.
1091 */
1092 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
1093
1094 /* re-init operational registers */
1095 ehci_writel(ehci, 0, &ehci->regs->segment);
1096 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
1097 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
1098
1099 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
1100 if (ehci->resume_sof_bug)
1101 ehci->command &= ~CMD_RUN;
1102
1103 /* restore CMD_RUN, framelist size, and irq threshold */
1104 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1105
1106 /* manually resume the ports we suspended during bus_suspend() */
1107resume_again:
1108 if (retry_cnt >= RESUME_RETRY_LIMIT) {
1109 pr_info("retry count(%d) reached max, resume in tight loop\n",
1110 retry_cnt);
1111 tight_resume = 1;
1112 }
1113
1114
1115 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1116 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
1117 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
1118 temp |= PORT_RESUME;
1119 set_bit(0, &resume_needed);
1120 }
1121 dbg_log_event(NULL, "FPR: Set", temp);
1122 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1123
1124 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1125 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1126 * controller in MSM clears FPR bit after driving the resume signal for
1127 * 20ms. Workaround is to stop SOFs before driving resume and then start
1128 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1129 * completion otherwise peripheral may enter undefined state. As
1130 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1131 * to time the resume sequence. If driver exceeds allowable time SOFs,
1132 * repeat the resume process.
1133 */
1134 if (ehci->resume_sof_bug && resume_needed) {
1135 if (!tight_resume) {
1136 mehci->resume_again = 0;
Pavankumar Kondetic91a92a2013-01-29 19:08:12 +05301137 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_USEC - 1),
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001138 &mehci->timer->gptimer0_ld);
1139 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1140 &mehci->timer->gptimer0_ctrl);
1141 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1142 &ehci->regs->intr_enable);
1143
Pavankumar Kondetic91a92a2013-01-29 19:08:12 +05301144 ehci_writel(ehci, GPT_LD(
1145 RESUME_SIGNAL_TIME_SOF_USEC - 1),
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001146 &mehci->timer->gptimer1_ld);
1147 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1148 &mehci->timer->gptimer1_ctrl);
1149
1150 spin_unlock_irq(&ehci->lock);
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301151 if (pdata && pdata->swfi_latency)
1152 pm_qos_update_request(&mehci->pm_qos_req_dma,
1153 pdata->swfi_latency + 1);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001154 wait_for_completion(&mehci->gpt0_completion);
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301155 if (pdata && pdata->swfi_latency)
1156 pm_qos_update_request(&mehci->pm_qos_req_dma,
1157 PM_QOS_DEFAULT_VALUE);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001158 spin_lock_irq(&ehci->lock);
1159 } else {
1160 dbg_log_event(NULL, "FPR: Tightloop", 0);
1161 /* do the resume in a tight loop */
1162 handshake(ehci, &ehci->regs->port_status[0],
1163 PORT_RESUME, 0, 22 * 1000);
1164 ehci_writel(ehci, ehci_readl(ehci,
1165 &ehci->regs->command) | CMD_RUN,
1166 &ehci->regs->command);
1167 }
1168
1169 if (mehci->resume_again) {
1170 int temp;
1171
1172 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1173 pr_info("FPR: retry count: %d\n", retry_cnt);
1174 spin_unlock_irq(&ehci->lock);
1175 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1176 temp &= ~PORT_RWC_BITS;
1177 temp |= PORT_SUSPEND;
1178 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1179 /* Keep the bus idle for 5ms so that peripheral
1180 * can detect and initiate suspend
1181 */
1182 usleep_range(5000, 5000);
1183 dbg_log_event(NULL,
1184 "FPR: RResume",
1185 ehci_readl(ehci, &ehci->regs->port_status[0]));
1186 spin_lock_irq(&ehci->lock);
1187 mehci->resume_again = 0;
1188 retry_cnt++;
1189 goto resume_again;
1190 }
1191 }
1192
1193 dbg_log_event(NULL, "FPR: RT-Done", 0);
1194 mehci->resume_status = 1;
1195 spin_unlock_irq(&ehci->lock);
1196
1197 complete(&mehci->rt_completion);
1198
1199 return 0;
1200}
1201
Hemant Kumar45d211b2012-05-31 17:58:43 -07001202static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1203{
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001204 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1205 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1206 u32 temp;
1207 struct task_struct *resume_thread = NULL;
1208
1209 mehci->resume_status = 0;
1210 resume_thread = kthread_run(msm_hsic_resume_thread,
1211 mehci, "hsic_resume_thread");
1212 if (IS_ERR(resume_thread)) {
1213 pr_err("Error creating resume thread:%lu\n",
1214 PTR_ERR(resume_thread));
1215 return PTR_ERR(resume_thread);
1216 }
1217
1218 wait_for_completion(&mehci->rt_completion);
1219
1220 if (mehci->resume_status < 0)
1221 return mehci->resume_status;
1222
1223 dbg_log_event(NULL, "FPR: Wokeup", 0);
1224 spin_lock_irq(&ehci->lock);
1225 (void) ehci_readl(ehci, &ehci->regs->command);
1226
1227 temp = 0;
1228 if (ehci->async->qh_next.qh)
1229 temp |= CMD_ASE;
1230 if (ehci->periodic_sched)
1231 temp |= CMD_PSE;
1232 if (temp) {
1233 ehci->command |= temp;
1234 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1235 }
1236
1237 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1238 hcd->state = HC_STATE_RUNNING;
1239 ehci->rh_state = EHCI_RH_RUNNING;
1240
1241 /* Now we can safely re-enable irqs */
1242 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1243
1244 spin_unlock_irq(&ehci->lock);
1245
1246 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001247}
1248
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301249static struct hc_driver msm_hsic_driver = {
1250 .description = hcd_name,
1251 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1252 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1253
1254 /*
1255 * generic hardware linkage
1256 */
1257 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001258 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301259
1260 .reset = ehci_hsic_reset,
1261 .start = ehci_run,
1262
1263 .stop = ehci_stop,
1264 .shutdown = ehci_shutdown,
1265
1266 /*
1267 * managing i/o requests and associated device resources
1268 */
Hemant Kumardf2d84d2012-08-15 09:06:35 -07001269 .urb_enqueue = ehci_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301270 .urb_dequeue = ehci_urb_dequeue,
1271 .endpoint_disable = ehci_endpoint_disable,
1272 .endpoint_reset = ehci_endpoint_reset,
1273 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1274
1275 /*
1276 * scheduling support
1277 */
1278 .get_frame_number = ehci_get_frame,
1279
1280 /*
1281 * root hub support
1282 */
1283 .hub_status_data = ehci_hub_status_data,
1284 .hub_control = ehci_hub_control,
1285 .relinquish_port = ehci_relinquish_port,
1286 .port_handed_over = ehci_port_handed_over,
1287
1288 /*
1289 * PM support
1290 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001291 .bus_suspend = ehci_hsic_bus_suspend,
1292 .bus_resume = ehci_hsic_bus_resume,
1293
Hemant Kumardf2d84d2012-08-15 09:06:35 -07001294 .log_urb = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001295 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001296
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +05301297 .reset_sof_bug_handler = ehci_hsic_reset_sof_bug_handler,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301298};
1299
1300static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1301{
1302 int ret = 0;
1303
1304 if (!init)
1305 goto put_clocks;
1306
Lena Salman8c8ba382012-02-14 15:59:31 +02001307 /*core_clk is required for LINK protocol engine
1308 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001309 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1310 if (IS_ERR(mehci->core_clk)) {
1311 dev_err(mehci->dev, "failed to get core_clk\n");
1312 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301313 return ret;
1314 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301315
Lena Salman8c8ba382012-02-14 15:59:31 +02001316 /* alt_core_clk is for LINK to be used during PHY RESET
1317 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001318 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
1319 if (IS_ERR(mehci->alt_core_clk)) {
1320 dev_err(mehci->dev, "failed to core_clk\n");
1321 ret = PTR_ERR(mehci->alt_core_clk);
1322 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301323 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301324
Lena Salman8c8ba382012-02-14 15:59:31 +02001325 /* phy_clk is required for HSIC PHY operation
1326 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001327 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1328 if (IS_ERR(mehci->phy_clk)) {
1329 dev_err(mehci->dev, "failed to get phy_clk\n");
1330 ret = PTR_ERR(mehci->phy_clk);
1331 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301332 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301333
1334 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001335 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301336 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001337 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301338 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001339 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301340 }
1341 clk_set_rate(mehci->cal_clk, 10000000);
1342
1343 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001344 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301345 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001346 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301347 ret = PTR_ERR(mehci->ahb_clk);
1348 goto put_cal_clk;
1349 }
1350
Manu Gautam28b1bac2012-01-30 16:43:06 +05301351 clk_prepare_enable(mehci->core_clk);
1352 clk_prepare_enable(mehci->phy_clk);
1353 clk_prepare_enable(mehci->cal_clk);
1354 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301355
1356 return 0;
1357
1358put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001359 if (!atomic_read(&mehci->in_lpm)) {
1360 clk_disable_unprepare(mehci->core_clk);
1361 clk_disable_unprepare(mehci->phy_clk);
1362 clk_disable_unprepare(mehci->cal_clk);
1363 clk_disable_unprepare(mehci->ahb_clk);
1364 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301365 clk_put(mehci->ahb_clk);
1366put_cal_clk:
1367 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001368put_phy_clk:
1369 clk_put(mehci->phy_clk);
1370put_alt_core_clk:
1371 clk_put(mehci->alt_core_clk);
1372put_core_clk:
1373 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301374
1375 return ret;
1376}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001377static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1378{
1379 struct msm_hsic_hcd *mehci = dev_id;
1380
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001381 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001382
1383 if (mehci)
1384 msm_hsic_config_gpios(mehci, 0);
1385
1386 return IRQ_HANDLED;
1387}
1388
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001389static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1390{
1391 struct msm_hsic_hcd *mehci = data;
Ajay Dudanid666daf2012-09-27 12:04:12 +05301392 int ret;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001393
Hemant Kumar6fd65032012-05-23 13:02:24 -07001394 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001395 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001396 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
1397 __func__, mehci->wakeup_int_cnt);
1398
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001399 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001400
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001401 spin_lock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001402 if (mehci->wakeup_irq_enabled) {
1403 mehci->wakeup_irq_enabled = 0;
1404 disable_irq_wake(irq);
1405 disable_irq_nosync(irq);
1406 }
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001407 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001408
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001409 if (!atomic_read(&mehci->pm_usage_cnt)) {
Ajay Dudanid666daf2012-09-27 12:04:12 +05301410 ret = pm_runtime_get(mehci->dev);
1411 /*
1412 * HSIC runtime resume can race with us.
1413 * if we are active (ret == 1) or resuming
1414 * (ret == -EINPROGRESS), decrement the
1415 * PM usage counter before returning.
1416 */
1417 if ((ret == 1) || (ret == -EINPROGRESS))
1418 pm_runtime_put_noidle(mehci->dev);
1419 else
1420 atomic_set(&mehci->pm_usage_cnt, 1);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001421 }
1422
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001423 return IRQ_HANDLED;
1424}
1425
Hemant Kumare6275972012-02-29 20:06:21 -08001426static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1427{
1428 if (debug_bus_voting_enabled)
1429 seq_printf(s, "enabled\n");
1430 else
1431 seq_printf(s, "disabled\n");
1432
1433 return 0;
1434}
1435
1436static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1437{
1438 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1439}
1440
1441static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1442 const char __user *ubuf, size_t count, loff_t *ppos)
1443{
1444 char buf[8];
1445 int ret;
1446 struct seq_file *s = file->private_data;
1447 struct msm_hsic_hcd *mehci = s->private;
1448
1449 memset(buf, 0x00, sizeof(buf));
1450
1451 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1452 return -EFAULT;
1453
1454 if (!strncmp(buf, "enable", 6)) {
1455 /* Do not vote here. Let hsic driver decide when to vote */
1456 debug_bus_voting_enabled = true;
1457 } else {
1458 debug_bus_voting_enabled = false;
1459 if (mehci->bus_perf_client) {
1460 ret = msm_bus_scale_client_update_request(
1461 mehci->bus_perf_client, 0);
1462 if (ret)
1463 dev_err(mehci->dev, "%s: Failed to devote "
1464 "for bus bw %d\n", __func__, ret);
1465 }
1466 }
1467
1468 return count;
1469}
1470
1471const struct file_operations ehci_hsic_msm_bus_fops = {
1472 .open = ehci_hsic_msm_bus_open,
1473 .read = seq_read,
1474 .write = ehci_hsic_msm_bus_write,
1475 .llseek = seq_lseek,
1476 .release = single_release,
1477};
1478
Hemant Kumar6fd65032012-05-23 13:02:24 -07001479static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1480{
1481 struct msm_hsic_hcd *mehci = s->private;
1482
1483 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1484
1485 return 0;
1486}
1487
1488static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1489{
1490 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1491}
1492
1493const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1494 .open = ehci_hsic_msm_wakeup_cnt_open,
1495 .read = seq_read,
1496 .llseek = seq_lseek,
1497 .release = single_release,
1498};
1499
Hemant Kumar45d211b2012-05-31 17:58:43 -07001500static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1501{
1502 unsigned long flags;
1503 unsigned i;
1504
1505 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1506
1507 i = dbg_hsic_data.idx;
1508 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1509 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1510 continue;
1511 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1512 }
1513
1514 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1515
1516 return 0;
1517}
1518
1519static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1520{
1521 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1522}
1523
1524const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1525 .open = ehci_hsic_msm_data_events_open,
1526 .read = seq_read,
1527 .llseek = seq_lseek,
1528 .release = single_release,
1529};
1530
1531static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1532{
1533 unsigned long flags;
1534 unsigned i;
1535
1536 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1537
1538 i = dbg_hsic_ctrl.idx;
1539 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1540 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1541 continue;
1542 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1543 }
1544
1545 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1546
1547 return 0;
1548}
1549
1550static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1551{
1552 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1553}
1554
1555const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1556 .open = ehci_hsic_msm_ctrl_events_open,
1557 .read = seq_read,
1558 .llseek = seq_lseek,
1559 .release = single_release,
1560};
1561
Hemant Kumare6275972012-02-29 20:06:21 -08001562static struct dentry *ehci_hsic_msm_dbg_root;
1563static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1564{
1565 struct dentry *ehci_hsic_msm_dentry;
1566
1567 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1568
1569 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1570 return -ENODEV;
1571
1572 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1573 S_IRUGO | S_IWUSR,
1574 ehci_hsic_msm_dbg_root, mehci,
1575 &ehci_hsic_msm_bus_fops);
1576
1577 if (!ehci_hsic_msm_dentry) {
1578 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1579 return -ENODEV;
1580 }
1581
Hemant Kumar6fd65032012-05-23 13:02:24 -07001582 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1583 S_IRUGO,
1584 ehci_hsic_msm_dbg_root, mehci,
1585 &ehci_hsic_msm_wakeup_cnt_fops);
1586
1587 if (!ehci_hsic_msm_dentry) {
1588 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1589 return -ENODEV;
1590 }
1591
Hemant Kumar45d211b2012-05-31 17:58:43 -07001592 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1593 S_IRUGO,
1594 ehci_hsic_msm_dbg_root, mehci,
1595 &ehci_hsic_msm_dbg_ctrl_fops);
1596
1597 if (!ehci_hsic_msm_dentry) {
1598 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1599 return -ENODEV;
1600 }
1601
1602 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1603 S_IRUGO,
1604 ehci_hsic_msm_dbg_root, mehci,
1605 &ehci_hsic_msm_dbg_data_fops);
1606
1607 if (!ehci_hsic_msm_dentry) {
1608 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1609 return -ENODEV;
1610 }
1611
Hemant Kumare6275972012-02-29 20:06:21 -08001612 return 0;
1613}
1614
1615static void ehci_hsic_msm_debugfs_cleanup(void)
1616{
1617 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1618}
1619
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301620static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1621{
1622 struct usb_hcd *hcd;
1623 struct resource *res;
1624 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301625 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301626 int ret;
1627
1628 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1629
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301630 /* After parent device's probe is executed, it will be put in suspend
1631 * mode. When child device's probe is called, driver core is not
1632 * resuming parent device due to which parent will be in suspend even
1633 * though child is active. Hence resume the parent device explicitly.
1634 */
1635 if (pdev->dev.parent)
1636 pm_runtime_get_sync(pdev->dev.parent);
1637
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301638 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1639 dev_name(&pdev->dev));
1640 if (!hcd) {
1641 dev_err(&pdev->dev, "Unable to create HCD\n");
1642 return -ENOMEM;
1643 }
1644
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301645 hcd_to_bus(hcd)->skip_resume = true;
1646
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301647 hcd->irq = platform_get_irq(pdev, 0);
1648 if (hcd->irq < 0) {
1649 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1650 ret = hcd->irq;
1651 goto put_hcd;
1652 }
1653
1654 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1655 if (!res) {
1656 dev_err(&pdev->dev, "Unable to get memory resource\n");
1657 ret = -ENODEV;
1658 goto put_hcd;
1659 }
1660
1661 hcd->rsrc_start = res->start;
1662 hcd->rsrc_len = resource_size(res);
1663 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1664 if (!hcd->regs) {
1665 dev_err(&pdev->dev, "ioremap failed\n");
1666 ret = -ENOMEM;
1667 goto put_hcd;
1668 }
1669
1670 mehci = hcd_to_hsic(hcd);
1671 mehci->dev = &pdev->dev;
Ajay Dudanic4e40db2012-08-20 14:44:40 -07001672 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301673
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001674 spin_lock_init(&mehci->wakeup_lock);
1675
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001676 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001677 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001678
Hemant Kumare4040492012-06-21 17:35:42 -07001679 mehci->ehci.resume_sof_bug = 1;
1680
Ajay Dudanic4e40db2012-08-20 14:44:40 -07001681 if (pdata)
1682 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Hemant Kumar933e0402012-05-22 11:11:40 -07001683
Vamsi Krishna34f01582011-12-14 19:54:42 -08001684 res = platform_get_resource_byname(pdev,
1685 IORESOURCE_IRQ,
1686 "peripheral_status_irq");
1687 if (res)
1688 mehci->peripheral_status_irq = res->start;
1689
Hemant Kumar6fd65032012-05-23 13:02:24 -07001690 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
1691 if (res) {
1692 mehci->wakeup_gpio = res->start;
1693 mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
1694 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1695 }
1696
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301697 ret = msm_hsic_init_clocks(mehci, 1);
1698 if (ret) {
1699 dev_err(&pdev->dev, "unable to initialize clocks\n");
1700 ret = -ENODEV;
1701 goto unmap;
1702 }
1703
1704 ret = msm_hsic_init_vddcx(mehci, 1);
1705 if (ret) {
1706 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1707 ret = -ENODEV;
1708 goto deinit_clocks;
1709 }
1710
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001711 init_completion(&mehci->rt_completion);
1712 init_completion(&mehci->gpt0_completion);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301713 ret = msm_hsic_reset(mehci);
1714 if (ret) {
1715 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301716 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301717 }
1718
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001719 ehci_wq = create_singlethread_workqueue("ehci_wq");
1720 if (!ehci_wq) {
1721 dev_err(&pdev->dev, "unable to create workqueue\n");
1722 ret = -ENOMEM;
1723 goto deinit_vddcx;
1724 }
1725
1726 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1727
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301728 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1729 if (ret) {
1730 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301731 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301732 }
1733
1734 device_init_wakeup(&pdev->dev, 1);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001735 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1736 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001737
1738 if (mehci->peripheral_status_irq) {
1739 ret = request_threaded_irq(mehci->peripheral_status_irq,
1740 NULL, hsic_peripheral_status_change,
1741 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1742 | IRQF_SHARED,
1743 "hsic_peripheral_status", mehci);
1744 if (ret)
1745 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1746 __func__, mehci->peripheral_status_irq, ret);
1747 }
1748
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001749 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001750 if (mehci->wakeup_irq) {
Hemant Kumar5e386632012-08-30 14:23:38 -07001751 /* In case if wakeup gpio is pulled high at this point
1752 * remote wakeup interrupt fires right after request_irq.
1753 * Remote wake up interrupt only needs to be enabled when
1754 * HSIC bus goes to suspend.
1755 */
1756 irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001757 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001758 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001759 "msm_hsic_wakeup", mehci);
Hemant Kumar5e386632012-08-30 14:23:38 -07001760 if (ret) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001761 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1762 mehci->wakeup_irq, ret);
1763 mehci->wakeup_irq = 0;
1764 }
1765 }
1766
Hemant Kumare6275972012-02-29 20:06:21 -08001767 ret = ehci_hsic_msm_debugfs_init(mehci);
1768 if (ret)
1769 dev_dbg(&pdev->dev, "mode debugfs file is"
1770 "not available\n");
1771
1772 if (pdata && pdata->bus_scale_table) {
1773 mehci->bus_perf_client =
1774 msm_bus_scale_register_client(pdata->bus_scale_table);
1775 /* Configure BUS performance parameters for MAX bandwidth */
1776 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001777 mehci->bus_vote = true;
1778 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001779 } else {
1780 dev_err(&pdev->dev, "%s: Failed to register BUS "
1781 "scaling client!!\n", __func__);
1782 }
1783 }
1784
Hemant Kumar105d07f2012-07-02 15:33:07 -07001785 __mehci = mehci;
1786
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301787 if (pdata && pdata->swfi_latency)
1788 pm_qos_add_request(&mehci->pm_qos_req_dma,
1789 PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
1790
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301791 /*
1792 * This pdev->dev is assigned parent of root-hub by USB core,
1793 * hence, runtime framework automatically calls this driver's
1794 * runtime APIs based on root-hub's state.
1795 */
1796 pm_runtime_set_active(&pdev->dev);
1797 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301798 /* Decrement the parent device's counter after probe.
1799 * As child is active, parent will not be put into
1800 * suspend mode.
1801 */
1802 if (pdev->dev.parent)
1803 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301804
1805 return 0;
1806
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301807unconfig_gpio:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001808 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301809 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301810deinit_vddcx:
1811 msm_hsic_init_vddcx(mehci, 0);
1812deinit_clocks:
1813 msm_hsic_init_clocks(mehci, 0);
1814unmap:
1815 iounmap(hcd->regs);
1816put_hcd:
1817 usb_put_hcd(hcd);
1818
1819 return ret;
1820}
1821
1822static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1823{
1824 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1825 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301826 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1827
Pavankumar Kondetifff3f2e2013-02-12 21:43:56 +05301828 /* Remove the HCD prior to releasing our resources. */
1829 usb_remove_hcd(hcd);
1830
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301831 if (pdata && pdata->swfi_latency)
1832 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301833
Vamsi Krishna34f01582011-12-14 19:54:42 -08001834 if (mehci->peripheral_status_irq)
1835 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001836
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001837 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001838 if (mehci->wakeup_irq_enabled)
1839 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001840 free_irq(mehci->wakeup_irq, mehci);
1841 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001842
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001843 /*
1844 * If the update request is called after unregister, the request will
1845 * fail. Results are undefined if unregister is called in the middle of
1846 * update request.
1847 */
1848 mehci->bus_vote = false;
1849 cancel_work_sync(&mehci->bus_vote_w);
1850
Hemant Kumare6275972012-02-29 20:06:21 -08001851 if (mehci->bus_perf_client)
1852 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1853
1854 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301855 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301856 pm_runtime_set_suspended(&pdev->dev);
1857
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001858 destroy_workqueue(ehci_wq);
1859
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301860 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301861 msm_hsic_init_vddcx(mehci, 0);
1862
1863 msm_hsic_init_clocks(mehci, 0);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001864 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301865 iounmap(hcd->regs);
1866 usb_put_hcd(hcd);
1867
1868 return 0;
1869}
1870
1871#ifdef CONFIG_PM_SLEEP
1872static int msm_hsic_pm_suspend(struct device *dev)
1873{
Jack Phambe05fbb2012-05-16 10:56:26 -07001874 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301875 struct usb_hcd *hcd = dev_get_drvdata(dev);
1876 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1877
1878 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1879
Hemant Kumar45d211b2012-05-31 17:58:43 -07001880 dbg_log_event(NULL, "PM Suspend", 0);
1881
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301882 if (device_may_wakeup(dev))
1883 enable_irq_wake(hcd->irq);
1884
Jack Phambe05fbb2012-05-16 10:56:26 -07001885 ret = msm_hsic_suspend(mehci);
1886
1887 if (ret && device_may_wakeup(dev))
1888 disable_irq_wake(hcd->irq);
1889
1890 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001891}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301892
Jack Pham16b06f82012-08-14 20:03:59 -07001893static int msm_hsic_pm_suspend_noirq(struct device *dev)
1894{
1895 struct usb_hcd *hcd = dev_get_drvdata(dev);
1896 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1897
Pavankumar Kondetibbd05822013-01-28 17:04:39 +05301898 if (atomic_read(&mehci->async_int)) {
Jack Pham16b06f82012-08-14 20:03:59 -07001899 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
1900 return -EBUSY;
1901 }
1902
1903 return 0;
1904}
1905
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301906static int msm_hsic_pm_resume(struct device *dev)
1907{
1908 int ret;
1909 struct usb_hcd *hcd = dev_get_drvdata(dev);
1910 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1911
Jack Pham16b06f82012-08-14 20:03:59 -07001912 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001913 dbg_log_event(NULL, "PM Resume", 0);
1914
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301915 if (device_may_wakeup(dev))
1916 disable_irq_wake(hcd->irq);
1917
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301918 /*
1919 * Keep HSIC in Low Power Mode if system is resumed
1920 * by any other wakeup source. HSIC is resumed later
1921 * when remote wakeup is received or interface driver
1922 * start I/O.
1923 */
Pavankumar Kondeti98089c02012-11-09 10:54:00 +05301924 if (!atomic_read(&mehci->pm_usage_cnt) &&
Pavankumar Kondetibbd05822013-01-28 17:04:39 +05301925 !atomic_read(&mehci->async_int) &&
Pavankumar Kondeti98089c02012-11-09 10:54:00 +05301926 pm_runtime_suspended(dev))
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301927 return 0;
1928
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301929 ret = msm_hsic_resume(mehci);
1930 if (ret)
1931 return ret;
1932
1933 /* Bring the device to full powered state upon system resume */
1934 pm_runtime_disable(dev);
1935 pm_runtime_set_active(dev);
1936 pm_runtime_enable(dev);
1937
1938 return 0;
1939}
1940#endif
1941
1942#ifdef CONFIG_PM_RUNTIME
1943static int msm_hsic_runtime_idle(struct device *dev)
1944{
1945 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301946 return 0;
1947}
1948
1949static int msm_hsic_runtime_suspend(struct device *dev)
1950{
1951 struct usb_hcd *hcd = dev_get_drvdata(dev);
1952 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1953
1954 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001955
1956 dbg_log_event(NULL, "Run Time PM Suspend", 0);
1957
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301958 return msm_hsic_suspend(mehci);
1959}
1960
1961static int msm_hsic_runtime_resume(struct device *dev)
1962{
1963 struct usb_hcd *hcd = dev_get_drvdata(dev);
1964 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1965
1966 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001967
1968 dbg_log_event(NULL, "Run Time PM Resume", 0);
1969
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301970 return msm_hsic_resume(mehci);
1971}
1972#endif
1973
1974#ifdef CONFIG_PM
1975static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1976 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07001977 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301978 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1979 msm_hsic_runtime_idle)
1980};
1981#endif
1982
1983static struct platform_driver ehci_msm_hsic_driver = {
1984 .probe = ehci_hsic_msm_probe,
1985 .remove = __devexit_p(ehci_hsic_msm_remove),
1986 .driver = {
1987 .name = "msm_hsic_host",
1988#ifdef CONFIG_PM
1989 .pm = &msm_hsic_dev_pm_ops,
1990#endif
1991 },
1992};