blob: 7ee672d908b469f81fb42f746d21e7c78179ada0 [file] [log] [blame]
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301/* ehci-msm-hsic.c - HSUSB Host Controller Driver Implementation
2 *
Ido Shayevitz95c46882013-01-20 13:47:46 +02003 * Copyright (c) 2011-2013, The 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>
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
Manu Gautam863b74132012-11-21 14:30:04 +053034#include <linux/usb/ulpi.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053035#include <linux/usb/msm_hsusb_hw.h>
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +053036#include <linux/usb/msm_hsusb.h>
37#include <linux/gpio.h>
Manu Gautam863b74132012-11-21 14:30:04 +053038#include <linux/of_gpio.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030039#include <linux/spinlock.h>
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -070040#include <linux/irq.h>
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070041#include <linux/kthread.h>
42#include <linux/wait.h>
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +053043#include <linux/pm_qos.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030044
45#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053046#include <mach/clk.h>
47#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053048#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080049#include <linux/spinlock.h>
Hemant Kumar45d211b2012-05-31 17:58:43 -070050#include <linux/cpu.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030051#include <mach/rpm-regulator.h>
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +020052#include "hbm.c"
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053053
54#define MSM_USB_BASE (hcd->regs)
Hemant Kumar105d07f2012-07-02 15:33:07 -070055#define USB_REG_START_OFFSET 0x90
56#define USB_REG_END_OFFSET 0x250
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053057
Hemant Kumar2309eaa2012-08-14 16:46:42 -070058static struct workqueue_struct *ehci_wq;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070059struct ehci_timer {
60#define GPT_LD(p) ((p) & 0x00FFFFFF)
61 u32 gptimer0_ld;
62#define GPT_RUN BIT(31)
63#define GPT_RESET BIT(30)
64#define GPT_MODE BIT(24)
65#define GPT_CNT(p) ((p) & 0x00FFFFFF)
66 u32 gptimer0_ctrl;
67
68 u32 gptimer1_ld;
69 u32 gptimer1_ctrl;
70};
Hemant Kumar2309eaa2012-08-14 16:46:42 -070071
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053072struct msm_hsic_hcd {
73 struct ehci_hcd ehci;
Hemant Kumard343c012012-09-06 19:57:14 -070074 spinlock_t wakeup_lock;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053075 struct device *dev;
76 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080077 struct clk *core_clk;
78 struct clk *alt_core_clk;
79 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053080 struct clk *cal_clk;
Ido Shayevitz5dfbb132013-04-18 13:22:07 +030081 struct clk *inactivity_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053082 struct regulator *hsic_vddcx;
Ofir Cohen4cc55372012-11-20 11:17:24 +020083 struct regulator *hsic_gdsc;
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +053084 atomic_t async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053085 atomic_t in_lpm;
Sudhir Sharma1673e302012-08-27 17:37:24 -070086 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080087 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080088 int wakeup_irq;
Jack Phamfe441ea2012-03-23 17:03:15 -070089 bool wakeup_irq_enabled;
Manu Gautam3fb60ca2013-02-13 18:33:33 +053090 int async_irq;
91 uint32_t async_int_cnt;
Sudhir Sharma1673e302012-08-27 17:37:24 -070092 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080093 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070094 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030095 enum usb_vdd_type vdd_type;
Hemant Kumar2309eaa2012-08-14 16:46:42 -070096
97 struct work_struct bus_vote_w;
98 bool bus_vote;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070099
100 /* gp timer */
101 struct ehci_timer __iomem *timer;
102 struct completion gpt0_completion;
103 struct completion rt_completion;
104 int resume_status;
105 int resume_again;
Pavankumar Kondeti23720492013-01-29 14:41:58 +0530106 int bus_reset;
107 int reset_again;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +0530108
109 struct pm_qos_request pm_qos_req_dma;
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +0200110 unsigned enable_hbm:1;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530111};
112
Hemant Kumar105d07f2012-07-02 15:33:07 -0700113struct msm_hsic_hcd *__mehci;
114
Hemant Kumare6275972012-02-29 20:06:21 -0800115static bool debug_bus_voting_enabled = true;
Ofir Cohen4cc55372012-11-20 11:17:24 +0200116static u64 ehci_msm_hsic_dma_mask = DMA_BIT_MASK(32);
117
Manu Gautam863b74132012-11-21 14:30:04 +0530118static struct platform_driver ehci_msm_hsic_driver;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700119
Hemant Kumar4d50a432012-08-15 09:06:35 -0700120static unsigned int enable_payload_log = 1;
121module_param(enable_payload_log, uint, S_IRUGO | S_IWUSR);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700122static unsigned int enable_dbg_log = 1;
123module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
124/*by default log ep0 and efs sync ep*/
125static unsigned int ep_addr_rxdbg_mask = 9;
126module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
127static unsigned int ep_addr_txdbg_mask = 9;
128module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
129
130/* Maximum debug message length */
Hemant Kumar4d50a432012-08-15 09:06:35 -0700131#define DBG_MSG_LEN 128UL
Hemant Kumar45d211b2012-05-31 17:58:43 -0700132
133/* Maximum number of messages */
134#define DBG_MAX_MSG 256UL
135
136#define TIME_BUF_LEN 20
Hemant Kumar4d50a432012-08-15 09:06:35 -0700137#define HEX_DUMP_LEN 72
Hemant Kumar45d211b2012-05-31 17:58:43 -0700138
139enum event_type {
140 EVENT_UNDEF = -1,
141 URB_SUBMIT,
142 URB_COMPLETE,
143 EVENT_NONE,
144};
145
146#define EVENT_STR_LEN 5
147
Hemant Kumar45d211b2012-05-31 17:58:43 -0700148static enum event_type str_to_event(const char *name)
149{
150 if (!strncasecmp("S", name, EVENT_STR_LEN))
151 return URB_SUBMIT;
152 if (!strncasecmp("C", name, EVENT_STR_LEN))
153 return URB_COMPLETE;
154 if (!strncasecmp("", name, EVENT_STR_LEN))
155 return EVENT_NONE;
156
157 return EVENT_UNDEF;
158}
159
160/*log ep0 activity*/
161static struct {
162 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
163 unsigned idx; /* index */
164 rwlock_t lck; /* lock */
165} dbg_hsic_ctrl = {
166 .idx = 0,
167 .lck = __RW_LOCK_UNLOCKED(lck)
168};
169
170static struct {
171 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
172 unsigned idx; /* index */
173 rwlock_t lck; /* lock */
174} dbg_hsic_data = {
175 .idx = 0,
176 .lck = __RW_LOCK_UNLOCKED(lck)
177};
178
179/**
180 * dbg_inc: increments debug event index
181 * @idx: buffer index
182 */
183static void dbg_inc(unsigned *idx)
184{
185 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
186}
187
188/*get_timestamp - returns time of day in us */
189static char *get_timestamp(char *tbuf)
190{
191 unsigned long long t;
192 unsigned long nanosec_rem;
193
194 t = cpu_clock(smp_processor_id());
195 nanosec_rem = do_div(t, 1000000000)/1000;
196 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
197 nanosec_rem);
198 return tbuf;
199}
200
201static int allow_dbg_log(int ep_addr)
202{
203 int dir, num;
204
205 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
206 num = ep_addr & ~USB_DIR_IN;
207 num = 1 << num;
208
209 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
210 return 1;
211 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
212 return 1;
213
214 return 0;
215}
216
Hemant Kumar4d50a432012-08-15 09:06:35 -0700217static char *get_hex_data(char *dbuf, struct urb *urb, int event, int status)
218{
219 int ep_addr = urb->ep->desc.bEndpointAddress;
220 char *ubuf = urb->transfer_buffer;
221 size_t len = event ? \
222 urb->actual_length : urb->transfer_buffer_length;
223
224 if (status == -EINPROGRESS)
225 status = 0;
226
227 /*Only dump ep in completions and epout submissions*/
228 if (len && !status &&
229 (((ep_addr & USB_DIR_IN) && event) ||
230 (!(ep_addr & USB_DIR_IN) && !event))) {
231 if (len >= 32)
232 len = 32;
233 hex_dump_to_buffer(ubuf, len, 32, 4, dbuf, HEX_DUMP_LEN, 0);
234 } else {
235 dbuf = "";
236 }
237
238 return dbuf;
239}
240
Hemant Kumar45d211b2012-05-31 17:58:43 -0700241static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
242{
243 unsigned long flags;
244 int ep_addr;
245 char tbuf[TIME_BUF_LEN];
Hemant Kumar4d50a432012-08-15 09:06:35 -0700246 char dbuf[HEX_DUMP_LEN];
Hemant Kumar45d211b2012-05-31 17:58:43 -0700247
248 if (!enable_dbg_log)
249 return;
250
251 if (!urb) {
252 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
253 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700254 "%s: %s : %u", get_timestamp(tbuf), event, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700255 dbg_inc(&dbg_hsic_ctrl.idx);
256 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
257 return;
258 }
259
260 ep_addr = urb->ep->desc.bEndpointAddress;
261 if (!allow_dbg_log(ep_addr))
262 return;
263
264 if ((ep_addr & 0x0f) == 0x0) {
265 /*submit event*/
266 if (!str_to_event(event)) {
267 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
268 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
269 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
Hemant Kumar4d50a432012-08-15 09:06:35 -0700270 "%02x %02x %04x %04x %04x %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700271 get_timestamp(tbuf), event, urb,
272 (ep_addr & USB_DIR_IN) ? "in" : "out",
273 urb->setup_packet[0], urb->setup_packet[1],
274 (urb->setup_packet[3] << 8) |
275 urb->setup_packet[2],
276 (urb->setup_packet[5] << 8) |
277 urb->setup_packet[4],
278 (urb->setup_packet[7] << 8) |
279 urb->setup_packet[6],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700280 urb->transfer_buffer_length, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700281
282 dbg_inc(&dbg_hsic_ctrl.idx);
283 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
284 } else {
285 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
286 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700287 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700288 get_timestamp(tbuf), event, urb,
289 (ep_addr & USB_DIR_IN) ? "in" : "out",
290 urb->actual_length, extra);
291
292 dbg_inc(&dbg_hsic_ctrl.idx);
293 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
294 }
295 } else {
296 write_lock_irqsave(&dbg_hsic_data.lck, flags);
297 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700298 "%s: [%s : %p]:ep%d[%s] %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700299 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
300 (ep_addr & USB_DIR_IN) ? "in" : "out",
301 str_to_event(event) ? urb->actual_length :
Hemant Kumar4d50a432012-08-15 09:06:35 -0700302 urb->transfer_buffer_length, extra,
303 enable_payload_log ? get_hex_data(dbuf, urb,
304 str_to_event(event), extra) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700305
306 dbg_inc(&dbg_hsic_data.idx);
307 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
308 }
309}
310
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530311static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
312{
313 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
314}
315
316static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
317{
318 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
319}
320
Hemant Kumar105d07f2012-07-02 15:33:07 -0700321static void dump_hsic_regs(struct usb_hcd *hcd)
322{
323 int i;
324 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
325
326 if (atomic_read(&mehci->in_lpm))
327 return;
328
329 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
330 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
331 readl_relaxed(hcd->regs + i),
332 readl_relaxed(hcd->regs + i + 4),
333 readl_relaxed(hcd->regs + i + 8),
334 readl_relaxed(hcd->regs + i + 0xc));
335}
336
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530337#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
338
Amit Blayd6ea6102012-06-07 16:26:24 +0300339#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Hemant Kumar3b743cd2012-10-17 13:48:10 -0700340#define USB_PHY_VDD_DIG_VOL_MIN 945000 /* uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700341#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530342
Lena Salman8c8ba382012-02-14 15:59:31 +0200343#define HSIC_DBG1_REG 0x38
344
Amit Blayd6ea6102012-06-07 16:26:24 +0300345static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
346 { /* VDD_CX CORNER Voting */
347 [VDD_NONE] = RPM_VREG_CORNER_NONE,
348 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
349 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
350 },
351 { /* VDD_CX Voltage Voting */
352 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
353 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
354 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
355 },
356};
357
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530358static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
359{
360 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300361 int none_vol, min_vol, max_vol;
362
363 if (!mehci->hsic_vddcx) {
364 mehci->vdd_type = VDDCX_CORNER;
365 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
366 "hsic_vdd_dig");
367 if (IS_ERR(mehci->hsic_vddcx)) {
368 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
369 "HSIC_VDDCX");
370 if (IS_ERR(mehci->hsic_vddcx)) {
371 dev_err(mehci->dev, "unable to get hsic vddcx\n");
372 return PTR_ERR(mehci->hsic_vddcx);
373 }
374 mehci->vdd_type = VDDCX;
375 }
376 }
377
378 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
379 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
380 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530381
382 if (!init)
383 goto disable_reg;
384
Amit Blayd6ea6102012-06-07 16:26:24 +0300385 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530386 if (ret) {
387 dev_err(mehci->dev, "unable to set the voltage"
388 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530389 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530390 }
391
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530392 ret = regulator_enable(mehci->hsic_vddcx);
393 if (ret) {
394 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
395 goto reg_enable_err;
396 }
397
398 return 0;
399
400disable_reg:
401 regulator_disable(mehci->hsic_vddcx);
402reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300403 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
404
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530405 return ret;
406
407}
408
Ofir Cohen4cc55372012-11-20 11:17:24 +0200409/* Global Distributed Switch Controller (GDSC) init */
410static int msm_hsic_init_gdsc(struct msm_hsic_hcd *mehci, int init)
411{
412 int ret = 0;
413
414 if (IS_ERR(mehci->hsic_gdsc))
415 return 0;
416
417 if (!mehci->hsic_gdsc) {
418 mehci->hsic_gdsc = devm_regulator_get(mehci->dev,
419 "HSIC_GDSC");
420 if (IS_ERR(mehci->hsic_gdsc))
421 return 0;
422 }
423
424 if (init) {
425 ret = regulator_enable(mehci->hsic_gdsc);
426 if (ret) {
427 dev_err(mehci->dev, "unable to enable hsic gdsc\n");
428 return ret;
429 }
430 } else {
431 regulator_disable(mehci->hsic_gdsc);
432 }
433
434 return 0;
435
436}
437
Pavankumar Kondeti23720492013-01-29 14:41:58 +0530438static int __maybe_unused ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700439{
440 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700441 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700442
443 /* initiate read operation */
444 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
445 USB_ULPI_VIEWPORT);
446
447 /* wait for completion */
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700448 while (cnt < ULPI_IO_TIMEOUT_USEC) {
449 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
450 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700451 udelay(1);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700452 cnt++;
453 }
454
455 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
456 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
457 readl_relaxed(USB_ULPI_VIEWPORT));
458 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
459 readl_relaxed(USB_PORTSC),
460 readl_relaxed(USB_USBCMD),
461 readl_relaxed(USB_FRINDEX));
462
463 /*frame counter increments afte 125us*/
464 udelay(130);
465 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
466 readl_relaxed(USB_FRINDEX));
467 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700468 }
469
470 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
471}
472
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530473static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
474{
475 struct usb_hcd *hcd = hsic_to_hcd(mehci);
476 int cnt = 0;
477
478 /* initiate write operation */
479 writel_relaxed(ULPI_RUN | ULPI_WRITE |
480 ULPI_ADDR(reg) | ULPI_DATA(val),
481 USB_ULPI_VIEWPORT);
482
483 /* wait for completion */
484 while (cnt < ULPI_IO_TIMEOUT_USEC) {
485 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
486 break;
487 udelay(1);
488 cnt++;
489 }
490
491 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700492 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
493 readl_relaxed(USB_ULPI_VIEWPORT));
494 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
495 readl_relaxed(USB_PORTSC),
496 readl_relaxed(USB_USBCMD),
497 readl_relaxed(USB_FRINDEX));
498
499 /*frame counter increments afte 125us*/
500 udelay(130);
501 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
502 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530503 return -ETIMEDOUT;
504 }
505
506 return 0;
507}
508
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530509static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
510{
511 int rc = 0;
512 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800513 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530514
515 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800516
Lena Salman8c8ba382012-02-14 15:59:31 +0200517 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530518 return rc;
519
Vamsi Krishna34f01582011-12-14 19:54:42 -0800520 if (gpio_status == gpio_en)
521 return 0;
522
523 gpio_status = gpio_en;
524
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530525 if (!gpio_en)
526 goto free_gpio;
527
528 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
529 if (rc < 0) {
530 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
531 return rc;
532 }
533
534 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
535 if (rc < 0) {
536 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
537 goto free_strobe;
Hemant Kumar6fd65032012-05-23 13:02:24 -0700538 }
539
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530540 return 0;
541
542free_gpio:
543 gpio_free(pdata->data);
544free_strobe:
545 gpio_free(pdata->strobe);
546
547 return rc;
548}
549
Vamsi Krishna64b48612012-06-14 16:08:11 -0700550static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530551{
552 int ret;
553
Ofir Cohen07944aa2012-12-23 13:41:57 +0200554 /* alt_core_clk exists in targets that do not use asynchronous reset */
555 if (!IS_ERR(mehci->alt_core_clk)) {
556 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
557 if (ret) {
558 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
559 return;
560 }
561
562 /* Since a hw bug, turn off the clock before complete reset */
563 clk_disable(mehci->core_clk);
564
565 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
566 if (ret)
567 dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
568 ret);
569
570 usleep_range(10000, 12000);
571
572 clk_enable(mehci->core_clk);
573 } else {
574 /* Using asynchronous block reset to the hardware */
575 clk_disable_unprepare(mehci->core_clk);
576 clk_disable_unprepare(mehci->phy_clk);
577 clk_disable_unprepare(mehci->cal_clk);
578 clk_disable_unprepare(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +0300579 if (!IS_ERR(mehci->inactivity_clk))
580 clk_disable_unprepare(mehci->inactivity_clk);
Ofir Cohen07944aa2012-12-23 13:41:57 +0200581
582 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
583 if (ret) {
584 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
585 return;
586 }
587 usleep_range(10000, 12000);
588
589 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
590 if (ret)
591 dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
592 ret);
593 /*
594 * Required delay between the deassertion and
595 * clock enablement.
596 */
597 ndelay(200);
598 clk_prepare_enable(mehci->core_clk);
599 clk_prepare_enable(mehci->phy_clk);
600 clk_prepare_enable(mehci->cal_clk);
601 clk_prepare_enable(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +0300602 if (!IS_ERR(mehci->inactivity_clk))
603 clk_prepare_enable(mehci->inactivity_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530604 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530605}
606
Vamsi Krishna64b48612012-06-14 16:08:11 -0700607#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
608#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530609#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
610#define HSIC_LV_MODE 0x04
611#define HSIC_PAD_CALIBRATION 0xA8
612#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530613#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
Ofir Cohen5dddb152012-11-14 11:18:50 +0200614
615static void msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530616{
617 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530618
Vamsi Krishna64b48612012-06-14 16:08:11 -0700619 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530620
Vamsi Krishna64b48612012-06-14 16:08:11 -0700621 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530622 writel_relaxed(0x80000000, USB_PORTSC);
Vamsi Krishna64b48612012-06-14 16:08:11 -0700623 mb();
Ofir Cohen5dddb152012-11-14 11:18:50 +0200624}
625
626static int msm_hsic_start(struct msm_hsic_hcd *mehci)
627{
628 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
629 int ret;
Manu Gautam863b74132012-11-21 14:30:04 +0530630 void __iomem *reg;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530631
Vamsi Krishnabef91832013-03-11 14:10:20 -0700632 if (pdata && pdata->resume_gpio) {
633 ret = gpio_request(pdata->resume_gpio, "HSIC_RESUME_GPIO");
634 if (ret < 0) {
635 dev_err(mehci->dev,
636 "gpio req failed for hsic resume:%d\n", ret);
637 pdata->resume_gpio = 0;
638 }
639 }
640
Lena Salman8c8ba382012-02-14 15:59:31 +0200641 /* HSIC init sequence when HSIC signals (Strobe/Data) are
642 routed via GPIOs */
643 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530644
Manu Gautam863b74132012-11-21 14:30:04 +0530645 if (!pdata->ignore_cal_pad_config) {
646 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
647 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
648 mb();
649 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700650
Lena Salman8c8ba382012-02-14 15:59:31 +0200651 /*set periodic calibration interval to ~2.048sec in
652 HSIC_IO_CAL_REG */
653 ulpi_write(mehci, 0xFF, 0x33);
654
655 /* Enable periodic IO calibration in HSIC_CFG register */
656 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
657
Vamsi Krishna64b48612012-06-14 16:08:11 -0700658 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200659 ret = msm_hsic_config_gpios(mehci, 1);
660 if (ret) {
661 dev_err(mehci->dev, " gpio configuarion failed\n");
Vamsi Krishnabef91832013-03-11 14:10:20 -0700662 goto free_resume_gpio;
Lena Salman8c8ba382012-02-14 15:59:31 +0200663 }
Manu Gautam863b74132012-11-21 14:30:04 +0530664 if (pdata->strobe_pad_offset) {
665 /* Set CORE_CTL_EN in STROBE GPIO PAD_CTL register */
666 reg = MSM_TLMM_BASE + pdata->strobe_pad_offset;
667 writel_relaxed(readl_relaxed(reg) | 0x2000000, reg);
668 } else {
669 /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */
670 reg = HSIC_STROBE_GPIO_PAD_CTL;
671 writel_relaxed(HSIC_GPIO_PAD_VAL, reg);
672 }
673
674 if (pdata->data_pad_offset) {
675 /* Set CORE_CTL_EN in HSIC_DATA GPIO PAD_CTL register */
676 reg = MSM_TLMM_BASE + pdata->data_pad_offset;
677 writel_relaxed(readl_relaxed(reg) | 0x2000000, reg);
678 } else {
679 /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */
680 reg = HSIC_DATA_GPIO_PAD_CTL;
681 writel_relaxed(HSIC_GPIO_PAD_VAL, reg);
682 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700683
684 mb();
685
Lena Salman8c8ba382012-02-14 15:59:31 +0200686 /* Enable HSIC mode in HSIC_CFG register */
687 ulpi_write(mehci, 0x01, 0x31);
688 } else {
689 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
690 via dedicated I/O */
691
692 /* programmable length of connect signaling (33.2ns) */
693 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
694 if (ret) {
695 pr_err("%s: Unable to program length of connect "
696 "signaling\n", __func__);
697 }
698
699 /*set periodic calibration interval to ~2.048sec in
700 HSIC_IO_CAL_REG */
701 ulpi_write(mehci, 0xFF, 0x33);
702
703 /* Enable HSIC mode in HSIC_CFG register */
704 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530705 }
706
Hemant Kumar6fd65032012-05-23 13:02:24 -0700707 /*disable auto resume*/
708 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
709
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530710 return 0;
Vamsi Krishnabef91832013-03-11 14:10:20 -0700711
712free_resume_gpio:
713 if (pdata && pdata->resume_gpio)
714 gpio_free(pdata->resume_gpio);
715
716 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530717}
718
719#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
720#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
721
722#ifdef CONFIG_PM_SLEEP
Ofir Cohen5dddb152012-11-14 11:18:50 +0200723static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
724{
725 /* reset HSIC phy */
726 msm_hsic_phy_reset(mehci);
727
728 /* HSIC init procedure (caliberation) */
729 return msm_hsic_start(mehci);
730}
731
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530732static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
733{
734 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530735 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530736 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300737 int none_vol, max_vol;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700738 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530739
740 if (atomic_read(&mehci->in_lpm)) {
741 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
742 return 0;
743 }
744
745 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700746
Sudhir Sharma1673e302012-08-27 17:37:24 -0700747 /* make sure we don't race against a remote wakeup */
748 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700749 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Sudhir Sharma1673e302012-08-27 17:37:24 -0700750 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700751 enable_irq(hcd->irq);
752 return -EBUSY;
753 }
754
Ido Shayevitzaa165c52013-05-12 16:01:28 +0200755 if (pdata->consider_ipa_handshake) {
756 dev_dbg(mehci->dev, "%s:Wait for resources release\n",
757 __func__);
758 if (!msm_bam_hsic_lpm_ok()) {
759 dev_dbg(mehci->dev, "%s:Prod+Cons not released\n",
760 __func__);
761 enable_irq(hcd->irq);
762 return -EBUSY;
763 }
764 dev_dbg(mehci->dev, "%s:Prod+Cons resources released\n",
765 __func__);
766 }
767
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530768 /*
769 * PHY may take some time or even fail to enter into low power
770 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
771 * in failure case.
772 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700773 val = readl_relaxed(USB_PORTSC);
774 val &= ~PORT_RWC_BITS;
775 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530776 writel_relaxed(val, USB_PORTSC);
777 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
778 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
779 break;
780 udelay(1);
781 cnt++;
782 }
783
784 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
785 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530786 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530787 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530788 }
789
790 /*
791 * PHY has capability to generate interrupt asynchronously in low
792 * power mode (LPM). This interrupt is level triggered. So USB IRQ
793 * line must be disabled till async interrupt enable bit is cleared
794 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
Pavankumar Kondeti0c9f29c2013-01-28 21:37:59 +0530795 * block data communication from PHY. Enable asynchronous interrupt
796 * only when wakeup gpio IRQ is not present.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530797 */
Pavankumar Kondeti0c9f29c2013-01-28 21:37:59 +0530798 if (mehci->wakeup_irq)
799 writel_relaxed(readl_relaxed(USB_USBCMD) |
800 ULPI_STP_CTRL, USB_USBCMD);
801 else
802 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530803 ULPI_STP_CTRL, USB_USBCMD);
804
805 /*
806 * Ensure that hardware is put in low power mode before
807 * clocks are turned OFF and VDD is allowed to minimize.
808 */
809 mb();
810
Manu Gautam28b1bac2012-01-30 16:43:06 +0530811 clk_disable_unprepare(mehci->core_clk);
812 clk_disable_unprepare(mehci->phy_clk);
813 clk_disable_unprepare(mehci->cal_clk);
814 clk_disable_unprepare(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +0300815 if (!IS_ERR(mehci->inactivity_clk))
816 clk_disable_unprepare(mehci->inactivity_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530817
Amit Blayd6ea6102012-06-07 16:26:24 +0300818 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
819 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
820
821 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700822 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300823 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700824
Hemant Kumare6275972012-02-29 20:06:21 -0800825 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700826 mehci->bus_vote = false;
827 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800828 }
829
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530830 atomic_set(&mehci->in_lpm, 1);
831 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700832
Manu Gautam3fb60ca2013-02-13 18:33:33 +0530833 if (mehci->wakeup_irq) {
834 mehci->wakeup_irq_enabled = 1;
835 enable_irq_wake(mehci->wakeup_irq);
836 enable_irq(mehci->wakeup_irq);
837 }
Hemant Kumar6fd65032012-05-23 13:02:24 -0700838
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700839 if (pdata && pdata->standalone_latency)
840 pm_qos_update_request(&mehci->pm_qos_req_dma,
841 PM_QOS_DEFAULT_VALUE);
842
Sudhir Sharma1673e302012-08-27 17:37:24 -0700843 wake_unlock(&mehci->wlock);
844
Ido Shayevitzaa165c52013-05-12 16:01:28 +0200845 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530846
847 return 0;
848}
849
850static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
851{
852 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530853 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530854 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300855 int min_vol, max_vol;
Hemant Kumard343c012012-09-06 19:57:14 -0700856 unsigned long flags;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700857 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530858
859 if (!atomic_read(&mehci->in_lpm)) {
860 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
861 return 0;
862 }
863
Ido Shayevitzaa165c52013-05-12 16:01:28 +0200864 if (pdata->consider_ipa_handshake) {
865 dev_dbg(mehci->dev, "%s:Wait for producer resource\n",
866 __func__);
867 msm_bam_wait_for_hsic_prod_granted();
868 dev_dbg(mehci->dev, "%s:Producer resource obtained\n",
869 __func__);
870 }
871
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530872 /* Handles race with Async interrupt */
873 disable_irq(hcd->irq);
874
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700875 if (pdata && pdata->standalone_latency)
876 pm_qos_update_request(&mehci->pm_qos_req_dma,
877 pdata->standalone_latency + 1);
878
Manu Gautam3fb60ca2013-02-13 18:33:33 +0530879 if (mehci->wakeup_irq) {
880 spin_lock_irqsave(&mehci->wakeup_lock, flags);
881 if (mehci->wakeup_irq_enabled) {
882 disable_irq_wake(mehci->wakeup_irq);
883 disable_irq_nosync(mehci->wakeup_irq);
884 mehci->wakeup_irq_enabled = 0;
885 }
886 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700887 }
888
Sudhir Sharma1673e302012-08-27 17:37:24 -0700889 wake_lock(&mehci->wlock);
890
Hemant Kumare6275972012-02-29 20:06:21 -0800891 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700892 mehci->bus_vote = true;
893 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800894 }
895
Amit Blayd6ea6102012-06-07 16:26:24 +0300896 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
897 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
898
899 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700900 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300901 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700902
Manu Gautam28b1bac2012-01-30 16:43:06 +0530903 clk_prepare_enable(mehci->core_clk);
904 clk_prepare_enable(mehci->phy_clk);
905 clk_prepare_enable(mehci->cal_clk);
906 clk_prepare_enable(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +0300907 if (!IS_ERR(mehci->inactivity_clk))
908 clk_prepare_enable(mehci->inactivity_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530909
910 temp = readl_relaxed(USB_USBCMD);
911 temp &= ~ASYNC_INTR_CTRL;
912 temp &= ~ULPI_STP_CTRL;
913 writel_relaxed(temp, USB_USBCMD);
914
915 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
916 goto skip_phy_resume;
917
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700918 temp = readl_relaxed(USB_PORTSC);
919 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530920 writel_relaxed(temp, USB_PORTSC);
921 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
922 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
923 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
924 break;
925 udelay(1);
926 cnt++;
927 }
928
929 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
930 /*
931 * This is a fatal error. Reset the link and
932 * PHY to make hsic working.
933 */
934 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530935 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530936 msm_hsic_reset(mehci);
937 }
938
939skip_phy_resume:
940
Hemant Kumar6fd65032012-05-23 13:02:24 -0700941 usb_hcd_resume_root_hub(hcd);
942
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530943 atomic_set(&mehci->in_lpm, 0);
944
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530945 if (atomic_read(&mehci->async_int)) {
946 atomic_set(&mehci->async_int, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530947 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700948 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700949 }
950
Sudhir Sharma1673e302012-08-27 17:37:24 -0700951 if (atomic_read(&mehci->pm_usage_cnt)) {
952 atomic_set(&mehci->pm_usage_cnt, 0);
953 pm_runtime_put_noidle(mehci->dev);
954 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700955
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530956 enable_irq(hcd->irq);
Ido Shayevitzaa165c52013-05-12 16:01:28 +0200957 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
958
959 if (pdata->consider_ipa_handshake) {
960 dev_dbg(mehci->dev, "%s:Notify usb bam on resume complete\n",
961 __func__);
962 msm_bam_hsic_notify_on_resume();
963 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530964
965 return 0;
966}
967#endif
968
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700969static void ehci_hsic_bus_vote_w(struct work_struct *w)
970{
971 struct msm_hsic_hcd *mehci =
972 container_of(w, struct msm_hsic_hcd, bus_vote_w);
973 int ret;
974
975 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
976 mehci->bus_vote);
977 if (ret)
978 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
979 __func__, ret);
980}
981
Pavankumar Kondeti23720492013-01-29 14:41:58 +0530982static int msm_hsic_reset_done(struct usb_hcd *hcd)
983{
984 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
985 u32 __iomem *status_reg = &ehci->regs->port_status[0];
986 int ret;
987
988 ehci_writel(ehci, ehci_readl(ehci, status_reg) & ~(PORT_RWC_BITS |
989 PORT_RESET), status_reg);
990
991 ret = handshake(ehci, status_reg, PORT_RESET, 0, 1 * 1000);
992
993 if (ret)
994 pr_err("reset handshake failed in %s\n", __func__);
995 else
996 ehci_writel(ehci, ehci_readl(ehci, &ehci->regs->command) |
997 CMD_RUN, &ehci->regs->command);
998
999 return ret;
1000}
1001
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001002#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301003static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
1004{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001005 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301006 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001007 u32 status;
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05301008 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301009
1010 if (atomic_read(&mehci->in_lpm)) {
Hemant Kumar3dbc5b32012-05-09 15:36:11 -07001011 dev_dbg(mehci->dev, "phy async intr\n");
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05301012 dbg_log_event(NULL, "Async IRQ", 0);
1013 ret = pm_runtime_get(mehci->dev);
1014 if ((ret == 1) || (ret == -EINPROGRESS)) {
1015 pm_runtime_put_noidle(mehci->dev);
1016 } else {
1017 disable_irq_nosync(hcd->irq);
1018 atomic_set(&mehci->async_int, 1);
1019 }
1020
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301021 return IRQ_HANDLED;
1022 }
1023
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001024 status = ehci_readl(ehci, &ehci->regs->status);
1025
1026 if (status & STS_GPTIMER0_INTERRUPT) {
1027 int timeleft;
1028
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301029 dbg_log_event(NULL, "FPR: gpt0_isr", mehci->bus_reset);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001030
1031 timeleft = GPT_CNT(ehci_readl(ehci,
1032 &mehci->timer->gptimer1_ctrl));
1033 if (timeleft) {
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301034 if (mehci->bus_reset) {
1035 ret = msm_hsic_reset_done(hcd);
1036 if (ret) {
1037 mehci->reset_again = 1;
1038 dbg_log_event(NULL, "RESET: fail", 0);
1039 }
1040 } else {
1041 ehci_writel(ehci, ehci_readl(ehci,
1042 &ehci->regs->command) | CMD_RUN,
1043 &ehci->regs->command);
1044 }
1045 } else {
1046 if (mehci->bus_reset)
1047 mehci->reset_again = 1;
1048 else
1049 mehci->resume_again = 1;
1050 }
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001051
1052 dbg_log_event(NULL, "FPR: timeleft", timeleft);
1053
1054 complete(&mehci->gpt0_completion);
1055 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
1056 }
1057
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301058 return ehci_irq(hcd);
1059}
1060
1061static int ehci_hsic_reset(struct usb_hcd *hcd)
1062{
1063 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001064 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Amit Blay1dfbbcc2013-05-26 17:33:13 +03001065 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301066 int retval;
1067
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001068 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301069 ehci->caps = USB_CAPLENGTH;
1070 ehci->regs = USB_CAPLENGTH +
1071 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
1072 dbg_hcs_params(ehci, "reset");
1073 dbg_hcc_params(ehci, "reset");
1074
1075 /* cache the data to minimize the chip reads*/
1076 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
1077
1078 hcd->has_tt = 1;
1079 ehci->sbrn = HCD_USB2;
1080
1081 retval = ehci_halt(ehci);
1082 if (retval)
1083 return retval;
1084
1085 /* data structure init */
1086 retval = ehci_init(hcd);
1087 if (retval)
1088 return retval;
1089
1090 retval = ehci_reset(ehci);
1091 if (retval)
1092 return retval;
1093
1094 /* bursts of unspecified length. */
1095 writel_relaxed(0, USB_AHBBURST);
Amit Blay1dfbbcc2013-05-26 17:33:13 +03001096
1097 /* Use the AHB transactor and configure async bridge bypass */
1098#define MSM_USB_ASYNC_BRIDGE_BYPASS BIT(31)
1099 if (pdata->ahb_async_bridge_bypass)
1100 writel_relaxed(0x08 | MSM_USB_ASYNC_BRIDGE_BYPASS, USB_AHBMODE);
1101 else
1102 writel_relaxed(0x08, USB_AHBMODE);
1103
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301104 /* Disable streaming mode and select host mode */
1105 writel_relaxed(0x13, USB_USBMODE);
1106
1107 ehci_port_power(ehci, 1);
1108 return 0;
1109}
1110
Jack Phamc0d41732012-09-28 17:45:38 -07001111#ifdef CONFIG_PM
1112
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301113#define RESET_RETRY_LIMIT 3
1114#define RESET_SIGNAL_TIME_SOF_USEC (50 * 1000)
1115#define RESET_SIGNAL_TIME_USEC (20 * 1000)
1116static void ehci_hsic_reset_sof_bug_handler(struct usb_hcd *hcd, u32 val)
1117{
1118 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1119 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1120 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1121 u32 __iomem *status_reg = &ehci->regs->port_status[0];
Pavankumar Kondetifc7d1d82013-03-05 09:43:22 +05301122 u32 cmd;
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301123 unsigned long flags;
1124 int retries = 0, ret, cnt = RESET_SIGNAL_TIME_USEC;
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301125 s32 next_latency = 0;
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301126
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301127 if (pdata && pdata->swfi_latency) {
1128 next_latency = pdata->swfi_latency + 1;
1129 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
1130 if (pdata->standalone_latency)
1131 next_latency = pdata->standalone_latency + 1;
1132 else
1133 next_latency = PM_QOS_DEFAULT_VALUE;
1134 }
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301135
1136 mehci->bus_reset = 1;
Pavankumar Kondetifc7d1d82013-03-05 09:43:22 +05301137
1138 /* Halt the controller */
1139 cmd = ehci_readl(ehci, &ehci->regs->command);
1140 cmd &= ~CMD_RUN;
1141 ehci_writel(ehci, cmd, &ehci->regs->command);
1142 ret = handshake(ehci, &ehci->regs->status, STS_HALT,
1143 STS_HALT, 16 * 125);
1144 if (ret) {
1145 pr_err("halt handshake fatal error\n");
1146 dbg_log_event(NULL, "HALT: fatal", 0);
1147 goto fail;
1148 }
1149
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301150retry:
1151 retries++;
1152 dbg_log_event(NULL, "RESET: start", retries);
1153 pr_debug("reset begin %d\n", retries);
1154 mehci->reset_again = 0;
1155 spin_lock_irqsave(&ehci->lock, flags);
1156 ehci_writel(ehci, val, status_reg);
1157 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_USEC - 1),
1158 &mehci->timer->gptimer0_ld);
1159 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1160 &mehci->timer->gptimer0_ctrl);
1161 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1162 &ehci->regs->intr_enable);
1163
1164 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_SOF_USEC - 1),
1165 &mehci->timer->gptimer1_ld);
1166 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1167 &mehci->timer->gptimer1_ctrl);
1168
1169 spin_unlock_irqrestore(&ehci->lock, flags);
1170 wait_for_completion(&mehci->gpt0_completion);
1171
1172 if (!mehci->reset_again)
1173 goto done;
1174
1175 if (handshake(ehci, status_reg, PORT_RESET, 0, 10 * 1000)) {
1176 pr_err("reset handshake fatal error\n");
1177 dbg_log_event(NULL, "RESET: fatal", retries);
1178 goto fail;
1179 }
1180
1181 if (retries < RESET_RETRY_LIMIT)
1182 goto retry;
1183
1184 /* complete reset in tight loop */
1185 pr_info("RESET in tight loop\n");
1186 dbg_log_event(NULL, "RESET: tight", 0);
1187
1188 spin_lock_irqsave(&ehci->lock, flags);
1189 ehci_writel(ehci, val, status_reg);
1190 while (cnt--)
1191 udelay(1);
1192 ret = msm_hsic_reset_done(hcd);
1193 spin_unlock_irqrestore(&ehci->lock, flags);
1194 if (ret) {
1195 pr_err("RESET in tight loop failed\n");
1196 dbg_log_event(NULL, "RESET: tight failed", 0);
1197 goto fail;
1198 }
1199
1200done:
1201 dbg_log_event(NULL, "RESET: done", retries);
1202 pr_debug("reset completed\n");
1203fail:
1204 mehci->bus_reset = 0;
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301205 if (next_latency)
1206 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301207}
1208
Hemant Kumar45d211b2012-05-31 17:58:43 -07001209static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
1210{
Pavankumar Kondetia723f742012-09-14 14:02:36 +05301211 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1212
1213 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
1214 dbg_log_event(NULL, "RH suspend attempt failed", 0);
1215 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
1216 __func__);
1217 return -EAGAIN;
1218 }
1219
Hemant Kumar45d211b2012-05-31 17:58:43 -07001220 dbg_log_event(NULL, "Suspend RH", 0);
1221 return ehci_bus_suspend(hcd);
1222}
1223
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001224#define RESUME_RETRY_LIMIT 3
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301225#define RESUME_SIGNAL_TIME_USEC (21 * 1000)
1226#define RESUME_SIGNAL_TIME_SOF_USEC (23 * 1000)
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001227static int msm_hsic_resume_thread(void *data)
1228{
1229 struct msm_hsic_hcd *mehci = data;
1230 struct usb_hcd *hcd = hsic_to_hcd(mehci);
1231 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1232 u32 temp;
1233 unsigned long resume_needed = 0;
1234 int retry_cnt = 0;
1235 int tight_resume = 0;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301236 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301237 s32 next_latency = 0;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001238
1239 dbg_log_event(NULL, "Resume RH", 0);
1240
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301241 if (pdata && pdata->swfi_latency) {
1242 next_latency = pdata->swfi_latency + 1;
1243 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
1244 if (pdata->standalone_latency)
1245 next_latency = pdata->standalone_latency + 1;
1246 else
1247 next_latency = PM_QOS_DEFAULT_VALUE;
1248 }
1249
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001250 /* keep delay between bus states */
1251 if (time_before(jiffies, ehci->next_statechange))
1252 usleep_range(5000, 5000);
1253
1254 spin_lock_irq(&ehci->lock);
1255 if (!HCD_HW_ACCESSIBLE(hcd)) {
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001256 mehci->resume_status = -ESHUTDOWN;
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301257 goto exit;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001258 }
1259
1260 if (unlikely(ehci->debug)) {
1261 if (!dbgp_reset_prep())
1262 ehci->debug = NULL;
1263 else
1264 dbgp_external_startup();
1265 }
1266
1267 /* at least some APM implementations will try to deliver
1268 * IRQs right away, so delay them until we're ready.
1269 */
1270 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
1271
1272 /* re-init operational registers */
1273 ehci_writel(ehci, 0, &ehci->regs->segment);
1274 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
1275 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
1276
1277 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
1278 if (ehci->resume_sof_bug)
1279 ehci->command &= ~CMD_RUN;
1280
1281 /* restore CMD_RUN, framelist size, and irq threshold */
1282 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1283
1284 /* manually resume the ports we suspended during bus_suspend() */
1285resume_again:
1286 if (retry_cnt >= RESUME_RETRY_LIMIT) {
1287 pr_info("retry count(%d) reached max, resume in tight loop\n",
1288 retry_cnt);
1289 tight_resume = 1;
1290 }
1291
1292
1293 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1294 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
1295 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
1296 temp |= PORT_RESUME;
1297 set_bit(0, &resume_needed);
1298 }
1299 dbg_log_event(NULL, "FPR: Set", temp);
1300 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1301
1302 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1303 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1304 * controller in MSM clears FPR bit after driving the resume signal for
1305 * 20ms. Workaround is to stop SOFs before driving resume and then start
1306 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1307 * completion otherwise peripheral may enter undefined state. As
1308 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1309 * to time the resume sequence. If driver exceeds allowable time SOFs,
1310 * repeat the resume process.
1311 */
1312 if (ehci->resume_sof_bug && resume_needed) {
1313 if (!tight_resume) {
1314 mehci->resume_again = 0;
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301315 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_USEC - 1),
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001316 &mehci->timer->gptimer0_ld);
1317 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1318 &mehci->timer->gptimer0_ctrl);
1319 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1320 &ehci->regs->intr_enable);
1321
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301322 ehci_writel(ehci, GPT_LD(
1323 RESUME_SIGNAL_TIME_SOF_USEC - 1),
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001324 &mehci->timer->gptimer1_ld);
1325 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1326 &mehci->timer->gptimer1_ctrl);
1327
1328 spin_unlock_irq(&ehci->lock);
1329 wait_for_completion(&mehci->gpt0_completion);
1330 spin_lock_irq(&ehci->lock);
1331 } else {
1332 dbg_log_event(NULL, "FPR: Tightloop", 0);
1333 /* do the resume in a tight loop */
1334 handshake(ehci, &ehci->regs->port_status[0],
1335 PORT_RESUME, 0, 22 * 1000);
1336 ehci_writel(ehci, ehci_readl(ehci,
1337 &ehci->regs->command) | CMD_RUN,
1338 &ehci->regs->command);
1339 }
1340
1341 if (mehci->resume_again) {
1342 int temp;
1343
1344 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1345 pr_info("FPR: retry count: %d\n", retry_cnt);
1346 spin_unlock_irq(&ehci->lock);
1347 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1348 temp &= ~PORT_RWC_BITS;
1349 temp |= PORT_SUSPEND;
1350 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1351 /* Keep the bus idle for 5ms so that peripheral
1352 * can detect and initiate suspend
1353 */
1354 usleep_range(5000, 5000);
1355 dbg_log_event(NULL,
1356 "FPR: RResume",
1357 ehci_readl(ehci, &ehci->regs->port_status[0]));
1358 spin_lock_irq(&ehci->lock);
1359 mehci->resume_again = 0;
1360 retry_cnt++;
1361 goto resume_again;
1362 }
1363 }
1364
1365 dbg_log_event(NULL, "FPR: RT-Done", 0);
1366 mehci->resume_status = 1;
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301367exit:
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001368 spin_unlock_irq(&ehci->lock);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001369 complete(&mehci->rt_completion);
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301370 if (next_latency)
1371 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001372
1373 return 0;
1374}
1375
Hemant Kumar45d211b2012-05-31 17:58:43 -07001376static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1377{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001378 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1379 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1380 u32 temp;
1381 struct task_struct *resume_thread = NULL;
Vamsi Krishnabef91832013-03-11 14:10:20 -07001382 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1383
1384 if (pdata->resume_gpio)
1385 gpio_direction_output(pdata->resume_gpio, 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001386
Manu Gautam3c598392013-03-22 16:59:10 +05301387 if (!mehci->ehci.resume_sof_bug) {
1388 ehci_bus_resume(hcd);
1389 } else {
1390 mehci->resume_status = 0;
1391 resume_thread = kthread_run(msm_hsic_resume_thread,
1392 mehci, "hsic_resume_thread");
1393 if (IS_ERR(resume_thread)) {
1394 pr_err("Error creating resume thread:%lu\n",
1395 PTR_ERR(resume_thread));
1396 return PTR_ERR(resume_thread);
1397 }
1398
1399 wait_for_completion(&mehci->rt_completion);
1400
1401 if (mehci->resume_status < 0)
1402 return mehci->resume_status;
1403
1404 dbg_log_event(NULL, "FPR: Wokeup", 0);
1405 spin_lock_irq(&ehci->lock);
1406 (void) ehci_readl(ehci, &ehci->regs->command);
1407
1408 temp = 0;
1409 if (ehci->async->qh_next.qh)
1410 temp |= CMD_ASE;
1411 if (ehci->periodic_sched)
1412 temp |= CMD_PSE;
1413 if (temp) {
1414 ehci->command |= temp;
1415 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1416 }
1417
1418 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1419 hcd->state = HC_STATE_RUNNING;
1420 ehci->rh_state = EHCI_RH_RUNNING;
1421 ehci->command |= CMD_RUN;
1422
1423 /* Now we can safely re-enable irqs */
1424 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1425
1426 spin_unlock_irq(&ehci->lock);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001427 }
1428
Vamsi Krishnabef91832013-03-11 14:10:20 -07001429 if (pdata->resume_gpio)
1430 gpio_direction_output(pdata->resume_gpio, 0);
1431
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001432 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001433}
1434
Jack Phamc0d41732012-09-28 17:45:38 -07001435#else
1436
1437#define ehci_hsic_bus_suspend NULL
1438#define ehci_hsic_bus_resume NULL
1439
1440#endif /* CONFIG_PM */
1441
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001442static void ehci_msm_set_autosuspend_delay(struct usb_device *dev)
1443{
1444 if (!dev->parent) /*for root hub no delay*/
1445 pm_runtime_set_autosuspend_delay(&dev->dev, 0);
1446 else
1447 pm_runtime_set_autosuspend_delay(&dev->dev, 200);
1448}
1449
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02001450static int ehci_msm_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
1451 gfp_t mem_flags)
1452{
1453 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1454 struct usb_host_bam_type *usb_host_bam =
1455 (struct usb_host_bam_type *)urb->priv_data;
1456
1457 if (usb_host_bam && mehci && mehci->enable_hbm)
1458 return hbm_urb_enqueue(hcd, urb, mem_flags);
1459 return ehci_urb_enqueue(hcd, urb, mem_flags);
1460}
1461
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301462static struct hc_driver msm_hsic_driver = {
1463 .description = hcd_name,
1464 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1465 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1466
1467 /*
1468 * generic hardware linkage
1469 */
1470 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001471 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301472
1473 .reset = ehci_hsic_reset,
1474 .start = ehci_run,
1475
1476 .stop = ehci_stop,
1477 .shutdown = ehci_shutdown,
1478
1479 /*
1480 * managing i/o requests and associated device resources
1481 */
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02001482 .urb_enqueue = ehci_msm_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301483 .urb_dequeue = ehci_urb_dequeue,
1484 .endpoint_disable = ehci_endpoint_disable,
1485 .endpoint_reset = ehci_endpoint_reset,
1486 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1487
1488 /*
1489 * scheduling support
1490 */
1491 .get_frame_number = ehci_get_frame,
1492
1493 /*
1494 * root hub support
1495 */
1496 .hub_status_data = ehci_hub_status_data,
1497 .hub_control = ehci_hub_control,
1498 .relinquish_port = ehci_relinquish_port,
1499 .port_handed_over = ehci_port_handed_over,
1500
1501 /*
1502 * PM support
1503 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001504 .bus_suspend = ehci_hsic_bus_suspend,
1505 .bus_resume = ehci_hsic_bus_resume,
1506
Hemant Kumar4d50a432012-08-15 09:06:35 -07001507 .log_urb = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001508 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001509
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001510 .set_autosuspend_delay = ehci_msm_set_autosuspend_delay,
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301511 .reset_sof_bug_handler = ehci_hsic_reset_sof_bug_handler,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301512};
1513
1514static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1515{
1516 int ret = 0;
1517
1518 if (!init)
1519 goto put_clocks;
1520
Lena Salman8c8ba382012-02-14 15:59:31 +02001521 /*core_clk is required for LINK protocol engine
1522 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001523 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1524 if (IS_ERR(mehci->core_clk)) {
1525 dev_err(mehci->dev, "failed to get core_clk\n");
1526 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301527 return ret;
1528 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301529
Ofir Cohen07944aa2012-12-23 13:41:57 +02001530 /* alt_core_clk is for LINK to be used during PHY RESET in
1531 * targets on which link does NOT use asynchronous reset methodology.
Lena Salman8c8ba382012-02-14 15:59:31 +02001532 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001533 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
Manu Gautam863b74132012-11-21 14:30:04 +05301534 if (IS_ERR(mehci->alt_core_clk))
1535 dev_dbg(mehci->dev, "failed to get alt_core_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301536
Lena Salman8c8ba382012-02-14 15:59:31 +02001537 /* phy_clk is required for HSIC PHY operation
1538 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001539 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1540 if (IS_ERR(mehci->phy_clk)) {
1541 dev_err(mehci->dev, "failed to get phy_clk\n");
1542 ret = PTR_ERR(mehci->phy_clk);
1543 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301544 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301545
1546 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001547 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301548 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001549 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301550 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001551 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301552 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301553
1554 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001555 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301556 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001557 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301558 ret = PTR_ERR(mehci->ahb_clk);
1559 goto put_cal_clk;
1560 }
1561
Ido Shayevitz5dfbb132013-04-18 13:22:07 +03001562 /*
1563 * Inactivity_clk is required for hsic bam inactivity timer.
1564 * This clock is not compulsory and is defined in clock lookup
1565 * only for targets that need to use the inactivity timer feature.
1566 */
1567 mehci->inactivity_clk = clk_get(mehci->dev, "inactivity_clk");
1568 if (IS_ERR(mehci->inactivity_clk))
1569 dev_dbg(mehci->dev, "failed to get inactivity_clk\n");
1570
Manu Gautam28b1bac2012-01-30 16:43:06 +05301571 clk_prepare_enable(mehci->core_clk);
1572 clk_prepare_enable(mehci->phy_clk);
1573 clk_prepare_enable(mehci->cal_clk);
1574 clk_prepare_enable(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +03001575 if (!IS_ERR(mehci->inactivity_clk))
1576 clk_prepare_enable(mehci->inactivity_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301577
1578 return 0;
1579
1580put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001581 if (!atomic_read(&mehci->in_lpm)) {
1582 clk_disable_unprepare(mehci->core_clk);
1583 clk_disable_unprepare(mehci->phy_clk);
1584 clk_disable_unprepare(mehci->cal_clk);
1585 clk_disable_unprepare(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +03001586 if (!IS_ERR(mehci->inactivity_clk))
1587 clk_disable_unprepare(mehci->inactivity_clk);
Jack Phamfd193eb2012-02-22 15:38:08 -08001588 }
Ido Shayevitz5dfbb132013-04-18 13:22:07 +03001589 if (!IS_ERR(mehci->inactivity_clk))
1590 clk_put(mehci->inactivity_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301591 clk_put(mehci->ahb_clk);
1592put_cal_clk:
1593 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001594put_phy_clk:
1595 clk_put(mehci->phy_clk);
1596put_alt_core_clk:
Manu Gautam863b74132012-11-21 14:30:04 +05301597 if (!IS_ERR(mehci->alt_core_clk))
1598 clk_put(mehci->alt_core_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001599 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301600
1601 return ret;
1602}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001603static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1604{
1605 struct msm_hsic_hcd *mehci = dev_id;
1606
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001607 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001608
1609 if (mehci)
1610 msm_hsic_config_gpios(mehci, 0);
1611
1612 return IRQ_HANDLED;
1613}
1614
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001615static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1616{
1617 struct msm_hsic_hcd *mehci = data;
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301618 int ret;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001619
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301620 if (irq == mehci->async_irq) {
1621 mehci->async_int_cnt++;
1622 dbg_log_event(NULL, "Remote Wakeup (ASYNC) IRQ",
1623 mehci->async_int_cnt);
1624 } else {
1625 mehci->wakeup_int_cnt++;
1626 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
1627 }
1628 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt %d cnt: %u, %u\n",
1629 __func__, irq, mehci->wakeup_int_cnt, mehci->async_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001630
Sudhir Sharma1673e302012-08-27 17:37:24 -07001631 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001632
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301633 if (mehci->wakeup_irq) {
1634 spin_lock(&mehci->wakeup_lock);
1635 if (mehci->wakeup_irq_enabled) {
1636 mehci->wakeup_irq_enabled = 0;
1637 disable_irq_wake(irq);
1638 disable_irq_nosync(irq);
1639 }
1640 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001641 }
1642
Sudhir Sharma1673e302012-08-27 17:37:24 -07001643 if (!atomic_read(&mehci->pm_usage_cnt)) {
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301644 ret = pm_runtime_get(mehci->dev);
1645 /*
1646 * HSIC runtime resume can race with us.
1647 * if we are active (ret == 1) or resuming
1648 * (ret == -EINPROGRESS), decrement the
1649 * PM usage counter before returning.
1650 */
1651 if ((ret == 1) || (ret == -EINPROGRESS))
1652 pm_runtime_put_noidle(mehci->dev);
1653 else
1654 atomic_set(&mehci->pm_usage_cnt, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001655 }
1656
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001657 return IRQ_HANDLED;
1658}
1659
Hemant Kumare6275972012-02-29 20:06:21 -08001660static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1661{
1662 if (debug_bus_voting_enabled)
1663 seq_printf(s, "enabled\n");
1664 else
1665 seq_printf(s, "disabled\n");
1666
1667 return 0;
1668}
1669
1670static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1671{
1672 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1673}
1674
1675static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1676 const char __user *ubuf, size_t count, loff_t *ppos)
1677{
1678 char buf[8];
1679 int ret;
1680 struct seq_file *s = file->private_data;
1681 struct msm_hsic_hcd *mehci = s->private;
1682
1683 memset(buf, 0x00, sizeof(buf));
1684
1685 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1686 return -EFAULT;
1687
1688 if (!strncmp(buf, "enable", 6)) {
1689 /* Do not vote here. Let hsic driver decide when to vote */
1690 debug_bus_voting_enabled = true;
1691 } else {
1692 debug_bus_voting_enabled = false;
1693 if (mehci->bus_perf_client) {
1694 ret = msm_bus_scale_client_update_request(
1695 mehci->bus_perf_client, 0);
1696 if (ret)
1697 dev_err(mehci->dev, "%s: Failed to devote "
1698 "for bus bw %d\n", __func__, ret);
1699 }
1700 }
1701
1702 return count;
1703}
1704
1705const struct file_operations ehci_hsic_msm_bus_fops = {
1706 .open = ehci_hsic_msm_bus_open,
1707 .read = seq_read,
1708 .write = ehci_hsic_msm_bus_write,
1709 .llseek = seq_lseek,
1710 .release = single_release,
1711};
1712
Hemant Kumar6fd65032012-05-23 13:02:24 -07001713static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1714{
1715 struct msm_hsic_hcd *mehci = s->private;
1716
1717 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1718
1719 return 0;
1720}
1721
1722static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1723{
1724 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1725}
1726
1727const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1728 .open = ehci_hsic_msm_wakeup_cnt_open,
1729 .read = seq_read,
1730 .llseek = seq_lseek,
1731 .release = single_release,
1732};
1733
Hemant Kumar45d211b2012-05-31 17:58:43 -07001734static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1735{
1736 unsigned long flags;
1737 unsigned i;
1738
1739 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1740
1741 i = dbg_hsic_data.idx;
1742 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1743 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1744 continue;
1745 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1746 }
1747
1748 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1749
1750 return 0;
1751}
1752
1753static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1754{
1755 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1756}
1757
1758const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1759 .open = ehci_hsic_msm_data_events_open,
1760 .read = seq_read,
1761 .llseek = seq_lseek,
1762 .release = single_release,
1763};
1764
1765static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1766{
1767 unsigned long flags;
1768 unsigned i;
1769
1770 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1771
1772 i = dbg_hsic_ctrl.idx;
1773 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1774 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1775 continue;
1776 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1777 }
1778
1779 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1780
1781 return 0;
1782}
1783
1784static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1785{
1786 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1787}
1788
1789const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1790 .open = ehci_hsic_msm_ctrl_events_open,
1791 .read = seq_read,
1792 .llseek = seq_lseek,
1793 .release = single_release,
1794};
1795
Hemant Kumare6275972012-02-29 20:06:21 -08001796static struct dentry *ehci_hsic_msm_dbg_root;
1797static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1798{
1799 struct dentry *ehci_hsic_msm_dentry;
1800
1801 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1802
1803 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1804 return -ENODEV;
1805
1806 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1807 S_IRUGO | S_IWUSR,
1808 ehci_hsic_msm_dbg_root, mehci,
1809 &ehci_hsic_msm_bus_fops);
1810
1811 if (!ehci_hsic_msm_dentry) {
1812 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1813 return -ENODEV;
1814 }
1815
Hemant Kumar6fd65032012-05-23 13:02:24 -07001816 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1817 S_IRUGO,
1818 ehci_hsic_msm_dbg_root, mehci,
1819 &ehci_hsic_msm_wakeup_cnt_fops);
1820
1821 if (!ehci_hsic_msm_dentry) {
1822 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1823 return -ENODEV;
1824 }
1825
Hemant Kumar45d211b2012-05-31 17:58:43 -07001826 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1827 S_IRUGO,
1828 ehci_hsic_msm_dbg_root, mehci,
1829 &ehci_hsic_msm_dbg_ctrl_fops);
1830
1831 if (!ehci_hsic_msm_dentry) {
1832 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1833 return -ENODEV;
1834 }
1835
1836 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1837 S_IRUGO,
1838 ehci_hsic_msm_dbg_root, mehci,
1839 &ehci_hsic_msm_dbg_data_fops);
1840
1841 if (!ehci_hsic_msm_dentry) {
1842 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1843 return -ENODEV;
1844 }
1845
Hemant Kumare6275972012-02-29 20:06:21 -08001846 return 0;
1847}
1848
1849static void ehci_hsic_msm_debugfs_cleanup(void)
1850{
1851 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1852}
1853
Manu Gautam863b74132012-11-21 14:30:04 +05301854struct msm_hsic_host_platform_data *msm_hsic_dt_to_pdata(
1855 struct platform_device *pdev)
1856{
1857 struct device_node *node = pdev->dev.of_node;
1858 struct msm_hsic_host_platform_data *pdata;
Ido Shayevitzca5dc492013-01-09 14:49:59 +02001859 int res_gpio;
Manu Gautam863b74132012-11-21 14:30:04 +05301860
1861 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1862 if (!pdata) {
1863 dev_err(&pdev->dev, "unable to allocate platform data\n");
1864 return NULL;
1865 }
Manu Gautam863b74132012-11-21 14:30:04 +05301866
Ido Shayevitzca5dc492013-01-09 14:49:59 +02001867 res_gpio = of_get_named_gpio(node, "hsic,strobe-gpio", 0);
1868 if (res_gpio < 0)
1869 res_gpio = 0;
1870 pdata->strobe = res_gpio;
1871
1872 res_gpio = of_get_named_gpio(node, "hsic,data-gpio", 0);
1873 if (res_gpio < 0)
1874 res_gpio = 0;
1875 pdata->data = res_gpio;
Manu Gautam863b74132012-11-21 14:30:04 +05301876
Vamsi Krishnabef91832013-03-11 14:10:20 -07001877 res_gpio = of_get_named_gpio(node, "hsic,resume-gpio", 0);
1878 if (res_gpio < 0)
1879 res_gpio = 0;
1880 pdata->resume_gpio = res_gpio;
1881
Manu Gautam3c598392013-03-22 16:59:10 +05301882 pdata->phy_sof_workaround = of_property_read_bool(node,
1883 "qcom,phy-sof-workaround");
Manu Gautam863b74132012-11-21 14:30:04 +05301884 pdata->ignore_cal_pad_config = of_property_read_bool(node,
1885 "hsic,ignore-cal-pad-config");
1886 of_property_read_u32(node, "hsic,strobe-pad-offset",
1887 &pdata->strobe_pad_offset);
1888 of_property_read_u32(node, "hsic,data-pad-offset",
1889 &pdata->data_pad_offset);
Vamsi Krishnafaee5da2013-06-14 12:41:10 -07001890 of_property_read_u32(node, "hsic,log2-itc",
1891 &pdata->log2_irq_thresh);
1892 if (pdata->log2_irq_thresh > 6)
1893 pdata->log2_irq_thresh = 0;
Manu Gautam863b74132012-11-21 14:30:04 +05301894
Ido Shayevitz95c46882013-01-20 13:47:46 +02001895 pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
1896
Shimrit Malichi36a0c852013-03-10 11:39:10 +02001897 pdata->pool_64_bit_align = of_property_read_bool(node,
1898 "qcom,pool-64-bit-align");
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02001899 pdata->enable_hbm = of_property_read_bool(node,
1900 "qcom,enable-hbm");
Shimrit Malichi08f07342013-04-24 13:09:12 +03001901 pdata->disable_park_mode = (of_property_read_bool(node,
1902 "qcom,disable-park-mode"));
Ido Shayevitzaa165c52013-05-12 16:01:28 +02001903 pdata->consider_ipa_handshake = (of_property_read_bool(node,
1904 "hsic,consider-ipa-handshake"));
Amit Blay1dfbbcc2013-05-26 17:33:13 +03001905 pdata->ahb_async_bridge_bypass = of_property_read_bool(node,
1906 "qcom,ahb-async-bridge-bypass");
Vamsi Krishna4f66c2c2013-06-21 11:33:59 -07001907 pdata->disable_cerr = of_property_read_bool(node,
1908 "hsic,disable-cerr");
Shimrit Malichi36a0c852013-03-10 11:39:10 +02001909
Manu Gautam863b74132012-11-21 14:30:04 +05301910 return pdata;
1911}
1912
1913
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301914static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1915{
1916 struct usb_hcd *hcd;
1917 struct resource *res;
1918 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301919 struct msm_hsic_host_platform_data *pdata;
Manu Gautam16562792013-03-13 07:04:11 +05301920 unsigned long wakeup_irq_flags = 0;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301921 int ret;
1922
1923 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1924
Manu Gautam863b74132012-11-21 14:30:04 +05301925 if (pdev->dev.of_node) {
1926 dev_dbg(&pdev->dev, "device tree enabled\n");
1927 pdev->dev.platform_data = msm_hsic_dt_to_pdata(pdev);
1928 dev_set_name(&pdev->dev, ehci_msm_hsic_driver.driver.name);
Manu Gautam16562792013-03-13 07:04:11 +05301929 } else {
1930 /* explicitly pass wakeup_irq flag for !DT */
1931 wakeup_irq_flags = IRQF_TRIGGER_HIGH;
Manu Gautam863b74132012-11-21 14:30:04 +05301932 }
1933 if (!pdev->dev.platform_data)
1934 dev_dbg(&pdev->dev, "No platform data given\n");
1935
Ofir Cohen4cc55372012-11-20 11:17:24 +02001936 if (!pdev->dev.dma_mask)
1937 pdev->dev.dma_mask = &ehci_msm_hsic_dma_mask;
1938 if (!pdev->dev.coherent_dma_mask)
1939 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
1940
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301941 /* After parent device's probe is executed, it will be put in suspend
1942 * mode. When child device's probe is called, driver core is not
1943 * resuming parent device due to which parent will be in suspend even
1944 * though child is active. Hence resume the parent device explicitly.
1945 */
1946 if (pdev->dev.parent)
1947 pm_runtime_get_sync(pdev->dev.parent);
1948
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301949 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1950 dev_name(&pdev->dev));
1951 if (!hcd) {
1952 dev_err(&pdev->dev, "Unable to create HCD\n");
1953 return -ENOMEM;
1954 }
1955
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301956 hcd_to_bus(hcd)->skip_resume = true;
1957
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301958 hcd->irq = platform_get_irq(pdev, 0);
1959 if (hcd->irq < 0) {
1960 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1961 ret = hcd->irq;
1962 goto put_hcd;
1963 }
1964
1965 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1966 if (!res) {
1967 dev_err(&pdev->dev, "Unable to get memory resource\n");
1968 ret = -ENODEV;
1969 goto put_hcd;
1970 }
1971
1972 hcd->rsrc_start = res->start;
1973 hcd->rsrc_len = resource_size(res);
1974 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1975 if (!hcd->regs) {
1976 dev_err(&pdev->dev, "ioremap failed\n");
1977 ret = -ENOMEM;
1978 goto put_hcd;
1979 }
1980
1981 mehci = hcd_to_hsic(hcd);
1982 mehci->dev = &pdev->dev;
Hemant Kumar30d361c2012-08-20 14:44:40 -07001983 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301984
Hemant Kumard343c012012-09-06 19:57:14 -07001985 spin_lock_init(&mehci->wakeup_lock);
1986
Manu Gautam3c598392013-03-22 16:59:10 +05301987 if (pdata->phy_sof_workaround) {
1988 mehci->ehci.susp_sof_bug = 1;
1989 mehci->ehci.reset_sof_bug = 1;
1990 mehci->ehci.resume_sof_bug = 1;
1991 }
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001992
Shimrit Malichi36a0c852013-03-10 11:39:10 +02001993 mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02001994 mehci->enable_hbm = pdata->enable_hbm;
Hemant Kumare4040492012-06-21 17:35:42 -07001995
Vamsi Krishna4f66c2c2013-06-21 11:33:59 -07001996 if (pdata) {
Hemant Kumar30d361c2012-08-20 14:44:40 -07001997 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Vamsi Krishna4f66c2c2013-06-21 11:33:59 -07001998 mehci->ehci.disable_cerr = pdata->disable_cerr;
1999 }
Hemant Kumar933e0402012-05-22 11:11:40 -07002000
Ofir Cohen4cc55372012-11-20 11:17:24 +02002001 ret = msm_hsic_init_gdsc(mehci, 1);
2002 if (ret) {
2003 dev_err(&pdev->dev, "unable to initialize GDSC\n");
2004 ret = -ENODEV;
2005 goto put_hcd;
2006 }
2007
Vamsi Krishna34f01582011-12-14 19:54:42 -08002008 res = platform_get_resource_byname(pdev,
2009 IORESOURCE_IRQ,
2010 "peripheral_status_irq");
2011 if (res)
2012 mehci->peripheral_status_irq = res->start;
2013
Jack Pham0cc75c42012-10-10 02:03:50 +02002014 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "wakeup");
Hemant Kumar6fd65032012-05-23 13:02:24 -07002015 if (res) {
Jack Pham0cc75c42012-10-10 02:03:50 +02002016 mehci->wakeup_irq = res->start;
Hemant Kumar6fd65032012-05-23 13:02:24 -07002017 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
2018 }
2019
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302020 ret = msm_hsic_init_clocks(mehci, 1);
2021 if (ret) {
2022 dev_err(&pdev->dev, "unable to initialize clocks\n");
2023 ret = -ENODEV;
2024 goto unmap;
2025 }
2026
2027 ret = msm_hsic_init_vddcx(mehci, 1);
2028 if (ret) {
2029 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
2030 ret = -ENODEV;
2031 goto deinit_clocks;
2032 }
2033
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07002034 init_completion(&mehci->rt_completion);
2035 init_completion(&mehci->gpt0_completion);
Ofir Cohen5dddb152012-11-14 11:18:50 +02002036
2037 msm_hsic_phy_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302038
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002039 ehci_wq = create_singlethread_workqueue("ehci_wq");
2040 if (!ehci_wq) {
2041 dev_err(&pdev->dev, "unable to create workqueue\n");
2042 ret = -ENOMEM;
2043 goto deinit_vddcx;
2044 }
2045
2046 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
2047
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302048 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
2049 if (ret) {
2050 dev_err(&pdev->dev, "unable to register HCD\n");
Ofir Cohen5dddb152012-11-14 11:18:50 +02002051 goto destroy_wq;
2052 }
2053
2054 ret = msm_hsic_start(mehci);
2055 if (ret) {
2056 dev_err(&pdev->dev, "unable to initialize PHY\n");
2057 goto destroy_wq;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302058 }
2059
2060 device_init_wakeup(&pdev->dev, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07002061 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
2062 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08002063
2064 if (mehci->peripheral_status_irq) {
2065 ret = request_threaded_irq(mehci->peripheral_status_irq,
2066 NULL, hsic_peripheral_status_change,
2067 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
2068 | IRQF_SHARED,
2069 "hsic_peripheral_status", mehci);
2070 if (ret)
2071 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
2072 __func__, mehci->peripheral_status_irq, ret);
2073 }
2074
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002075 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07002076 if (mehci->wakeup_irq) {
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07002077 /* In case if wakeup gpio is pulled high at this point
2078 * remote wakeup interrupt fires right after request_irq.
2079 * Remote wake up interrupt only needs to be enabled when
2080 * HSIC bus goes to suspend.
2081 */
2082 irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002083 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Manu Gautam16562792013-03-13 07:04:11 +05302084 wakeup_irq_flags,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002085 "msm_hsic_wakeup", mehci);
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07002086 if (ret) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002087 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
2088 mehci->wakeup_irq, ret);
2089 mehci->wakeup_irq = 0;
2090 }
2091 }
2092
Manu Gautam3fb60ca2013-02-13 18:33:33 +05302093 mehci->async_irq = platform_get_irq_byname(pdev, "async_irq");
2094 if (mehci->async_irq < 0) {
2095 dev_dbg(&pdev->dev, "platform_get_irq for async_int failed\n");
2096 mehci->async_irq = 0;
2097 } else {
2098 ret = request_irq(mehci->async_irq, msm_hsic_wakeup_irq,
2099 IRQF_TRIGGER_RISING, "msm_hsic_async", mehci);
2100 if (ret) {
2101 dev_err(&pdev->dev, "request irq failed (ASYNC INT)\n");
2102 mehci->async_irq = 0;
Manu Gautam16562792013-03-13 07:04:11 +05302103 } else if (!mehci->wakeup_irq) {
2104 /* Async IRQ is used only in absence of dedicated irq */
Manu Gautam3fb60ca2013-02-13 18:33:33 +05302105 enable_irq_wake(mehci->async_irq);
2106 }
2107 }
2108
Hemant Kumare6275972012-02-29 20:06:21 -08002109 ret = ehci_hsic_msm_debugfs_init(mehci);
2110 if (ret)
2111 dev_dbg(&pdev->dev, "mode debugfs file is"
2112 "not available\n");
2113
2114 if (pdata && pdata->bus_scale_table) {
2115 mehci->bus_perf_client =
2116 msm_bus_scale_register_client(pdata->bus_scale_table);
2117 /* Configure BUS performance parameters for MAX bandwidth */
2118 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002119 mehci->bus_vote = true;
2120 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08002121 } else {
2122 dev_err(&pdev->dev, "%s: Failed to register BUS "
2123 "scaling client!!\n", __func__);
2124 }
2125 }
2126
Hemant Kumar105d07f2012-07-02 15:33:07 -07002127 __mehci = mehci;
2128
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07002129 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05302130 pm_qos_add_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07002131 PM_QOS_CPU_DMA_LATENCY, pdata->standalone_latency + 1);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05302132
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302133 /*
2134 * This pdev->dev is assigned parent of root-hub by USB core,
2135 * hence, runtime framework automatically calls this driver's
2136 * runtime APIs based on root-hub's state.
2137 */
2138 pm_runtime_set_active(&pdev->dev);
2139 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05302140 /* Decrement the parent device's counter after probe.
2141 * As child is active, parent will not be put into
2142 * suspend mode.
2143 */
2144 if (pdev->dev.parent)
2145 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302146
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02002147 if (mehci->enable_hbm)
Shimrit Malichi08f07342013-04-24 13:09:12 +03002148 hbm_init(hcd, pdata->disable_park_mode);
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02002149
Jack Pham06306d52013-06-06 15:28:13 -07002150 if (pdata && pdata->consider_ipa_handshake)
2151 msm_bam_set_hsic_host_dev(&pdev->dev);
Ido Shayevitzaa165c52013-05-12 16:01:28 +02002152
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302153 return 0;
2154
Ofir Cohen5dddb152012-11-14 11:18:50 +02002155destroy_wq:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002156 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302157deinit_vddcx:
2158 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02002159 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302160deinit_clocks:
2161 msm_hsic_init_clocks(mehci, 0);
2162unmap:
2163 iounmap(hcd->regs);
2164put_hcd:
2165 usb_put_hcd(hcd);
2166
2167 return ret;
2168}
2169
2170static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
2171{
2172 struct usb_hcd *hcd = platform_get_drvdata(pdev);
2173 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05302174 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
2175
Jack Pham06306d52013-06-06 15:28:13 -07002176 if (pdata && pdata->consider_ipa_handshake)
2177 msm_bam_set_hsic_host_dev(NULL);
Ido Shayevitzaa165c52013-05-12 16:01:28 +02002178
Ido Shayevitz65943492013-02-20 18:55:59 +02002179 /* If the device was removed no need to call pm_runtime_disable */
2180 if (pdev->dev.power.power_state.event != PM_EVENT_INVALID)
2181 pm_runtime_disable(&pdev->dev);
2182
2183 pm_runtime_set_suspended(&pdev->dev);
2184
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02002185 if (mehci->enable_hbm)
2186 hbm_uninit();
2187
Pavankumar Kondeti21a840e2013-02-12 21:43:56 +05302188 /* Remove the HCD prior to releasing our resources. */
2189 usb_remove_hcd(hcd);
2190
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07002191 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05302192 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302193
Vamsi Krishna34f01582011-12-14 19:54:42 -08002194 if (mehci->peripheral_status_irq)
2195 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07002196
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002197 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07002198 if (mehci->wakeup_irq_enabled)
2199 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002200 free_irq(mehci->wakeup_irq, mehci);
2201 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08002202
Manu Gautam3fb60ca2013-02-13 18:33:33 +05302203 if (mehci->async_irq) {
Manu Gautam1a1a9c62013-03-19 17:37:11 +05302204 /* Async IRQ is used only in absence of dedicated wakeup irq */
2205 if (!mehci->wakeup_irq)
2206 disable_irq_wake(mehci->async_irq);
Manu Gautam3fb60ca2013-02-13 18:33:33 +05302207 free_irq(mehci->async_irq, mehci);
2208 }
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002209 /*
2210 * If the update request is called after unregister, the request will
2211 * fail. Results are undefined if unregister is called in the middle of
2212 * update request.
2213 */
2214 mehci->bus_vote = false;
2215 cancel_work_sync(&mehci->bus_vote_w);
2216
Hemant Kumare6275972012-02-29 20:06:21 -08002217 if (mehci->bus_perf_client)
2218 msm_bus_scale_unregister_client(mehci->bus_perf_client);
2219
2220 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302221 device_init_wakeup(&pdev->dev, 0);
Ido Shayevitze50d9142013-02-17 20:43:26 +02002222
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002223 destroy_workqueue(ehci_wq);
2224
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05302225 msm_hsic_config_gpios(mehci, 0);
Vamsi Krishnabef91832013-03-11 14:10:20 -07002226
2227 if (pdata && pdata->resume_gpio)
2228 gpio_free(pdata->resume_gpio);
2229
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302230 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02002231 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302232
2233 msm_hsic_init_clocks(mehci, 0);
Sudhir Sharma1673e302012-08-27 17:37:24 -07002234 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302235 iounmap(hcd->regs);
2236 usb_put_hcd(hcd);
2237
2238 return 0;
2239}
2240
2241#ifdef CONFIG_PM_SLEEP
2242static int msm_hsic_pm_suspend(struct device *dev)
2243{
2244 struct usb_hcd *hcd = dev_get_drvdata(dev);
2245 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2246
2247 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
2248
Hemant Kumar45d211b2012-05-31 17:58:43 -07002249 dbg_log_event(NULL, "PM Suspend", 0);
2250
Pavankumar Kondeti1081f3e2013-04-25 13:51:24 +05302251 if (!atomic_read(&mehci->in_lpm)) {
2252 dev_info(dev, "abort suspend\n");
2253 dbg_log_event(NULL, "PM Suspend abort", 0);
2254 return -EBUSY;
2255 }
2256
Manu Gautam16562792013-03-13 07:04:11 +05302257 if (device_may_wakeup(dev) && !mehci->async_irq)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302258 enable_irq_wake(hcd->irq);
2259
Pavankumar Kondeti1081f3e2013-04-25 13:51:24 +05302260 return 0;
Jack Phamfe441ea2012-03-23 17:03:15 -07002261}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302262
Jack Pham16b06f82012-08-14 20:03:59 -07002263static int msm_hsic_pm_suspend_noirq(struct device *dev)
2264{
2265 struct usb_hcd *hcd = dev_get_drvdata(dev);
2266 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2267
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05302268 if (atomic_read(&mehci->async_int)) {
Jack Pham16b06f82012-08-14 20:03:59 -07002269 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
2270 return -EBUSY;
2271 }
2272
2273 return 0;
2274}
2275
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302276static int msm_hsic_pm_resume(struct device *dev)
2277{
2278 int ret;
2279 struct usb_hcd *hcd = dev_get_drvdata(dev);
2280 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2281
Jack Pham16b06f82012-08-14 20:03:59 -07002282 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002283 dbg_log_event(NULL, "PM Resume", 0);
2284
Manu Gautam16562792013-03-13 07:04:11 +05302285 if (device_may_wakeup(dev) && !mehci->async_irq)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302286 disable_irq_wake(hcd->irq);
2287
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05302288 /*
2289 * Keep HSIC in Low Power Mode if system is resumed
2290 * by any other wakeup source. HSIC is resumed later
2291 * when remote wakeup is received or interface driver
2292 * start I/O.
2293 */
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05302294 if (!atomic_read(&mehci->pm_usage_cnt) &&
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05302295 !atomic_read(&mehci->async_int) &&
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05302296 pm_runtime_suspended(dev))
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05302297 return 0;
2298
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302299 ret = msm_hsic_resume(mehci);
2300 if (ret)
2301 return ret;
2302
2303 /* Bring the device to full powered state upon system resume */
2304 pm_runtime_disable(dev);
2305 pm_runtime_set_active(dev);
2306 pm_runtime_enable(dev);
2307
2308 return 0;
2309}
2310#endif
2311
2312#ifdef CONFIG_PM_RUNTIME
2313static int msm_hsic_runtime_idle(struct device *dev)
2314{
2315 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302316 return 0;
2317}
2318
2319static int msm_hsic_runtime_suspend(struct device *dev)
2320{
2321 struct usb_hcd *hcd = dev_get_drvdata(dev);
2322 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2323
2324 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002325
2326 dbg_log_event(NULL, "Run Time PM Suspend", 0);
2327
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302328 return msm_hsic_suspend(mehci);
2329}
2330
2331static int msm_hsic_runtime_resume(struct device *dev)
2332{
2333 struct usb_hcd *hcd = dev_get_drvdata(dev);
2334 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2335
2336 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002337
2338 dbg_log_event(NULL, "Run Time PM Resume", 0);
2339
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302340 return msm_hsic_resume(mehci);
2341}
2342#endif
2343
2344#ifdef CONFIG_PM
2345static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
2346 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07002347 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302348 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
2349 msm_hsic_runtime_idle)
2350};
2351#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02002352static const struct of_device_id hsic_host_dt_match[] = {
2353 { .compatible = "qcom,hsic-host",
2354 },
2355 {}
2356};
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302357static struct platform_driver ehci_msm_hsic_driver = {
2358 .probe = ehci_hsic_msm_probe,
2359 .remove = __devexit_p(ehci_hsic_msm_remove),
2360 .driver = {
2361 .name = "msm_hsic_host",
2362#ifdef CONFIG_PM
2363 .pm = &msm_hsic_dev_pm_ops,
2364#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02002365 .of_match_table = hsic_host_dt_match,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302366 },
2367};