blob: bf887a726910bce452dd4eac6257e67b2eb820e0 [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>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053052
53#define MSM_USB_BASE (hcd->regs)
Hemant Kumar105d07f2012-07-02 15:33:07 -070054#define USB_REG_START_OFFSET 0x90
55#define USB_REG_END_OFFSET 0x250
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053056
Hemant Kumar2309eaa2012-08-14 16:46:42 -070057static struct workqueue_struct *ehci_wq;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070058struct ehci_timer {
59#define GPT_LD(p) ((p) & 0x00FFFFFF)
60 u32 gptimer0_ld;
61#define GPT_RUN BIT(31)
62#define GPT_RESET BIT(30)
63#define GPT_MODE BIT(24)
64#define GPT_CNT(p) ((p) & 0x00FFFFFF)
65 u32 gptimer0_ctrl;
66
67 u32 gptimer1_ld;
68 u32 gptimer1_ctrl;
69};
Hemant Kumar2309eaa2012-08-14 16:46:42 -070070
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053071struct msm_hsic_hcd {
72 struct ehci_hcd ehci;
Hemant Kumard343c012012-09-06 19:57:14 -070073 spinlock_t wakeup_lock;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053074 struct device *dev;
75 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080076 struct clk *core_clk;
77 struct clk *alt_core_clk;
78 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053079 struct clk *cal_clk;
80 struct regulator *hsic_vddcx;
Ofir Cohen4cc55372012-11-20 11:17:24 +020081 struct regulator *hsic_gdsc;
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +053082 atomic_t async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053083 atomic_t in_lpm;
Sudhir Sharma1673e302012-08-27 17:37:24 -070084 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080085 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080086 int wakeup_irq;
Jack Phamfe441ea2012-03-23 17:03:15 -070087 bool wakeup_irq_enabled;
Manu Gautam3fb60ca2013-02-13 18:33:33 +053088 int async_irq;
89 uint32_t async_int_cnt;
Sudhir Sharma1673e302012-08-27 17:37:24 -070090 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080091 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070092 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030093 enum usb_vdd_type vdd_type;
Hemant Kumar2309eaa2012-08-14 16:46:42 -070094
95 struct work_struct bus_vote_w;
96 bool bus_vote;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070097
98 /* gp timer */
99 struct ehci_timer __iomem *timer;
100 struct completion gpt0_completion;
101 struct completion rt_completion;
102 int resume_status;
103 int resume_again;
Pavankumar Kondeti23720492013-01-29 14:41:58 +0530104 int bus_reset;
105 int reset_again;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +0530106
107 struct pm_qos_request pm_qos_req_dma;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530108};
109
Hemant Kumar105d07f2012-07-02 15:33:07 -0700110struct msm_hsic_hcd *__mehci;
111
Hemant Kumare6275972012-02-29 20:06:21 -0800112static bool debug_bus_voting_enabled = true;
Ofir Cohen4cc55372012-11-20 11:17:24 +0200113static u64 ehci_msm_hsic_dma_mask = DMA_BIT_MASK(32);
114
Manu Gautam863b74132012-11-21 14:30:04 +0530115static struct platform_driver ehci_msm_hsic_driver;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700116
Hemant Kumar4d50a432012-08-15 09:06:35 -0700117static unsigned int enable_payload_log = 1;
118module_param(enable_payload_log, uint, S_IRUGO | S_IWUSR);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700119static unsigned int enable_dbg_log = 1;
120module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
121/*by default log ep0 and efs sync ep*/
122static unsigned int ep_addr_rxdbg_mask = 9;
123module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
124static unsigned int ep_addr_txdbg_mask = 9;
125module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
126
127/* Maximum debug message length */
Hemant Kumar4d50a432012-08-15 09:06:35 -0700128#define DBG_MSG_LEN 128UL
Hemant Kumar45d211b2012-05-31 17:58:43 -0700129
130/* Maximum number of messages */
131#define DBG_MAX_MSG 256UL
132
133#define TIME_BUF_LEN 20
Hemant Kumar4d50a432012-08-15 09:06:35 -0700134#define HEX_DUMP_LEN 72
Hemant Kumar45d211b2012-05-31 17:58:43 -0700135
136enum event_type {
137 EVENT_UNDEF = -1,
138 URB_SUBMIT,
139 URB_COMPLETE,
140 EVENT_NONE,
141};
142
143#define EVENT_STR_LEN 5
144
Hemant Kumar45d211b2012-05-31 17:58:43 -0700145static enum event_type str_to_event(const char *name)
146{
147 if (!strncasecmp("S", name, EVENT_STR_LEN))
148 return URB_SUBMIT;
149 if (!strncasecmp("C", name, EVENT_STR_LEN))
150 return URB_COMPLETE;
151 if (!strncasecmp("", name, EVENT_STR_LEN))
152 return EVENT_NONE;
153
154 return EVENT_UNDEF;
155}
156
157/*log ep0 activity*/
158static struct {
159 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
160 unsigned idx; /* index */
161 rwlock_t lck; /* lock */
162} dbg_hsic_ctrl = {
163 .idx = 0,
164 .lck = __RW_LOCK_UNLOCKED(lck)
165};
166
167static struct {
168 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
169 unsigned idx; /* index */
170 rwlock_t lck; /* lock */
171} dbg_hsic_data = {
172 .idx = 0,
173 .lck = __RW_LOCK_UNLOCKED(lck)
174};
175
176/**
177 * dbg_inc: increments debug event index
178 * @idx: buffer index
179 */
180static void dbg_inc(unsigned *idx)
181{
182 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
183}
184
185/*get_timestamp - returns time of day in us */
186static char *get_timestamp(char *tbuf)
187{
188 unsigned long long t;
189 unsigned long nanosec_rem;
190
191 t = cpu_clock(smp_processor_id());
192 nanosec_rem = do_div(t, 1000000000)/1000;
193 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
194 nanosec_rem);
195 return tbuf;
196}
197
198static int allow_dbg_log(int ep_addr)
199{
200 int dir, num;
201
202 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
203 num = ep_addr & ~USB_DIR_IN;
204 num = 1 << num;
205
206 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
207 return 1;
208 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
209 return 1;
210
211 return 0;
212}
213
Hemant Kumar4d50a432012-08-15 09:06:35 -0700214static char *get_hex_data(char *dbuf, struct urb *urb, int event, int status)
215{
216 int ep_addr = urb->ep->desc.bEndpointAddress;
217 char *ubuf = urb->transfer_buffer;
218 size_t len = event ? \
219 urb->actual_length : urb->transfer_buffer_length;
220
221 if (status == -EINPROGRESS)
222 status = 0;
223
224 /*Only dump ep in completions and epout submissions*/
225 if (len && !status &&
226 (((ep_addr & USB_DIR_IN) && event) ||
227 (!(ep_addr & USB_DIR_IN) && !event))) {
228 if (len >= 32)
229 len = 32;
230 hex_dump_to_buffer(ubuf, len, 32, 4, dbuf, HEX_DUMP_LEN, 0);
231 } else {
232 dbuf = "";
233 }
234
235 return dbuf;
236}
237
Hemant Kumar45d211b2012-05-31 17:58:43 -0700238static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
239{
240 unsigned long flags;
241 int ep_addr;
242 char tbuf[TIME_BUF_LEN];
Hemant Kumar4d50a432012-08-15 09:06:35 -0700243 char dbuf[HEX_DUMP_LEN];
Hemant Kumar45d211b2012-05-31 17:58:43 -0700244
245 if (!enable_dbg_log)
246 return;
247
248 if (!urb) {
249 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
250 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700251 "%s: %s : %u", get_timestamp(tbuf), event, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700252 dbg_inc(&dbg_hsic_ctrl.idx);
253 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
254 return;
255 }
256
257 ep_addr = urb->ep->desc.bEndpointAddress;
258 if (!allow_dbg_log(ep_addr))
259 return;
260
261 if ((ep_addr & 0x0f) == 0x0) {
262 /*submit event*/
263 if (!str_to_event(event)) {
264 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
265 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
266 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
Hemant Kumar4d50a432012-08-15 09:06:35 -0700267 "%02x %02x %04x %04x %04x %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700268 get_timestamp(tbuf), event, urb,
269 (ep_addr & USB_DIR_IN) ? "in" : "out",
270 urb->setup_packet[0], urb->setup_packet[1],
271 (urb->setup_packet[3] << 8) |
272 urb->setup_packet[2],
273 (urb->setup_packet[5] << 8) |
274 urb->setup_packet[4],
275 (urb->setup_packet[7] << 8) |
276 urb->setup_packet[6],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700277 urb->transfer_buffer_length, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700278
279 dbg_inc(&dbg_hsic_ctrl.idx);
280 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
281 } else {
282 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
283 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700284 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700285 get_timestamp(tbuf), event, urb,
286 (ep_addr & USB_DIR_IN) ? "in" : "out",
287 urb->actual_length, extra);
288
289 dbg_inc(&dbg_hsic_ctrl.idx);
290 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
291 }
292 } else {
293 write_lock_irqsave(&dbg_hsic_data.lck, flags);
294 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700295 "%s: [%s : %p]:ep%d[%s] %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700296 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
297 (ep_addr & USB_DIR_IN) ? "in" : "out",
298 str_to_event(event) ? urb->actual_length :
Hemant Kumar4d50a432012-08-15 09:06:35 -0700299 urb->transfer_buffer_length, extra,
300 enable_payload_log ? get_hex_data(dbuf, urb,
301 str_to_event(event), extra) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700302
303 dbg_inc(&dbg_hsic_data.idx);
304 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
305 }
306}
307
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530308static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
309{
310 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
311}
312
313static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
314{
315 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
316}
317
Hemant Kumar105d07f2012-07-02 15:33:07 -0700318static void dump_hsic_regs(struct usb_hcd *hcd)
319{
320 int i;
321 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
322
323 if (atomic_read(&mehci->in_lpm))
324 return;
325
326 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
327 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
328 readl_relaxed(hcd->regs + i),
329 readl_relaxed(hcd->regs + i + 4),
330 readl_relaxed(hcd->regs + i + 8),
331 readl_relaxed(hcd->regs + i + 0xc));
332}
333
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530334#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
335
Amit Blayd6ea6102012-06-07 16:26:24 +0300336#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Hemant Kumar3b743cd2012-10-17 13:48:10 -0700337#define USB_PHY_VDD_DIG_VOL_MIN 945000 /* uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700338#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530339
Lena Salman8c8ba382012-02-14 15:59:31 +0200340#define HSIC_DBG1_REG 0x38
341
Amit Blayd6ea6102012-06-07 16:26:24 +0300342static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
343 { /* VDD_CX CORNER Voting */
344 [VDD_NONE] = RPM_VREG_CORNER_NONE,
345 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
346 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
347 },
348 { /* VDD_CX Voltage Voting */
349 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
350 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
351 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
352 },
353};
354
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530355static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
356{
357 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300358 int none_vol, min_vol, max_vol;
359
360 if (!mehci->hsic_vddcx) {
361 mehci->vdd_type = VDDCX_CORNER;
362 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
363 "hsic_vdd_dig");
364 if (IS_ERR(mehci->hsic_vddcx)) {
365 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
366 "HSIC_VDDCX");
367 if (IS_ERR(mehci->hsic_vddcx)) {
368 dev_err(mehci->dev, "unable to get hsic vddcx\n");
369 return PTR_ERR(mehci->hsic_vddcx);
370 }
371 mehci->vdd_type = VDDCX;
372 }
373 }
374
375 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
376 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
377 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530378
379 if (!init)
380 goto disable_reg;
381
Amit Blayd6ea6102012-06-07 16:26:24 +0300382 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530383 if (ret) {
384 dev_err(mehci->dev, "unable to set the voltage"
385 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530386 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530387 }
388
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530389 ret = regulator_enable(mehci->hsic_vddcx);
390 if (ret) {
391 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
392 goto reg_enable_err;
393 }
394
395 return 0;
396
397disable_reg:
398 regulator_disable(mehci->hsic_vddcx);
399reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300400 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
401
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530402 return ret;
403
404}
405
Ofir Cohen4cc55372012-11-20 11:17:24 +0200406/* Global Distributed Switch Controller (GDSC) init */
407static int msm_hsic_init_gdsc(struct msm_hsic_hcd *mehci, int init)
408{
409 int ret = 0;
410
411 if (IS_ERR(mehci->hsic_gdsc))
412 return 0;
413
414 if (!mehci->hsic_gdsc) {
415 mehci->hsic_gdsc = devm_regulator_get(mehci->dev,
416 "HSIC_GDSC");
417 if (IS_ERR(mehci->hsic_gdsc))
418 return 0;
419 }
420
421 if (init) {
422 ret = regulator_enable(mehci->hsic_gdsc);
423 if (ret) {
424 dev_err(mehci->dev, "unable to enable hsic gdsc\n");
425 return ret;
426 }
427 } else {
428 regulator_disable(mehci->hsic_gdsc);
429 }
430
431 return 0;
432
433}
434
Pavankumar Kondeti23720492013-01-29 14:41:58 +0530435static int __maybe_unused ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700436{
437 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700438 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700439
440 /* initiate read operation */
441 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
442 USB_ULPI_VIEWPORT);
443
444 /* wait for completion */
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700445 while (cnt < ULPI_IO_TIMEOUT_USEC) {
446 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
447 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700448 udelay(1);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700449 cnt++;
450 }
451
452 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
453 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
454 readl_relaxed(USB_ULPI_VIEWPORT));
455 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
456 readl_relaxed(USB_PORTSC),
457 readl_relaxed(USB_USBCMD),
458 readl_relaxed(USB_FRINDEX));
459
460 /*frame counter increments afte 125us*/
461 udelay(130);
462 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
463 readl_relaxed(USB_FRINDEX));
464 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700465 }
466
467 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
468}
469
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530470static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
471{
472 struct usb_hcd *hcd = hsic_to_hcd(mehci);
473 int cnt = 0;
474
475 /* initiate write operation */
476 writel_relaxed(ULPI_RUN | ULPI_WRITE |
477 ULPI_ADDR(reg) | ULPI_DATA(val),
478 USB_ULPI_VIEWPORT);
479
480 /* wait for completion */
481 while (cnt < ULPI_IO_TIMEOUT_USEC) {
482 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
483 break;
484 udelay(1);
485 cnt++;
486 }
487
488 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700489 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
490 readl_relaxed(USB_ULPI_VIEWPORT));
491 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
492 readl_relaxed(USB_PORTSC),
493 readl_relaxed(USB_USBCMD),
494 readl_relaxed(USB_FRINDEX));
495
496 /*frame counter increments afte 125us*/
497 udelay(130);
498 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
499 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530500 return -ETIMEDOUT;
501 }
502
503 return 0;
504}
505
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530506static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
507{
508 int rc = 0;
509 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800510 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530511
512 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800513
Lena Salman8c8ba382012-02-14 15:59:31 +0200514 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530515 return rc;
516
Vamsi Krishna34f01582011-12-14 19:54:42 -0800517 if (gpio_status == gpio_en)
518 return 0;
519
520 gpio_status = gpio_en;
521
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530522 if (!gpio_en)
523 goto free_gpio;
524
525 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
526 if (rc < 0) {
527 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
528 return rc;
529 }
530
531 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
532 if (rc < 0) {
533 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
534 goto free_strobe;
Hemant Kumar6fd65032012-05-23 13:02:24 -0700535 }
536
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530537 return 0;
538
539free_gpio:
540 gpio_free(pdata->data);
541free_strobe:
542 gpio_free(pdata->strobe);
543
544 return rc;
545}
546
Vamsi Krishna64b48612012-06-14 16:08:11 -0700547static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530548{
549 int ret;
550
Ofir Cohen07944aa2012-12-23 13:41:57 +0200551 /* alt_core_clk exists in targets that do not use asynchronous reset */
552 if (!IS_ERR(mehci->alt_core_clk)) {
553 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
554 if (ret) {
555 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
556 return;
557 }
558
559 /* Since a hw bug, turn off the clock before complete reset */
560 clk_disable(mehci->core_clk);
561
562 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
563 if (ret)
564 dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
565 ret);
566
567 usleep_range(10000, 12000);
568
569 clk_enable(mehci->core_clk);
570 } else {
571 /* Using asynchronous block reset to the hardware */
572 clk_disable_unprepare(mehci->core_clk);
573 clk_disable_unprepare(mehci->phy_clk);
574 clk_disable_unprepare(mehci->cal_clk);
575 clk_disable_unprepare(mehci->ahb_clk);
576
577 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
578 if (ret) {
579 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
580 return;
581 }
582 usleep_range(10000, 12000);
583
584 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
585 if (ret)
586 dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
587 ret);
588 /*
589 * Required delay between the deassertion and
590 * clock enablement.
591 */
592 ndelay(200);
593 clk_prepare_enable(mehci->core_clk);
594 clk_prepare_enable(mehci->phy_clk);
595 clk_prepare_enable(mehci->cal_clk);
596 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530597 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530598}
599
Vamsi Krishna64b48612012-06-14 16:08:11 -0700600#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
601#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530602#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
603#define HSIC_LV_MODE 0x04
604#define HSIC_PAD_CALIBRATION 0xA8
605#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530606#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
Ofir Cohen5dddb152012-11-14 11:18:50 +0200607
608static void msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530609{
610 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530611
Vamsi Krishna64b48612012-06-14 16:08:11 -0700612 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530613
Vamsi Krishna64b48612012-06-14 16:08:11 -0700614 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530615 writel_relaxed(0x80000000, USB_PORTSC);
Vamsi Krishna64b48612012-06-14 16:08:11 -0700616 mb();
Ofir Cohen5dddb152012-11-14 11:18:50 +0200617}
618
619static int msm_hsic_start(struct msm_hsic_hcd *mehci)
620{
621 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
622 int ret;
Manu Gautam863b74132012-11-21 14:30:04 +0530623 void __iomem *reg;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530624
Lena Salman8c8ba382012-02-14 15:59:31 +0200625 /* HSIC init sequence when HSIC signals (Strobe/Data) are
626 routed via GPIOs */
627 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530628
Manu Gautam863b74132012-11-21 14:30:04 +0530629 if (!pdata->ignore_cal_pad_config) {
630 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
631 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
632 mb();
633 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700634
Lena Salman8c8ba382012-02-14 15:59:31 +0200635 /*set periodic calibration interval to ~2.048sec in
636 HSIC_IO_CAL_REG */
637 ulpi_write(mehci, 0xFF, 0x33);
638
639 /* Enable periodic IO calibration in HSIC_CFG register */
640 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
641
Vamsi Krishna64b48612012-06-14 16:08:11 -0700642 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200643 ret = msm_hsic_config_gpios(mehci, 1);
644 if (ret) {
645 dev_err(mehci->dev, " gpio configuarion failed\n");
646 return ret;
647 }
Manu Gautam863b74132012-11-21 14:30:04 +0530648 if (pdata->strobe_pad_offset) {
649 /* Set CORE_CTL_EN in STROBE GPIO PAD_CTL register */
650 reg = MSM_TLMM_BASE + pdata->strobe_pad_offset;
651 writel_relaxed(readl_relaxed(reg) | 0x2000000, reg);
652 } else {
653 /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */
654 reg = HSIC_STROBE_GPIO_PAD_CTL;
655 writel_relaxed(HSIC_GPIO_PAD_VAL, reg);
656 }
657
658 if (pdata->data_pad_offset) {
659 /* Set CORE_CTL_EN in HSIC_DATA GPIO PAD_CTL register */
660 reg = MSM_TLMM_BASE + pdata->data_pad_offset;
661 writel_relaxed(readl_relaxed(reg) | 0x2000000, reg);
662 } else {
663 /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */
664 reg = HSIC_DATA_GPIO_PAD_CTL;
665 writel_relaxed(HSIC_GPIO_PAD_VAL, reg);
666 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700667
668 mb();
669
Lena Salman8c8ba382012-02-14 15:59:31 +0200670 /* Enable HSIC mode in HSIC_CFG register */
671 ulpi_write(mehci, 0x01, 0x31);
672 } else {
673 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
674 via dedicated I/O */
675
676 /* programmable length of connect signaling (33.2ns) */
677 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
678 if (ret) {
679 pr_err("%s: Unable to program length of connect "
680 "signaling\n", __func__);
681 }
682
683 /*set periodic calibration interval to ~2.048sec in
684 HSIC_IO_CAL_REG */
685 ulpi_write(mehci, 0xFF, 0x33);
686
687 /* Enable HSIC mode in HSIC_CFG register */
688 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530689 }
690
Hemant Kumar6fd65032012-05-23 13:02:24 -0700691 /*disable auto resume*/
692 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
693
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530694 return 0;
695}
696
697#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
698#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
699
700#ifdef CONFIG_PM_SLEEP
Ofir Cohen5dddb152012-11-14 11:18:50 +0200701static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
702{
703 /* reset HSIC phy */
704 msm_hsic_phy_reset(mehci);
705
706 /* HSIC init procedure (caliberation) */
707 return msm_hsic_start(mehci);
708}
709
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530710static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
711{
712 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530713 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530714 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300715 int none_vol, max_vol;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700716 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530717
718 if (atomic_read(&mehci->in_lpm)) {
719 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
720 return 0;
721 }
722
723 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700724
Sudhir Sharma1673e302012-08-27 17:37:24 -0700725 /* make sure we don't race against a remote wakeup */
726 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700727 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Sudhir Sharma1673e302012-08-27 17:37:24 -0700728 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700729 enable_irq(hcd->irq);
730 return -EBUSY;
731 }
732
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530733 /*
734 * PHY may take some time or even fail to enter into low power
735 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
736 * in failure case.
737 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700738 val = readl_relaxed(USB_PORTSC);
739 val &= ~PORT_RWC_BITS;
740 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530741 writel_relaxed(val, USB_PORTSC);
742 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
743 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
744 break;
745 udelay(1);
746 cnt++;
747 }
748
749 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
750 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530751 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530752 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530753 }
754
755 /*
756 * PHY has capability to generate interrupt asynchronously in low
757 * power mode (LPM). This interrupt is level triggered. So USB IRQ
758 * line must be disabled till async interrupt enable bit is cleared
759 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
Pavankumar Kondeti0c9f29c2013-01-28 21:37:59 +0530760 * block data communication from PHY. Enable asynchronous interrupt
761 * only when wakeup gpio IRQ is not present.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530762 */
Pavankumar Kondeti0c9f29c2013-01-28 21:37:59 +0530763 if (mehci->wakeup_irq)
764 writel_relaxed(readl_relaxed(USB_USBCMD) |
765 ULPI_STP_CTRL, USB_USBCMD);
766 else
767 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530768 ULPI_STP_CTRL, USB_USBCMD);
769
770 /*
771 * Ensure that hardware is put in low power mode before
772 * clocks are turned OFF and VDD is allowed to minimize.
773 */
774 mb();
775
Manu Gautam28b1bac2012-01-30 16:43:06 +0530776 clk_disable_unprepare(mehci->core_clk);
777 clk_disable_unprepare(mehci->phy_clk);
778 clk_disable_unprepare(mehci->cal_clk);
779 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530780
Amit Blayd6ea6102012-06-07 16:26:24 +0300781 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
782 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
783
784 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700785 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300786 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700787
Hemant Kumare6275972012-02-29 20:06:21 -0800788 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700789 mehci->bus_vote = false;
790 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800791 }
792
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530793 atomic_set(&mehci->in_lpm, 1);
794 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700795
Manu Gautam3fb60ca2013-02-13 18:33:33 +0530796 if (mehci->wakeup_irq) {
797 mehci->wakeup_irq_enabled = 1;
798 enable_irq_wake(mehci->wakeup_irq);
799 enable_irq(mehci->wakeup_irq);
800 }
Hemant Kumar6fd65032012-05-23 13:02:24 -0700801
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700802 if (pdata && pdata->standalone_latency)
803 pm_qos_update_request(&mehci->pm_qos_req_dma,
804 PM_QOS_DEFAULT_VALUE);
805
Sudhir Sharma1673e302012-08-27 17:37:24 -0700806 wake_unlock(&mehci->wlock);
807
Pavankumar Kondetiafbaf8e2013-02-22 11:58:44 +0530808 dev_dbg(mehci->dev, "HSIC-USB in low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530809
810 return 0;
811}
812
813static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
814{
815 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530816 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530817 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300818 int min_vol, max_vol;
Hemant Kumard343c012012-09-06 19:57:14 -0700819 unsigned long flags;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700820 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530821
822 if (!atomic_read(&mehci->in_lpm)) {
823 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
824 return 0;
825 }
826
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530827 /* Handles race with Async interrupt */
828 disable_irq(hcd->irq);
829
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700830 if (pdata && pdata->standalone_latency)
831 pm_qos_update_request(&mehci->pm_qos_req_dma,
832 pdata->standalone_latency + 1);
833
Manu Gautam3fb60ca2013-02-13 18:33:33 +0530834 if (mehci->wakeup_irq) {
835 spin_lock_irqsave(&mehci->wakeup_lock, flags);
836 if (mehci->wakeup_irq_enabled) {
837 disable_irq_wake(mehci->wakeup_irq);
838 disable_irq_nosync(mehci->wakeup_irq);
839 mehci->wakeup_irq_enabled = 0;
840 }
841 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700842 }
843
Sudhir Sharma1673e302012-08-27 17:37:24 -0700844 wake_lock(&mehci->wlock);
845
Hemant Kumare6275972012-02-29 20:06:21 -0800846 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700847 mehci->bus_vote = true;
848 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800849 }
850
Amit Blayd6ea6102012-06-07 16:26:24 +0300851 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
852 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
853
854 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700855 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300856 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700857
Manu Gautam28b1bac2012-01-30 16:43:06 +0530858 clk_prepare_enable(mehci->core_clk);
859 clk_prepare_enable(mehci->phy_clk);
860 clk_prepare_enable(mehci->cal_clk);
861 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530862
863 temp = readl_relaxed(USB_USBCMD);
864 temp &= ~ASYNC_INTR_CTRL;
865 temp &= ~ULPI_STP_CTRL;
866 writel_relaxed(temp, USB_USBCMD);
867
868 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
869 goto skip_phy_resume;
870
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700871 temp = readl_relaxed(USB_PORTSC);
872 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530873 writel_relaxed(temp, USB_PORTSC);
874 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
875 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
876 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
877 break;
878 udelay(1);
879 cnt++;
880 }
881
882 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
883 /*
884 * This is a fatal error. Reset the link and
885 * PHY to make hsic working.
886 */
887 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530888 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530889 msm_hsic_reset(mehci);
890 }
891
892skip_phy_resume:
893
Hemant Kumar6fd65032012-05-23 13:02:24 -0700894 usb_hcd_resume_root_hub(hcd);
895
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530896 atomic_set(&mehci->in_lpm, 0);
897
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530898 if (atomic_read(&mehci->async_int)) {
899 atomic_set(&mehci->async_int, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530900 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700901 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700902 }
903
Sudhir Sharma1673e302012-08-27 17:37:24 -0700904 if (atomic_read(&mehci->pm_usage_cnt)) {
905 atomic_set(&mehci->pm_usage_cnt, 0);
906 pm_runtime_put_noidle(mehci->dev);
907 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700908
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530909 enable_irq(hcd->irq);
Pavankumar Kondetiafbaf8e2013-02-22 11:58:44 +0530910 dev_dbg(mehci->dev, "HSIC-USB exited from low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530911
912 return 0;
913}
914#endif
915
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700916static void ehci_hsic_bus_vote_w(struct work_struct *w)
917{
918 struct msm_hsic_hcd *mehci =
919 container_of(w, struct msm_hsic_hcd, bus_vote_w);
920 int ret;
921
922 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
923 mehci->bus_vote);
924 if (ret)
925 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
926 __func__, ret);
927}
928
Pavankumar Kondeti23720492013-01-29 14:41:58 +0530929static int msm_hsic_reset_done(struct usb_hcd *hcd)
930{
931 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
932 u32 __iomem *status_reg = &ehci->regs->port_status[0];
933 int ret;
934
935 ehci_writel(ehci, ehci_readl(ehci, status_reg) & ~(PORT_RWC_BITS |
936 PORT_RESET), status_reg);
937
938 ret = handshake(ehci, status_reg, PORT_RESET, 0, 1 * 1000);
939
940 if (ret)
941 pr_err("reset handshake failed in %s\n", __func__);
942 else
943 ehci_writel(ehci, ehci_readl(ehci, &ehci->regs->command) |
944 CMD_RUN, &ehci->regs->command);
945
946 return ret;
947}
948
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700949#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530950static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
951{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700952 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530953 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700954 u32 status;
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530955 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530956
957 if (atomic_read(&mehci->in_lpm)) {
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700958 dev_dbg(mehci->dev, "phy async intr\n");
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530959 dbg_log_event(NULL, "Async IRQ", 0);
960 ret = pm_runtime_get(mehci->dev);
961 if ((ret == 1) || (ret == -EINPROGRESS)) {
962 pm_runtime_put_noidle(mehci->dev);
963 } else {
964 disable_irq_nosync(hcd->irq);
965 atomic_set(&mehci->async_int, 1);
966 }
967
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530968 return IRQ_HANDLED;
969 }
970
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700971 status = ehci_readl(ehci, &ehci->regs->status);
972
973 if (status & STS_GPTIMER0_INTERRUPT) {
974 int timeleft;
975
Pavankumar Kondeti23720492013-01-29 14:41:58 +0530976 dbg_log_event(NULL, "FPR: gpt0_isr", mehci->bus_reset);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700977
978 timeleft = GPT_CNT(ehci_readl(ehci,
979 &mehci->timer->gptimer1_ctrl));
980 if (timeleft) {
Pavankumar Kondeti23720492013-01-29 14:41:58 +0530981 if (mehci->bus_reset) {
982 ret = msm_hsic_reset_done(hcd);
983 if (ret) {
984 mehci->reset_again = 1;
985 dbg_log_event(NULL, "RESET: fail", 0);
986 }
987 } else {
988 ehci_writel(ehci, ehci_readl(ehci,
989 &ehci->regs->command) | CMD_RUN,
990 &ehci->regs->command);
991 }
992 } else {
993 if (mehci->bus_reset)
994 mehci->reset_again = 1;
995 else
996 mehci->resume_again = 1;
997 }
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700998
999 dbg_log_event(NULL, "FPR: timeleft", timeleft);
1000
1001 complete(&mehci->gpt0_completion);
1002 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
1003 }
1004
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301005 return ehci_irq(hcd);
1006}
1007
1008static int ehci_hsic_reset(struct usb_hcd *hcd)
1009{
1010 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001011 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301012 int retval;
1013
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001014 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301015 ehci->caps = USB_CAPLENGTH;
1016 ehci->regs = USB_CAPLENGTH +
1017 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
1018 dbg_hcs_params(ehci, "reset");
1019 dbg_hcc_params(ehci, "reset");
1020
1021 /* cache the data to minimize the chip reads*/
1022 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
1023
1024 hcd->has_tt = 1;
1025 ehci->sbrn = HCD_USB2;
1026
1027 retval = ehci_halt(ehci);
1028 if (retval)
1029 return retval;
1030
1031 /* data structure init */
1032 retval = ehci_init(hcd);
1033 if (retval)
1034 return retval;
1035
1036 retval = ehci_reset(ehci);
1037 if (retval)
1038 return retval;
1039
1040 /* bursts of unspecified length. */
1041 writel_relaxed(0, USB_AHBBURST);
1042 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +05301043 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301044 /* Disable streaming mode and select host mode */
1045 writel_relaxed(0x13, USB_USBMODE);
1046
1047 ehci_port_power(ehci, 1);
1048 return 0;
1049}
1050
Jack Phamc0d41732012-09-28 17:45:38 -07001051#ifdef CONFIG_PM
1052
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301053#define RESET_RETRY_LIMIT 3
1054#define RESET_SIGNAL_TIME_SOF_USEC (50 * 1000)
1055#define RESET_SIGNAL_TIME_USEC (20 * 1000)
1056static void ehci_hsic_reset_sof_bug_handler(struct usb_hcd *hcd, u32 val)
1057{
1058 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1059 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1060 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1061 u32 __iomem *status_reg = &ehci->regs->port_status[0];
Pavankumar Kondetifc7d1d82013-03-05 09:43:22 +05301062 u32 cmd;
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301063 unsigned long flags;
1064 int retries = 0, ret, cnt = RESET_SIGNAL_TIME_USEC;
1065
1066 if (pdata && pdata->swfi_latency)
1067 pm_qos_update_request(&mehci->pm_qos_req_dma,
1068 pdata->swfi_latency + 1);
1069
1070 mehci->bus_reset = 1;
Pavankumar Kondetifc7d1d82013-03-05 09:43:22 +05301071
1072 /* Halt the controller */
1073 cmd = ehci_readl(ehci, &ehci->regs->command);
1074 cmd &= ~CMD_RUN;
1075 ehci_writel(ehci, cmd, &ehci->regs->command);
1076 ret = handshake(ehci, &ehci->regs->status, STS_HALT,
1077 STS_HALT, 16 * 125);
1078 if (ret) {
1079 pr_err("halt handshake fatal error\n");
1080 dbg_log_event(NULL, "HALT: fatal", 0);
1081 goto fail;
1082 }
1083
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301084retry:
1085 retries++;
1086 dbg_log_event(NULL, "RESET: start", retries);
1087 pr_debug("reset begin %d\n", retries);
1088 mehci->reset_again = 0;
1089 spin_lock_irqsave(&ehci->lock, flags);
1090 ehci_writel(ehci, val, status_reg);
1091 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_USEC - 1),
1092 &mehci->timer->gptimer0_ld);
1093 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1094 &mehci->timer->gptimer0_ctrl);
1095 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1096 &ehci->regs->intr_enable);
1097
1098 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_SOF_USEC - 1),
1099 &mehci->timer->gptimer1_ld);
1100 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1101 &mehci->timer->gptimer1_ctrl);
1102
1103 spin_unlock_irqrestore(&ehci->lock, flags);
1104 wait_for_completion(&mehci->gpt0_completion);
1105
1106 if (!mehci->reset_again)
1107 goto done;
1108
1109 if (handshake(ehci, status_reg, PORT_RESET, 0, 10 * 1000)) {
1110 pr_err("reset handshake fatal error\n");
1111 dbg_log_event(NULL, "RESET: fatal", retries);
1112 goto fail;
1113 }
1114
1115 if (retries < RESET_RETRY_LIMIT)
1116 goto retry;
1117
1118 /* complete reset in tight loop */
1119 pr_info("RESET in tight loop\n");
1120 dbg_log_event(NULL, "RESET: tight", 0);
1121
1122 spin_lock_irqsave(&ehci->lock, flags);
1123 ehci_writel(ehci, val, status_reg);
1124 while (cnt--)
1125 udelay(1);
1126 ret = msm_hsic_reset_done(hcd);
1127 spin_unlock_irqrestore(&ehci->lock, flags);
1128 if (ret) {
1129 pr_err("RESET in tight loop failed\n");
1130 dbg_log_event(NULL, "RESET: tight failed", 0);
1131 goto fail;
1132 }
1133
1134done:
1135 dbg_log_event(NULL, "RESET: done", retries);
1136 pr_debug("reset completed\n");
1137fail:
1138 mehci->bus_reset = 0;
1139 if (pdata && pdata->swfi_latency)
1140 pm_qos_update_request(&mehci->pm_qos_req_dma,
1141 PM_QOS_DEFAULT_VALUE);
1142}
1143
Hemant Kumar45d211b2012-05-31 17:58:43 -07001144static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
1145{
Pavankumar Kondetia723f742012-09-14 14:02:36 +05301146 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1147
1148 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
1149 dbg_log_event(NULL, "RH suspend attempt failed", 0);
1150 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
1151 __func__);
1152 return -EAGAIN;
1153 }
1154
Hemant Kumar45d211b2012-05-31 17:58:43 -07001155 dbg_log_event(NULL, "Suspend RH", 0);
1156 return ehci_bus_suspend(hcd);
1157}
1158
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001159#define RESUME_RETRY_LIMIT 3
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301160#define RESUME_SIGNAL_TIME_USEC (21 * 1000)
1161#define RESUME_SIGNAL_TIME_SOF_USEC (23 * 1000)
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001162static int msm_hsic_resume_thread(void *data)
1163{
1164 struct msm_hsic_hcd *mehci = data;
1165 struct usb_hcd *hcd = hsic_to_hcd(mehci);
1166 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1167 u32 temp;
1168 unsigned long resume_needed = 0;
1169 int retry_cnt = 0;
1170 int tight_resume = 0;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301171 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001172
1173 dbg_log_event(NULL, "Resume RH", 0);
1174
1175 /* keep delay between bus states */
1176 if (time_before(jiffies, ehci->next_statechange))
1177 usleep_range(5000, 5000);
1178
1179 spin_lock_irq(&ehci->lock);
1180 if (!HCD_HW_ACCESSIBLE(hcd)) {
1181 spin_unlock_irq(&ehci->lock);
1182 mehci->resume_status = -ESHUTDOWN;
1183 complete(&mehci->rt_completion);
1184 return 0;
1185 }
1186
1187 if (unlikely(ehci->debug)) {
1188 if (!dbgp_reset_prep())
1189 ehci->debug = NULL;
1190 else
1191 dbgp_external_startup();
1192 }
1193
1194 /* at least some APM implementations will try to deliver
1195 * IRQs right away, so delay them until we're ready.
1196 */
1197 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
1198
1199 /* re-init operational registers */
1200 ehci_writel(ehci, 0, &ehci->regs->segment);
1201 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
1202 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
1203
1204 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
1205 if (ehci->resume_sof_bug)
1206 ehci->command &= ~CMD_RUN;
1207
1208 /* restore CMD_RUN, framelist size, and irq threshold */
1209 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1210
1211 /* manually resume the ports we suspended during bus_suspend() */
1212resume_again:
1213 if (retry_cnt >= RESUME_RETRY_LIMIT) {
1214 pr_info("retry count(%d) reached max, resume in tight loop\n",
1215 retry_cnt);
1216 tight_resume = 1;
1217 }
1218
1219
1220 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1221 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
1222 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
1223 temp |= PORT_RESUME;
1224 set_bit(0, &resume_needed);
1225 }
1226 dbg_log_event(NULL, "FPR: Set", temp);
1227 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1228
1229 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1230 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1231 * controller in MSM clears FPR bit after driving the resume signal for
1232 * 20ms. Workaround is to stop SOFs before driving resume and then start
1233 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1234 * completion otherwise peripheral may enter undefined state. As
1235 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1236 * to time the resume sequence. If driver exceeds allowable time SOFs,
1237 * repeat the resume process.
1238 */
1239 if (ehci->resume_sof_bug && resume_needed) {
1240 if (!tight_resume) {
1241 mehci->resume_again = 0;
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301242 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_USEC - 1),
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001243 &mehci->timer->gptimer0_ld);
1244 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1245 &mehci->timer->gptimer0_ctrl);
1246 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1247 &ehci->regs->intr_enable);
1248
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301249 ehci_writel(ehci, GPT_LD(
1250 RESUME_SIGNAL_TIME_SOF_USEC - 1),
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001251 &mehci->timer->gptimer1_ld);
1252 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1253 &mehci->timer->gptimer1_ctrl);
1254
1255 spin_unlock_irq(&ehci->lock);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301256 if (pdata && pdata->swfi_latency)
1257 pm_qos_update_request(&mehci->pm_qos_req_dma,
1258 pdata->swfi_latency + 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001259 wait_for_completion(&mehci->gpt0_completion);
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001260 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301261 pm_qos_update_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001262 pdata->standalone_latency + 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001263 spin_lock_irq(&ehci->lock);
1264 } else {
1265 dbg_log_event(NULL, "FPR: Tightloop", 0);
1266 /* do the resume in a tight loop */
1267 handshake(ehci, &ehci->regs->port_status[0],
1268 PORT_RESUME, 0, 22 * 1000);
1269 ehci_writel(ehci, ehci_readl(ehci,
1270 &ehci->regs->command) | CMD_RUN,
1271 &ehci->regs->command);
1272 }
1273
1274 if (mehci->resume_again) {
1275 int temp;
1276
1277 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1278 pr_info("FPR: retry count: %d\n", retry_cnt);
1279 spin_unlock_irq(&ehci->lock);
1280 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1281 temp &= ~PORT_RWC_BITS;
1282 temp |= PORT_SUSPEND;
1283 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1284 /* Keep the bus idle for 5ms so that peripheral
1285 * can detect and initiate suspend
1286 */
1287 usleep_range(5000, 5000);
1288 dbg_log_event(NULL,
1289 "FPR: RResume",
1290 ehci_readl(ehci, &ehci->regs->port_status[0]));
1291 spin_lock_irq(&ehci->lock);
1292 mehci->resume_again = 0;
1293 retry_cnt++;
1294 goto resume_again;
1295 }
1296 }
1297
1298 dbg_log_event(NULL, "FPR: RT-Done", 0);
1299 mehci->resume_status = 1;
1300 spin_unlock_irq(&ehci->lock);
1301
1302 complete(&mehci->rt_completion);
1303
1304 return 0;
1305}
1306
Hemant Kumar45d211b2012-05-31 17:58:43 -07001307static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1308{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001309 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1310 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1311 u32 temp;
1312 struct task_struct *resume_thread = NULL;
1313
1314 mehci->resume_status = 0;
1315 resume_thread = kthread_run(msm_hsic_resume_thread,
1316 mehci, "hsic_resume_thread");
1317 if (IS_ERR(resume_thread)) {
1318 pr_err("Error creating resume thread:%lu\n",
1319 PTR_ERR(resume_thread));
1320 return PTR_ERR(resume_thread);
1321 }
1322
1323 wait_for_completion(&mehci->rt_completion);
1324
1325 if (mehci->resume_status < 0)
1326 return mehci->resume_status;
1327
1328 dbg_log_event(NULL, "FPR: Wokeup", 0);
1329 spin_lock_irq(&ehci->lock);
1330 (void) ehci_readl(ehci, &ehci->regs->command);
1331
1332 temp = 0;
1333 if (ehci->async->qh_next.qh)
1334 temp |= CMD_ASE;
1335 if (ehci->periodic_sched)
1336 temp |= CMD_PSE;
1337 if (temp) {
1338 ehci->command |= temp;
1339 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1340 }
1341
1342 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1343 hcd->state = HC_STATE_RUNNING;
1344 ehci->rh_state = EHCI_RH_RUNNING;
Manu Gautam3a8eb532013-02-13 18:29:02 +05301345 ehci->command |= CMD_RUN;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001346
1347 /* Now we can safely re-enable irqs */
1348 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1349
1350 spin_unlock_irq(&ehci->lock);
1351
1352 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001353}
1354
Jack Phamc0d41732012-09-28 17:45:38 -07001355#else
1356
1357#define ehci_hsic_bus_suspend NULL
1358#define ehci_hsic_bus_resume NULL
1359
1360#endif /* CONFIG_PM */
1361
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001362static void ehci_msm_set_autosuspend_delay(struct usb_device *dev)
1363{
1364 if (!dev->parent) /*for root hub no delay*/
1365 pm_runtime_set_autosuspend_delay(&dev->dev, 0);
1366 else
1367 pm_runtime_set_autosuspend_delay(&dev->dev, 200);
1368}
1369
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301370static struct hc_driver msm_hsic_driver = {
1371 .description = hcd_name,
1372 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1373 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1374
1375 /*
1376 * generic hardware linkage
1377 */
1378 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001379 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301380
1381 .reset = ehci_hsic_reset,
1382 .start = ehci_run,
1383
1384 .stop = ehci_stop,
1385 .shutdown = ehci_shutdown,
1386
1387 /*
1388 * managing i/o requests and associated device resources
1389 */
Hemant Kumar4d50a432012-08-15 09:06:35 -07001390 .urb_enqueue = ehci_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301391 .urb_dequeue = ehci_urb_dequeue,
1392 .endpoint_disable = ehci_endpoint_disable,
1393 .endpoint_reset = ehci_endpoint_reset,
1394 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1395
1396 /*
1397 * scheduling support
1398 */
1399 .get_frame_number = ehci_get_frame,
1400
1401 /*
1402 * root hub support
1403 */
1404 .hub_status_data = ehci_hub_status_data,
1405 .hub_control = ehci_hub_control,
1406 .relinquish_port = ehci_relinquish_port,
1407 .port_handed_over = ehci_port_handed_over,
1408
1409 /*
1410 * PM support
1411 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001412 .bus_suspend = ehci_hsic_bus_suspend,
1413 .bus_resume = ehci_hsic_bus_resume,
1414
Hemant Kumar4d50a432012-08-15 09:06:35 -07001415 .log_urb = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001416 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001417
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001418 .set_autosuspend_delay = ehci_msm_set_autosuspend_delay,
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301419 .reset_sof_bug_handler = ehci_hsic_reset_sof_bug_handler,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301420};
1421
1422static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1423{
1424 int ret = 0;
1425
1426 if (!init)
1427 goto put_clocks;
1428
Lena Salman8c8ba382012-02-14 15:59:31 +02001429 /*core_clk is required for LINK protocol engine
1430 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001431 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1432 if (IS_ERR(mehci->core_clk)) {
1433 dev_err(mehci->dev, "failed to get core_clk\n");
1434 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301435 return ret;
1436 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301437
Ofir Cohen07944aa2012-12-23 13:41:57 +02001438 /* alt_core_clk is for LINK to be used during PHY RESET in
1439 * targets on which link does NOT use asynchronous reset methodology.
Lena Salman8c8ba382012-02-14 15:59:31 +02001440 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001441 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
Manu Gautam863b74132012-11-21 14:30:04 +05301442 if (IS_ERR(mehci->alt_core_clk))
1443 dev_dbg(mehci->dev, "failed to get alt_core_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301444
Lena Salman8c8ba382012-02-14 15:59:31 +02001445 /* phy_clk is required for HSIC PHY operation
1446 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001447 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1448 if (IS_ERR(mehci->phy_clk)) {
1449 dev_err(mehci->dev, "failed to get phy_clk\n");
1450 ret = PTR_ERR(mehci->phy_clk);
1451 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301452 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301453
1454 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001455 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301456 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001457 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301458 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001459 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301460 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301461
1462 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001463 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301464 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001465 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301466 ret = PTR_ERR(mehci->ahb_clk);
1467 goto put_cal_clk;
1468 }
1469
Manu Gautam28b1bac2012-01-30 16:43:06 +05301470 clk_prepare_enable(mehci->core_clk);
1471 clk_prepare_enable(mehci->phy_clk);
1472 clk_prepare_enable(mehci->cal_clk);
1473 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301474
1475 return 0;
1476
1477put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001478 if (!atomic_read(&mehci->in_lpm)) {
1479 clk_disable_unprepare(mehci->core_clk);
1480 clk_disable_unprepare(mehci->phy_clk);
1481 clk_disable_unprepare(mehci->cal_clk);
1482 clk_disable_unprepare(mehci->ahb_clk);
1483 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301484 clk_put(mehci->ahb_clk);
1485put_cal_clk:
1486 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001487put_phy_clk:
1488 clk_put(mehci->phy_clk);
1489put_alt_core_clk:
Manu Gautam863b74132012-11-21 14:30:04 +05301490 if (!IS_ERR(mehci->alt_core_clk))
1491 clk_put(mehci->alt_core_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001492 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301493
1494 return ret;
1495}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001496static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1497{
1498 struct msm_hsic_hcd *mehci = dev_id;
1499
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001500 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001501
1502 if (mehci)
1503 msm_hsic_config_gpios(mehci, 0);
1504
1505 return IRQ_HANDLED;
1506}
1507
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001508static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1509{
1510 struct msm_hsic_hcd *mehci = data;
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301511 int ret;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001512
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301513 if (irq == mehci->async_irq) {
1514 mehci->async_int_cnt++;
1515 dbg_log_event(NULL, "Remote Wakeup (ASYNC) IRQ",
1516 mehci->async_int_cnt);
1517 } else {
1518 mehci->wakeup_int_cnt++;
1519 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
1520 }
1521 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt %d cnt: %u, %u\n",
1522 __func__, irq, mehci->wakeup_int_cnt, mehci->async_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001523
Sudhir Sharma1673e302012-08-27 17:37:24 -07001524 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001525
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301526 if (mehci->wakeup_irq) {
1527 spin_lock(&mehci->wakeup_lock);
1528 if (mehci->wakeup_irq_enabled) {
1529 mehci->wakeup_irq_enabled = 0;
1530 disable_irq_wake(irq);
1531 disable_irq_nosync(irq);
1532 }
1533 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001534 }
1535
Sudhir Sharma1673e302012-08-27 17:37:24 -07001536 if (!atomic_read(&mehci->pm_usage_cnt)) {
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301537 ret = pm_runtime_get(mehci->dev);
1538 /*
1539 * HSIC runtime resume can race with us.
1540 * if we are active (ret == 1) or resuming
1541 * (ret == -EINPROGRESS), decrement the
1542 * PM usage counter before returning.
1543 */
1544 if ((ret == 1) || (ret == -EINPROGRESS))
1545 pm_runtime_put_noidle(mehci->dev);
1546 else
1547 atomic_set(&mehci->pm_usage_cnt, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001548 }
1549
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001550 return IRQ_HANDLED;
1551}
1552
Hemant Kumare6275972012-02-29 20:06:21 -08001553static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1554{
1555 if (debug_bus_voting_enabled)
1556 seq_printf(s, "enabled\n");
1557 else
1558 seq_printf(s, "disabled\n");
1559
1560 return 0;
1561}
1562
1563static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1564{
1565 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1566}
1567
1568static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1569 const char __user *ubuf, size_t count, loff_t *ppos)
1570{
1571 char buf[8];
1572 int ret;
1573 struct seq_file *s = file->private_data;
1574 struct msm_hsic_hcd *mehci = s->private;
1575
1576 memset(buf, 0x00, sizeof(buf));
1577
1578 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1579 return -EFAULT;
1580
1581 if (!strncmp(buf, "enable", 6)) {
1582 /* Do not vote here. Let hsic driver decide when to vote */
1583 debug_bus_voting_enabled = true;
1584 } else {
1585 debug_bus_voting_enabled = false;
1586 if (mehci->bus_perf_client) {
1587 ret = msm_bus_scale_client_update_request(
1588 mehci->bus_perf_client, 0);
1589 if (ret)
1590 dev_err(mehci->dev, "%s: Failed to devote "
1591 "for bus bw %d\n", __func__, ret);
1592 }
1593 }
1594
1595 return count;
1596}
1597
1598const struct file_operations ehci_hsic_msm_bus_fops = {
1599 .open = ehci_hsic_msm_bus_open,
1600 .read = seq_read,
1601 .write = ehci_hsic_msm_bus_write,
1602 .llseek = seq_lseek,
1603 .release = single_release,
1604};
1605
Hemant Kumar6fd65032012-05-23 13:02:24 -07001606static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1607{
1608 struct msm_hsic_hcd *mehci = s->private;
1609
1610 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1611
1612 return 0;
1613}
1614
1615static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1616{
1617 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1618}
1619
1620const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1621 .open = ehci_hsic_msm_wakeup_cnt_open,
1622 .read = seq_read,
1623 .llseek = seq_lseek,
1624 .release = single_release,
1625};
1626
Hemant Kumar45d211b2012-05-31 17:58:43 -07001627static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1628{
1629 unsigned long flags;
1630 unsigned i;
1631
1632 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1633
1634 i = dbg_hsic_data.idx;
1635 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1636 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1637 continue;
1638 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1639 }
1640
1641 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1642
1643 return 0;
1644}
1645
1646static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1647{
1648 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1649}
1650
1651const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1652 .open = ehci_hsic_msm_data_events_open,
1653 .read = seq_read,
1654 .llseek = seq_lseek,
1655 .release = single_release,
1656};
1657
1658static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1659{
1660 unsigned long flags;
1661 unsigned i;
1662
1663 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1664
1665 i = dbg_hsic_ctrl.idx;
1666 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1667 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1668 continue;
1669 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1670 }
1671
1672 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1673
1674 return 0;
1675}
1676
1677static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1678{
1679 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1680}
1681
1682const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1683 .open = ehci_hsic_msm_ctrl_events_open,
1684 .read = seq_read,
1685 .llseek = seq_lseek,
1686 .release = single_release,
1687};
1688
Hemant Kumare6275972012-02-29 20:06:21 -08001689static struct dentry *ehci_hsic_msm_dbg_root;
1690static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1691{
1692 struct dentry *ehci_hsic_msm_dentry;
1693
1694 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1695
1696 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1697 return -ENODEV;
1698
1699 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1700 S_IRUGO | S_IWUSR,
1701 ehci_hsic_msm_dbg_root, mehci,
1702 &ehci_hsic_msm_bus_fops);
1703
1704 if (!ehci_hsic_msm_dentry) {
1705 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1706 return -ENODEV;
1707 }
1708
Hemant Kumar6fd65032012-05-23 13:02:24 -07001709 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1710 S_IRUGO,
1711 ehci_hsic_msm_dbg_root, mehci,
1712 &ehci_hsic_msm_wakeup_cnt_fops);
1713
1714 if (!ehci_hsic_msm_dentry) {
1715 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1716 return -ENODEV;
1717 }
1718
Hemant Kumar45d211b2012-05-31 17:58:43 -07001719 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1720 S_IRUGO,
1721 ehci_hsic_msm_dbg_root, mehci,
1722 &ehci_hsic_msm_dbg_ctrl_fops);
1723
1724 if (!ehci_hsic_msm_dentry) {
1725 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1726 return -ENODEV;
1727 }
1728
1729 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1730 S_IRUGO,
1731 ehci_hsic_msm_dbg_root, mehci,
1732 &ehci_hsic_msm_dbg_data_fops);
1733
1734 if (!ehci_hsic_msm_dentry) {
1735 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1736 return -ENODEV;
1737 }
1738
Hemant Kumare6275972012-02-29 20:06:21 -08001739 return 0;
1740}
1741
1742static void ehci_hsic_msm_debugfs_cleanup(void)
1743{
1744 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1745}
1746
Manu Gautam863b74132012-11-21 14:30:04 +05301747struct msm_hsic_host_platform_data *msm_hsic_dt_to_pdata(
1748 struct platform_device *pdev)
1749{
1750 struct device_node *node = pdev->dev.of_node;
1751 struct msm_hsic_host_platform_data *pdata;
Ido Shayevitzca5dc492013-01-09 14:49:59 +02001752 int res_gpio;
Manu Gautam863b74132012-11-21 14:30:04 +05301753
1754 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1755 if (!pdata) {
1756 dev_err(&pdev->dev, "unable to allocate platform data\n");
1757 return NULL;
1758 }
Manu Gautam863b74132012-11-21 14:30:04 +05301759
Ido Shayevitzca5dc492013-01-09 14:49:59 +02001760 res_gpio = of_get_named_gpio(node, "hsic,strobe-gpio", 0);
1761 if (res_gpio < 0)
1762 res_gpio = 0;
1763 pdata->strobe = res_gpio;
1764
1765 res_gpio = of_get_named_gpio(node, "hsic,data-gpio", 0);
1766 if (res_gpio < 0)
1767 res_gpio = 0;
1768 pdata->data = res_gpio;
Manu Gautam863b74132012-11-21 14:30:04 +05301769
1770 pdata->ignore_cal_pad_config = of_property_read_bool(node,
1771 "hsic,ignore-cal-pad-config");
1772 of_property_read_u32(node, "hsic,strobe-pad-offset",
1773 &pdata->strobe_pad_offset);
1774 of_property_read_u32(node, "hsic,data-pad-offset",
1775 &pdata->data_pad_offset);
1776
Ido Shayevitz95c46882013-01-20 13:47:46 +02001777 pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
1778
Shimrit Malichi36a0c852013-03-10 11:39:10 +02001779 pdata->pool_64_bit_align = of_property_read_bool(node,
1780 "qcom,pool-64-bit-align");
1781
Manu Gautam863b74132012-11-21 14:30:04 +05301782 return pdata;
1783}
1784
1785
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301786static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1787{
1788 struct usb_hcd *hcd;
1789 struct resource *res;
1790 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301791 struct msm_hsic_host_platform_data *pdata;
Manu Gautam16562792013-03-13 07:04:11 +05301792 unsigned long wakeup_irq_flags = 0;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301793 int ret;
1794
1795 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1796
Manu Gautam863b74132012-11-21 14:30:04 +05301797 if (pdev->dev.of_node) {
1798 dev_dbg(&pdev->dev, "device tree enabled\n");
1799 pdev->dev.platform_data = msm_hsic_dt_to_pdata(pdev);
1800 dev_set_name(&pdev->dev, ehci_msm_hsic_driver.driver.name);
Manu Gautam16562792013-03-13 07:04:11 +05301801 } else {
1802 /* explicitly pass wakeup_irq flag for !DT */
1803 wakeup_irq_flags = IRQF_TRIGGER_HIGH;
Manu Gautam863b74132012-11-21 14:30:04 +05301804 }
1805 if (!pdev->dev.platform_data)
1806 dev_dbg(&pdev->dev, "No platform data given\n");
1807
Ofir Cohen4cc55372012-11-20 11:17:24 +02001808 if (!pdev->dev.dma_mask)
1809 pdev->dev.dma_mask = &ehci_msm_hsic_dma_mask;
1810 if (!pdev->dev.coherent_dma_mask)
1811 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
1812
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301813 /* After parent device's probe is executed, it will be put in suspend
1814 * mode. When child device's probe is called, driver core is not
1815 * resuming parent device due to which parent will be in suspend even
1816 * though child is active. Hence resume the parent device explicitly.
1817 */
1818 if (pdev->dev.parent)
1819 pm_runtime_get_sync(pdev->dev.parent);
1820
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301821 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1822 dev_name(&pdev->dev));
1823 if (!hcd) {
1824 dev_err(&pdev->dev, "Unable to create HCD\n");
1825 return -ENOMEM;
1826 }
1827
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301828 hcd_to_bus(hcd)->skip_resume = true;
1829
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301830 hcd->irq = platform_get_irq(pdev, 0);
1831 if (hcd->irq < 0) {
1832 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1833 ret = hcd->irq;
1834 goto put_hcd;
1835 }
1836
1837 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1838 if (!res) {
1839 dev_err(&pdev->dev, "Unable to get memory resource\n");
1840 ret = -ENODEV;
1841 goto put_hcd;
1842 }
1843
1844 hcd->rsrc_start = res->start;
1845 hcd->rsrc_len = resource_size(res);
1846 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1847 if (!hcd->regs) {
1848 dev_err(&pdev->dev, "ioremap failed\n");
1849 ret = -ENOMEM;
1850 goto put_hcd;
1851 }
1852
1853 mehci = hcd_to_hsic(hcd);
1854 mehci->dev = &pdev->dev;
Hemant Kumar30d361c2012-08-20 14:44:40 -07001855 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301856
Hemant Kumard343c012012-09-06 19:57:14 -07001857 spin_lock_init(&mehci->wakeup_lock);
1858
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001859 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001860 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001861
Hemant Kumare4040492012-06-21 17:35:42 -07001862 mehci->ehci.resume_sof_bug = 1;
Shimrit Malichi36a0c852013-03-10 11:39:10 +02001863 mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
Hemant Kumare4040492012-06-21 17:35:42 -07001864
Hemant Kumar30d361c2012-08-20 14:44:40 -07001865 if (pdata)
1866 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Hemant Kumar933e0402012-05-22 11:11:40 -07001867
Ofir Cohen4cc55372012-11-20 11:17:24 +02001868 ret = msm_hsic_init_gdsc(mehci, 1);
1869 if (ret) {
1870 dev_err(&pdev->dev, "unable to initialize GDSC\n");
1871 ret = -ENODEV;
1872 goto put_hcd;
1873 }
1874
Vamsi Krishna34f01582011-12-14 19:54:42 -08001875 res = platform_get_resource_byname(pdev,
1876 IORESOURCE_IRQ,
1877 "peripheral_status_irq");
1878 if (res)
1879 mehci->peripheral_status_irq = res->start;
1880
Jack Pham0cc75c42012-10-10 02:03:50 +02001881 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "wakeup");
Hemant Kumar6fd65032012-05-23 13:02:24 -07001882 if (res) {
Jack Pham0cc75c42012-10-10 02:03:50 +02001883 mehci->wakeup_irq = res->start;
Hemant Kumar6fd65032012-05-23 13:02:24 -07001884 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1885 }
1886
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301887 ret = msm_hsic_init_clocks(mehci, 1);
1888 if (ret) {
1889 dev_err(&pdev->dev, "unable to initialize clocks\n");
1890 ret = -ENODEV;
1891 goto unmap;
1892 }
1893
1894 ret = msm_hsic_init_vddcx(mehci, 1);
1895 if (ret) {
1896 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1897 ret = -ENODEV;
1898 goto deinit_clocks;
1899 }
1900
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001901 init_completion(&mehci->rt_completion);
1902 init_completion(&mehci->gpt0_completion);
Ofir Cohen5dddb152012-11-14 11:18:50 +02001903
1904 msm_hsic_phy_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301905
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001906 ehci_wq = create_singlethread_workqueue("ehci_wq");
1907 if (!ehci_wq) {
1908 dev_err(&pdev->dev, "unable to create workqueue\n");
1909 ret = -ENOMEM;
1910 goto deinit_vddcx;
1911 }
1912
1913 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1914
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301915 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1916 if (ret) {
1917 dev_err(&pdev->dev, "unable to register HCD\n");
Ofir Cohen5dddb152012-11-14 11:18:50 +02001918 goto destroy_wq;
1919 }
1920
1921 ret = msm_hsic_start(mehci);
1922 if (ret) {
1923 dev_err(&pdev->dev, "unable to initialize PHY\n");
1924 goto destroy_wq;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301925 }
1926
1927 device_init_wakeup(&pdev->dev, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001928 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1929 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001930
1931 if (mehci->peripheral_status_irq) {
1932 ret = request_threaded_irq(mehci->peripheral_status_irq,
1933 NULL, hsic_peripheral_status_change,
1934 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1935 | IRQF_SHARED,
1936 "hsic_peripheral_status", mehci);
1937 if (ret)
1938 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1939 __func__, mehci->peripheral_status_irq, ret);
1940 }
1941
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001942 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001943 if (mehci->wakeup_irq) {
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07001944 /* In case if wakeup gpio is pulled high at this point
1945 * remote wakeup interrupt fires right after request_irq.
1946 * Remote wake up interrupt only needs to be enabled when
1947 * HSIC bus goes to suspend.
1948 */
1949 irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001950 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Manu Gautam16562792013-03-13 07:04:11 +05301951 wakeup_irq_flags,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001952 "msm_hsic_wakeup", mehci);
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07001953 if (ret) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001954 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1955 mehci->wakeup_irq, ret);
1956 mehci->wakeup_irq = 0;
1957 }
1958 }
1959
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301960 mehci->async_irq = platform_get_irq_byname(pdev, "async_irq");
1961 if (mehci->async_irq < 0) {
1962 dev_dbg(&pdev->dev, "platform_get_irq for async_int failed\n");
1963 mehci->async_irq = 0;
1964 } else {
1965 ret = request_irq(mehci->async_irq, msm_hsic_wakeup_irq,
1966 IRQF_TRIGGER_RISING, "msm_hsic_async", mehci);
1967 if (ret) {
1968 dev_err(&pdev->dev, "request irq failed (ASYNC INT)\n");
1969 mehci->async_irq = 0;
Manu Gautam16562792013-03-13 07:04:11 +05301970 } else if (!mehci->wakeup_irq) {
1971 /* Async IRQ is used only in absence of dedicated irq */
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301972 enable_irq_wake(mehci->async_irq);
1973 }
1974 }
1975
Hemant Kumare6275972012-02-29 20:06:21 -08001976 ret = ehci_hsic_msm_debugfs_init(mehci);
1977 if (ret)
1978 dev_dbg(&pdev->dev, "mode debugfs file is"
1979 "not available\n");
1980
1981 if (pdata && pdata->bus_scale_table) {
1982 mehci->bus_perf_client =
1983 msm_bus_scale_register_client(pdata->bus_scale_table);
1984 /* Configure BUS performance parameters for MAX bandwidth */
1985 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001986 mehci->bus_vote = true;
1987 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001988 } else {
1989 dev_err(&pdev->dev, "%s: Failed to register BUS "
1990 "scaling client!!\n", __func__);
1991 }
1992 }
1993
Hemant Kumar105d07f2012-07-02 15:33:07 -07001994 __mehci = mehci;
1995
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001996 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301997 pm_qos_add_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001998 PM_QOS_CPU_DMA_LATENCY, pdata->standalone_latency + 1);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301999
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302000 /*
2001 * This pdev->dev is assigned parent of root-hub by USB core,
2002 * hence, runtime framework automatically calls this driver's
2003 * runtime APIs based on root-hub's state.
2004 */
2005 pm_runtime_set_active(&pdev->dev);
2006 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05302007 /* Decrement the parent device's counter after probe.
2008 * As child is active, parent will not be put into
2009 * suspend mode.
2010 */
2011 if (pdev->dev.parent)
2012 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302013
2014 return 0;
2015
Ofir Cohen5dddb152012-11-14 11:18:50 +02002016destroy_wq:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002017 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302018deinit_vddcx:
2019 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02002020 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302021deinit_clocks:
2022 msm_hsic_init_clocks(mehci, 0);
2023unmap:
2024 iounmap(hcd->regs);
2025put_hcd:
2026 usb_put_hcd(hcd);
2027
2028 return ret;
2029}
2030
2031static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
2032{
2033 struct usb_hcd *hcd = platform_get_drvdata(pdev);
2034 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05302035 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
2036
Ido Shayevitz65943492013-02-20 18:55:59 +02002037 /* If the device was removed no need to call pm_runtime_disable */
2038 if (pdev->dev.power.power_state.event != PM_EVENT_INVALID)
2039 pm_runtime_disable(&pdev->dev);
2040
2041 pm_runtime_set_suspended(&pdev->dev);
2042
Pavankumar Kondeti21a840e2013-02-12 21:43:56 +05302043 /* Remove the HCD prior to releasing our resources. */
2044 usb_remove_hcd(hcd);
2045
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07002046 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05302047 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302048
Vamsi Krishna34f01582011-12-14 19:54:42 -08002049 if (mehci->peripheral_status_irq)
2050 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07002051
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002052 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07002053 if (mehci->wakeup_irq_enabled)
2054 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002055 free_irq(mehci->wakeup_irq, mehci);
2056 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08002057
Manu Gautam3fb60ca2013-02-13 18:33:33 +05302058 if (mehci->async_irq) {
2059 disable_irq_wake(mehci->async_irq);
2060 free_irq(mehci->async_irq, mehci);
2061 }
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002062 /*
2063 * If the update request is called after unregister, the request will
2064 * fail. Results are undefined if unregister is called in the middle of
2065 * update request.
2066 */
2067 mehci->bus_vote = false;
2068 cancel_work_sync(&mehci->bus_vote_w);
2069
Hemant Kumare6275972012-02-29 20:06:21 -08002070 if (mehci->bus_perf_client)
2071 msm_bus_scale_unregister_client(mehci->bus_perf_client);
2072
2073 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302074 device_init_wakeup(&pdev->dev, 0);
Ido Shayevitze50d9142013-02-17 20:43:26 +02002075
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002076 destroy_workqueue(ehci_wq);
2077
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05302078 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302079 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02002080 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302081
2082 msm_hsic_init_clocks(mehci, 0);
Sudhir Sharma1673e302012-08-27 17:37:24 -07002083 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302084 iounmap(hcd->regs);
2085 usb_put_hcd(hcd);
2086
2087 return 0;
2088}
2089
2090#ifdef CONFIG_PM_SLEEP
2091static int msm_hsic_pm_suspend(struct device *dev)
2092{
Jack Phambe05fbb2012-05-16 10:56:26 -07002093 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302094 struct usb_hcd *hcd = dev_get_drvdata(dev);
2095 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2096
2097 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
2098
Hemant Kumar45d211b2012-05-31 17:58:43 -07002099 dbg_log_event(NULL, "PM Suspend", 0);
2100
Manu Gautam16562792013-03-13 07:04:11 +05302101 if (device_may_wakeup(dev) && !mehci->async_irq)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302102 enable_irq_wake(hcd->irq);
2103
Jack Phambe05fbb2012-05-16 10:56:26 -07002104 ret = msm_hsic_suspend(mehci);
2105
Manu Gautam16562792013-03-13 07:04:11 +05302106 if (ret && device_may_wakeup(dev) && !mehci->async_irq)
Jack Phambe05fbb2012-05-16 10:56:26 -07002107 disable_irq_wake(hcd->irq);
2108
2109 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07002110}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302111
Jack Pham16b06f82012-08-14 20:03:59 -07002112static int msm_hsic_pm_suspend_noirq(struct device *dev)
2113{
2114 struct usb_hcd *hcd = dev_get_drvdata(dev);
2115 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2116
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05302117 if (atomic_read(&mehci->async_int)) {
Jack Pham16b06f82012-08-14 20:03:59 -07002118 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
2119 return -EBUSY;
2120 }
2121
2122 return 0;
2123}
2124
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302125static int msm_hsic_pm_resume(struct device *dev)
2126{
2127 int ret;
2128 struct usb_hcd *hcd = dev_get_drvdata(dev);
2129 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2130
Jack Pham16b06f82012-08-14 20:03:59 -07002131 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002132 dbg_log_event(NULL, "PM Resume", 0);
2133
Manu Gautam16562792013-03-13 07:04:11 +05302134 if (device_may_wakeup(dev) && !mehci->async_irq)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302135 disable_irq_wake(hcd->irq);
2136
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05302137 /*
2138 * Keep HSIC in Low Power Mode if system is resumed
2139 * by any other wakeup source. HSIC is resumed later
2140 * when remote wakeup is received or interface driver
2141 * start I/O.
2142 */
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05302143 if (!atomic_read(&mehci->pm_usage_cnt) &&
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05302144 !atomic_read(&mehci->async_int) &&
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05302145 pm_runtime_suspended(dev))
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05302146 return 0;
2147
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302148 ret = msm_hsic_resume(mehci);
2149 if (ret)
2150 return ret;
2151
2152 /* Bring the device to full powered state upon system resume */
2153 pm_runtime_disable(dev);
2154 pm_runtime_set_active(dev);
2155 pm_runtime_enable(dev);
2156
2157 return 0;
2158}
2159#endif
2160
2161#ifdef CONFIG_PM_RUNTIME
2162static int msm_hsic_runtime_idle(struct device *dev)
2163{
2164 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302165 return 0;
2166}
2167
2168static int msm_hsic_runtime_suspend(struct device *dev)
2169{
2170 struct usb_hcd *hcd = dev_get_drvdata(dev);
2171 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2172
2173 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002174
2175 dbg_log_event(NULL, "Run Time PM Suspend", 0);
2176
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302177 return msm_hsic_suspend(mehci);
2178}
2179
2180static int msm_hsic_runtime_resume(struct device *dev)
2181{
2182 struct usb_hcd *hcd = dev_get_drvdata(dev);
2183 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2184
2185 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002186
2187 dbg_log_event(NULL, "Run Time PM Resume", 0);
2188
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302189 return msm_hsic_resume(mehci);
2190}
2191#endif
2192
2193#ifdef CONFIG_PM
2194static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
2195 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07002196 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302197 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
2198 msm_hsic_runtime_idle)
2199};
2200#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02002201static const struct of_device_id hsic_host_dt_match[] = {
2202 { .compatible = "qcom,hsic-host",
2203 },
2204 {}
2205};
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302206static struct platform_driver ehci_msm_hsic_driver = {
2207 .probe = ehci_hsic_msm_probe,
2208 .remove = __devexit_p(ehci_hsic_msm_remove),
2209 .driver = {
2210 .name = "msm_hsic_host",
2211#ifdef CONFIG_PM
2212 .pm = &msm_hsic_dev_pm_ops,
2213#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02002214 .of_match_table = hsic_host_dt_match,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302215 },
2216};