blob: 5d58f168068a1056ed4bde369b34bc53e78e6d87 [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
Vijayavardhan Vennapusa29af4142013-08-12 13:10:07 +0530345static int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
Amit Blayd6ea6102012-06-07 16:26:24 +0300346 { /* 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;
Vijayavardhan Vennapusa29af4142013-08-12 13:10:07 +0530362 u32 tmp[3];
363 int len = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300364
365 if (!mehci->hsic_vddcx) {
366 mehci->vdd_type = VDDCX_CORNER;
367 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
368 "hsic_vdd_dig");
369 if (IS_ERR(mehci->hsic_vddcx)) {
370 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
371 "HSIC_VDDCX");
372 if (IS_ERR(mehci->hsic_vddcx)) {
373 dev_err(mehci->dev, "unable to get hsic vddcx\n");
374 return PTR_ERR(mehci->hsic_vddcx);
375 }
376 mehci->vdd_type = VDDCX;
377 }
Vijayavardhan Vennapusa29af4142013-08-12 13:10:07 +0530378
379 if (mehci->dev->of_node) {
380 of_get_property(mehci->dev->of_node,
381 "hsic,vdd-voltage-level",
382 &len);
383 if (len == sizeof(tmp)) {
384 of_property_read_u32_array(mehci->dev->of_node,
385 "hsic,vdd-voltage-level",
386 tmp, len/sizeof(*tmp));
387 vdd_val[mehci->vdd_type][VDD_NONE] = tmp[0];
388 vdd_val[mehci->vdd_type][VDD_MIN] = tmp[1];
389 vdd_val[mehci->vdd_type][VDD_MAX] = tmp[2];
390 } else {
391 dev_dbg(mehci->dev, "Use default vdd config\n");
392 }
393 }
Amit Blayd6ea6102012-06-07 16:26:24 +0300394 }
395
396 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
397 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
398 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530399
400 if (!init)
401 goto disable_reg;
402
Amit Blayd6ea6102012-06-07 16:26:24 +0300403 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530404 if (ret) {
405 dev_err(mehci->dev, "unable to set the voltage"
406 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530407 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530408 }
409
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530410 ret = regulator_enable(mehci->hsic_vddcx);
411 if (ret) {
412 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
413 goto reg_enable_err;
414 }
415
416 return 0;
417
418disable_reg:
419 regulator_disable(mehci->hsic_vddcx);
420reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300421 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
422
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530423 return ret;
424
425}
426
Ofir Cohen4cc55372012-11-20 11:17:24 +0200427/* Global Distributed Switch Controller (GDSC) init */
428static int msm_hsic_init_gdsc(struct msm_hsic_hcd *mehci, int init)
429{
430 int ret = 0;
431
432 if (IS_ERR(mehci->hsic_gdsc))
433 return 0;
434
435 if (!mehci->hsic_gdsc) {
436 mehci->hsic_gdsc = devm_regulator_get(mehci->dev,
437 "HSIC_GDSC");
438 if (IS_ERR(mehci->hsic_gdsc))
439 return 0;
440 }
441
442 if (init) {
443 ret = regulator_enable(mehci->hsic_gdsc);
444 if (ret) {
445 dev_err(mehci->dev, "unable to enable hsic gdsc\n");
446 return ret;
447 }
448 } else {
449 regulator_disable(mehci->hsic_gdsc);
450 }
451
452 return 0;
453
454}
455
Pavankumar Kondeti23720492013-01-29 14:41:58 +0530456static int __maybe_unused ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700457{
458 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700459 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700460
461 /* initiate read operation */
462 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
463 USB_ULPI_VIEWPORT);
464
465 /* wait for completion */
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700466 while (cnt < ULPI_IO_TIMEOUT_USEC) {
467 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
468 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700469 udelay(1);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700470 cnt++;
471 }
472
473 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
474 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
475 readl_relaxed(USB_ULPI_VIEWPORT));
476 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
477 readl_relaxed(USB_PORTSC),
478 readl_relaxed(USB_USBCMD),
479 readl_relaxed(USB_FRINDEX));
480
481 /*frame counter increments afte 125us*/
482 udelay(130);
483 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
484 readl_relaxed(USB_FRINDEX));
485 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700486 }
487
488 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
489}
490
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530491static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
492{
493 struct usb_hcd *hcd = hsic_to_hcd(mehci);
494 int cnt = 0;
495
496 /* initiate write operation */
497 writel_relaxed(ULPI_RUN | ULPI_WRITE |
498 ULPI_ADDR(reg) | ULPI_DATA(val),
499 USB_ULPI_VIEWPORT);
500
501 /* wait for completion */
502 while (cnt < ULPI_IO_TIMEOUT_USEC) {
503 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
504 break;
505 udelay(1);
506 cnt++;
507 }
508
509 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700510 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
511 readl_relaxed(USB_ULPI_VIEWPORT));
512 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
513 readl_relaxed(USB_PORTSC),
514 readl_relaxed(USB_USBCMD),
515 readl_relaxed(USB_FRINDEX));
516
517 /*frame counter increments afte 125us*/
518 udelay(130);
519 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
520 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530521 return -ETIMEDOUT;
522 }
523
524 return 0;
525}
526
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530527static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
528{
529 int rc = 0;
530 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800531 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530532
533 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800534
Lena Salman8c8ba382012-02-14 15:59:31 +0200535 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530536 return rc;
537
Vamsi Krishna34f01582011-12-14 19:54:42 -0800538 if (gpio_status == gpio_en)
539 return 0;
540
541 gpio_status = gpio_en;
542
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530543 if (!gpio_en)
544 goto free_gpio;
545
546 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
547 if (rc < 0) {
548 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
549 return rc;
550 }
551
552 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
553 if (rc < 0) {
554 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
555 goto free_strobe;
Hemant Kumar6fd65032012-05-23 13:02:24 -0700556 }
557
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530558 return 0;
559
560free_gpio:
561 gpio_free(pdata->data);
562free_strobe:
563 gpio_free(pdata->strobe);
564
565 return rc;
566}
567
Vamsi Krishna64b48612012-06-14 16:08:11 -0700568static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530569{
570 int ret;
571
Ofir Cohen07944aa2012-12-23 13:41:57 +0200572 /* alt_core_clk exists in targets that do not use asynchronous reset */
573 if (!IS_ERR(mehci->alt_core_clk)) {
574 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
575 if (ret) {
576 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
577 return;
578 }
579
580 /* Since a hw bug, turn off the clock before complete reset */
581 clk_disable(mehci->core_clk);
582
583 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
584 if (ret)
585 dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
586 ret);
587
588 usleep_range(10000, 12000);
589
590 clk_enable(mehci->core_clk);
591 } else {
592 /* Using asynchronous block reset to the hardware */
593 clk_disable_unprepare(mehci->core_clk);
594 clk_disable_unprepare(mehci->phy_clk);
595 clk_disable_unprepare(mehci->cal_clk);
596 clk_disable_unprepare(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +0300597 if (!IS_ERR(mehci->inactivity_clk))
598 clk_disable_unprepare(mehci->inactivity_clk);
Ofir Cohen07944aa2012-12-23 13:41:57 +0200599
600 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
601 if (ret) {
602 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
603 return;
604 }
605 usleep_range(10000, 12000);
606
607 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
608 if (ret)
609 dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
610 ret);
611 /*
612 * Required delay between the deassertion and
613 * clock enablement.
614 */
615 ndelay(200);
616 clk_prepare_enable(mehci->core_clk);
617 clk_prepare_enable(mehci->phy_clk);
618 clk_prepare_enable(mehci->cal_clk);
619 clk_prepare_enable(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +0300620 if (!IS_ERR(mehci->inactivity_clk))
621 clk_prepare_enable(mehci->inactivity_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530622 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530623}
624
Vamsi Krishna64b48612012-06-14 16:08:11 -0700625#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
626#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530627#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
628#define HSIC_LV_MODE 0x04
629#define HSIC_PAD_CALIBRATION 0xA8
630#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530631#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
Ofir Cohen5dddb152012-11-14 11:18:50 +0200632
633static void msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530634{
635 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530636
Vamsi Krishna64b48612012-06-14 16:08:11 -0700637 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530638
Vamsi Krishna64b48612012-06-14 16:08:11 -0700639 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530640 writel_relaxed(0x80000000, USB_PORTSC);
Vamsi Krishna64b48612012-06-14 16:08:11 -0700641 mb();
Ofir Cohen5dddb152012-11-14 11:18:50 +0200642}
643
644static int msm_hsic_start(struct msm_hsic_hcd *mehci)
645{
646 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
647 int ret;
Manu Gautam863b74132012-11-21 14:30:04 +0530648 void __iomem *reg;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530649
Vamsi Krishnabef91832013-03-11 14:10:20 -0700650 if (pdata && pdata->resume_gpio) {
651 ret = gpio_request(pdata->resume_gpio, "HSIC_RESUME_GPIO");
652 if (ret < 0) {
653 dev_err(mehci->dev,
654 "gpio req failed for hsic resume:%d\n", ret);
655 pdata->resume_gpio = 0;
656 }
657 }
658
Lena Salman8c8ba382012-02-14 15:59:31 +0200659 /* HSIC init sequence when HSIC signals (Strobe/Data) are
660 routed via GPIOs */
661 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530662
Manu Gautam863b74132012-11-21 14:30:04 +0530663 if (!pdata->ignore_cal_pad_config) {
664 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
665 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
666 mb();
667 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700668
Lena Salman8c8ba382012-02-14 15:59:31 +0200669 /*set periodic calibration interval to ~2.048sec in
670 HSIC_IO_CAL_REG */
671 ulpi_write(mehci, 0xFF, 0x33);
672
673 /* Enable periodic IO calibration in HSIC_CFG register */
674 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
675
Vamsi Krishna64b48612012-06-14 16:08:11 -0700676 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200677 ret = msm_hsic_config_gpios(mehci, 1);
678 if (ret) {
679 dev_err(mehci->dev, " gpio configuarion failed\n");
Vamsi Krishnabef91832013-03-11 14:10:20 -0700680 goto free_resume_gpio;
Lena Salman8c8ba382012-02-14 15:59:31 +0200681 }
Manu Gautam863b74132012-11-21 14:30:04 +0530682 if (pdata->strobe_pad_offset) {
683 /* Set CORE_CTL_EN in STROBE GPIO PAD_CTL register */
684 reg = MSM_TLMM_BASE + pdata->strobe_pad_offset;
685 writel_relaxed(readl_relaxed(reg) | 0x2000000, reg);
686 } else {
687 /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */
688 reg = HSIC_STROBE_GPIO_PAD_CTL;
689 writel_relaxed(HSIC_GPIO_PAD_VAL, reg);
690 }
691
692 if (pdata->data_pad_offset) {
693 /* Set CORE_CTL_EN in HSIC_DATA GPIO PAD_CTL register */
694 reg = MSM_TLMM_BASE + pdata->data_pad_offset;
695 writel_relaxed(readl_relaxed(reg) | 0x2000000, reg);
696 } else {
697 /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */
698 reg = HSIC_DATA_GPIO_PAD_CTL;
699 writel_relaxed(HSIC_GPIO_PAD_VAL, reg);
700 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700701
702 mb();
703
Lena Salman8c8ba382012-02-14 15:59:31 +0200704 /* Enable HSIC mode in HSIC_CFG register */
705 ulpi_write(mehci, 0x01, 0x31);
706 } else {
707 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
708 via dedicated I/O */
709
710 /* programmable length of connect signaling (33.2ns) */
711 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
712 if (ret) {
713 pr_err("%s: Unable to program length of connect "
714 "signaling\n", __func__);
715 }
716
717 /*set periodic calibration interval to ~2.048sec in
718 HSIC_IO_CAL_REG */
719 ulpi_write(mehci, 0xFF, 0x33);
720
721 /* Enable HSIC mode in HSIC_CFG register */
722 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530723 }
724
Hemant Kumar6fd65032012-05-23 13:02:24 -0700725 /*disable auto resume*/
726 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
727
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530728 return 0;
Vamsi Krishnabef91832013-03-11 14:10:20 -0700729
730free_resume_gpio:
731 if (pdata && pdata->resume_gpio)
732 gpio_free(pdata->resume_gpio);
733
734 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530735}
736
737#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
738#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
739
740#ifdef CONFIG_PM_SLEEP
Ofir Cohen5dddb152012-11-14 11:18:50 +0200741static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
742{
743 /* reset HSIC phy */
744 msm_hsic_phy_reset(mehci);
745
746 /* HSIC init procedure (caliberation) */
747 return msm_hsic_start(mehci);
748}
749
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530750static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
751{
752 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530753 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530754 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300755 int none_vol, max_vol;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700756 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530757
758 if (atomic_read(&mehci->in_lpm)) {
759 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
760 return 0;
761 }
762
763 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700764
Sudhir Sharma1673e302012-08-27 17:37:24 -0700765 /* make sure we don't race against a remote wakeup */
766 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700767 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Sudhir Sharma1673e302012-08-27 17:37:24 -0700768 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700769 enable_irq(hcd->irq);
770 return -EBUSY;
771 }
772
Ido Shayevitzaa165c52013-05-12 16:01:28 +0200773 if (pdata->consider_ipa_handshake) {
774 dev_dbg(mehci->dev, "%s:Wait for resources release\n",
775 __func__);
776 if (!msm_bam_hsic_lpm_ok()) {
777 dev_dbg(mehci->dev, "%s:Prod+Cons not released\n",
778 __func__);
779 enable_irq(hcd->irq);
780 return -EBUSY;
781 }
782 dev_dbg(mehci->dev, "%s:Prod+Cons resources released\n",
783 __func__);
784 }
785
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530786 /*
787 * PHY may take some time or even fail to enter into low power
788 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
789 * in failure case.
790 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700791 val = readl_relaxed(USB_PORTSC);
792 val &= ~PORT_RWC_BITS;
793 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530794 writel_relaxed(val, USB_PORTSC);
795 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
796 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
797 break;
798 udelay(1);
799 cnt++;
800 }
801
802 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
803 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530804 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530805 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530806 }
807
808 /*
809 * PHY has capability to generate interrupt asynchronously in low
810 * power mode (LPM). This interrupt is level triggered. So USB IRQ
811 * line must be disabled till async interrupt enable bit is cleared
812 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
Pavankumar Kondeti0c9f29c2013-01-28 21:37:59 +0530813 * block data communication from PHY. Enable asynchronous interrupt
814 * only when wakeup gpio IRQ is not present.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530815 */
Pavankumar Kondeti0c9f29c2013-01-28 21:37:59 +0530816 if (mehci->wakeup_irq)
817 writel_relaxed(readl_relaxed(USB_USBCMD) |
818 ULPI_STP_CTRL, USB_USBCMD);
819 else
820 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530821 ULPI_STP_CTRL, USB_USBCMD);
822
823 /*
824 * Ensure that hardware is put in low power mode before
825 * clocks are turned OFF and VDD is allowed to minimize.
826 */
827 mb();
828
Manu Gautam28b1bac2012-01-30 16:43:06 +0530829 clk_disable_unprepare(mehci->core_clk);
830 clk_disable_unprepare(mehci->phy_clk);
831 clk_disable_unprepare(mehci->cal_clk);
832 clk_disable_unprepare(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +0300833 if (!IS_ERR(mehci->inactivity_clk))
834 clk_disable_unprepare(mehci->inactivity_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530835
Amit Blayd6ea6102012-06-07 16:26:24 +0300836 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
837 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
838
839 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700840 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300841 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700842
Hemant Kumare6275972012-02-29 20:06:21 -0800843 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700844 mehci->bus_vote = false;
845 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800846 }
847
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530848 atomic_set(&mehci->in_lpm, 1);
849 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700850
Manu Gautam3fb60ca2013-02-13 18:33:33 +0530851 if (mehci->wakeup_irq) {
852 mehci->wakeup_irq_enabled = 1;
853 enable_irq_wake(mehci->wakeup_irq);
854 enable_irq(mehci->wakeup_irq);
855 }
Hemant Kumar6fd65032012-05-23 13:02:24 -0700856
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700857 if (pdata && pdata->standalone_latency)
858 pm_qos_update_request(&mehci->pm_qos_req_dma,
859 PM_QOS_DEFAULT_VALUE);
860
Sudhir Sharma1673e302012-08-27 17:37:24 -0700861 wake_unlock(&mehci->wlock);
862
Ido Shayevitzaa165c52013-05-12 16:01:28 +0200863 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530864
865 return 0;
866}
867
868static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
869{
870 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530871 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530872 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300873 int min_vol, max_vol;
Hemant Kumard343c012012-09-06 19:57:14 -0700874 unsigned long flags;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700875 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530876
877 if (!atomic_read(&mehci->in_lpm)) {
878 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
879 return 0;
880 }
881
Ido Shayevitzaa165c52013-05-12 16:01:28 +0200882 if (pdata->consider_ipa_handshake) {
883 dev_dbg(mehci->dev, "%s:Wait for producer resource\n",
884 __func__);
885 msm_bam_wait_for_hsic_prod_granted();
886 dev_dbg(mehci->dev, "%s:Producer resource obtained\n",
887 __func__);
888 }
889
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530890 /* Handles race with Async interrupt */
891 disable_irq(hcd->irq);
892
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700893 if (pdata && pdata->standalone_latency)
894 pm_qos_update_request(&mehci->pm_qos_req_dma,
895 pdata->standalone_latency + 1);
896
Manu Gautam3fb60ca2013-02-13 18:33:33 +0530897 if (mehci->wakeup_irq) {
898 spin_lock_irqsave(&mehci->wakeup_lock, flags);
899 if (mehci->wakeup_irq_enabled) {
900 disable_irq_wake(mehci->wakeup_irq);
901 disable_irq_nosync(mehci->wakeup_irq);
902 mehci->wakeup_irq_enabled = 0;
903 }
904 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700905 }
906
Sudhir Sharma1673e302012-08-27 17:37:24 -0700907 wake_lock(&mehci->wlock);
908
Hemant Kumare6275972012-02-29 20:06:21 -0800909 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700910 mehci->bus_vote = true;
911 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800912 }
913
Amit Blayd6ea6102012-06-07 16:26:24 +0300914 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
915 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
916
917 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700918 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300919 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700920
Manu Gautam28b1bac2012-01-30 16:43:06 +0530921 clk_prepare_enable(mehci->core_clk);
922 clk_prepare_enable(mehci->phy_clk);
923 clk_prepare_enable(mehci->cal_clk);
924 clk_prepare_enable(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +0300925 if (!IS_ERR(mehci->inactivity_clk))
926 clk_prepare_enable(mehci->inactivity_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530927
928 temp = readl_relaxed(USB_USBCMD);
929 temp &= ~ASYNC_INTR_CTRL;
930 temp &= ~ULPI_STP_CTRL;
931 writel_relaxed(temp, USB_USBCMD);
932
933 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
934 goto skip_phy_resume;
935
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700936 temp = readl_relaxed(USB_PORTSC);
937 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530938 writel_relaxed(temp, USB_PORTSC);
939 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
940 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
941 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
942 break;
943 udelay(1);
944 cnt++;
945 }
946
947 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
948 /*
949 * This is a fatal error. Reset the link and
950 * PHY to make hsic working.
951 */
952 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530953 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530954 msm_hsic_reset(mehci);
955 }
956
957skip_phy_resume:
958
Hemant Kumar6fd65032012-05-23 13:02:24 -0700959 usb_hcd_resume_root_hub(hcd);
960
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530961 atomic_set(&mehci->in_lpm, 0);
962
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530963 if (atomic_read(&mehci->async_int)) {
964 atomic_set(&mehci->async_int, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530965 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700966 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700967 }
968
Sudhir Sharma1673e302012-08-27 17:37:24 -0700969 if (atomic_read(&mehci->pm_usage_cnt)) {
970 atomic_set(&mehci->pm_usage_cnt, 0);
971 pm_runtime_put_noidle(mehci->dev);
972 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700973
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530974 enable_irq(hcd->irq);
Ido Shayevitzaa165c52013-05-12 16:01:28 +0200975 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
976
977 if (pdata->consider_ipa_handshake) {
978 dev_dbg(mehci->dev, "%s:Notify usb bam on resume complete\n",
979 __func__);
980 msm_bam_hsic_notify_on_resume();
981 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530982
983 return 0;
984}
985#endif
986
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700987static void ehci_hsic_bus_vote_w(struct work_struct *w)
988{
989 struct msm_hsic_hcd *mehci =
990 container_of(w, struct msm_hsic_hcd, bus_vote_w);
991 int ret;
992
993 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
994 mehci->bus_vote);
995 if (ret)
996 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
997 __func__, ret);
998}
999
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301000static int msm_hsic_reset_done(struct usb_hcd *hcd)
1001{
1002 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1003 u32 __iomem *status_reg = &ehci->regs->port_status[0];
1004 int ret;
1005
1006 ehci_writel(ehci, ehci_readl(ehci, status_reg) & ~(PORT_RWC_BITS |
1007 PORT_RESET), status_reg);
1008
1009 ret = handshake(ehci, status_reg, PORT_RESET, 0, 1 * 1000);
1010
1011 if (ret)
1012 pr_err("reset handshake failed in %s\n", __func__);
1013 else
1014 ehci_writel(ehci, ehci_readl(ehci, &ehci->regs->command) |
1015 CMD_RUN, &ehci->regs->command);
1016
1017 return ret;
1018}
1019
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001020#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301021static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
1022{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001023 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301024 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001025 u32 status;
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05301026 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301027
1028 if (atomic_read(&mehci->in_lpm)) {
Hemant Kumar3dbc5b32012-05-09 15:36:11 -07001029 dev_dbg(mehci->dev, "phy async intr\n");
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05301030 dbg_log_event(NULL, "Async IRQ", 0);
1031 ret = pm_runtime_get(mehci->dev);
1032 if ((ret == 1) || (ret == -EINPROGRESS)) {
1033 pm_runtime_put_noidle(mehci->dev);
1034 } else {
1035 disable_irq_nosync(hcd->irq);
1036 atomic_set(&mehci->async_int, 1);
1037 }
1038
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301039 return IRQ_HANDLED;
1040 }
1041
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001042 status = ehci_readl(ehci, &ehci->regs->status);
1043
1044 if (status & STS_GPTIMER0_INTERRUPT) {
1045 int timeleft;
1046
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301047 dbg_log_event(NULL, "FPR: gpt0_isr", mehci->bus_reset);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001048
1049 timeleft = GPT_CNT(ehci_readl(ehci,
1050 &mehci->timer->gptimer1_ctrl));
1051 if (timeleft) {
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301052 if (mehci->bus_reset) {
1053 ret = msm_hsic_reset_done(hcd);
1054 if (ret) {
1055 mehci->reset_again = 1;
1056 dbg_log_event(NULL, "RESET: fail", 0);
1057 }
1058 } else {
1059 ehci_writel(ehci, ehci_readl(ehci,
1060 &ehci->regs->command) | CMD_RUN,
1061 &ehci->regs->command);
1062 }
1063 } else {
1064 if (mehci->bus_reset)
1065 mehci->reset_again = 1;
1066 else
1067 mehci->resume_again = 1;
1068 }
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001069
1070 dbg_log_event(NULL, "FPR: timeleft", timeleft);
1071
1072 complete(&mehci->gpt0_completion);
1073 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
1074 }
1075
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301076 return ehci_irq(hcd);
1077}
1078
1079static int ehci_hsic_reset(struct usb_hcd *hcd)
1080{
1081 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001082 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Amit Blay1dfbbcc2013-05-26 17:33:13 +03001083 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301084 int retval;
1085
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001086 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301087 ehci->caps = USB_CAPLENGTH;
1088 ehci->regs = USB_CAPLENGTH +
1089 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
1090 dbg_hcs_params(ehci, "reset");
1091 dbg_hcc_params(ehci, "reset");
1092
1093 /* cache the data to minimize the chip reads*/
1094 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
1095
1096 hcd->has_tt = 1;
1097 ehci->sbrn = HCD_USB2;
1098
1099 retval = ehci_halt(ehci);
1100 if (retval)
1101 return retval;
1102
1103 /* data structure init */
1104 retval = ehci_init(hcd);
1105 if (retval)
1106 return retval;
1107
1108 retval = ehci_reset(ehci);
1109 if (retval)
1110 return retval;
1111
1112 /* bursts of unspecified length. */
1113 writel_relaxed(0, USB_AHBBURST);
Amit Blay1dfbbcc2013-05-26 17:33:13 +03001114
1115 /* Use the AHB transactor and configure async bridge bypass */
1116#define MSM_USB_ASYNC_BRIDGE_BYPASS BIT(31)
1117 if (pdata->ahb_async_bridge_bypass)
1118 writel_relaxed(0x08 | MSM_USB_ASYNC_BRIDGE_BYPASS, USB_AHBMODE);
1119 else
1120 writel_relaxed(0x08, USB_AHBMODE);
1121
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301122 /* Disable streaming mode and select host mode */
1123 writel_relaxed(0x13, USB_USBMODE);
1124
1125 ehci_port_power(ehci, 1);
1126 return 0;
1127}
1128
Jack Phamc0d41732012-09-28 17:45:38 -07001129#ifdef CONFIG_PM
1130
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301131#define RESET_RETRY_LIMIT 3
1132#define RESET_SIGNAL_TIME_SOF_USEC (50 * 1000)
1133#define RESET_SIGNAL_TIME_USEC (20 * 1000)
1134static void ehci_hsic_reset_sof_bug_handler(struct usb_hcd *hcd, u32 val)
1135{
1136 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1137 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1138 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1139 u32 __iomem *status_reg = &ehci->regs->port_status[0];
Pavankumar Kondetifc7d1d82013-03-05 09:43:22 +05301140 u32 cmd;
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301141 unsigned long flags;
1142 int retries = 0, ret, cnt = RESET_SIGNAL_TIME_USEC;
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301143 s32 next_latency = 0;
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301144
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301145 if (pdata && pdata->swfi_latency) {
1146 next_latency = pdata->swfi_latency + 1;
1147 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
1148 if (pdata->standalone_latency)
1149 next_latency = pdata->standalone_latency + 1;
1150 else
1151 next_latency = PM_QOS_DEFAULT_VALUE;
1152 }
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301153
1154 mehci->bus_reset = 1;
Pavankumar Kondetifc7d1d82013-03-05 09:43:22 +05301155
1156 /* Halt the controller */
1157 cmd = ehci_readl(ehci, &ehci->regs->command);
1158 cmd &= ~CMD_RUN;
1159 ehci_writel(ehci, cmd, &ehci->regs->command);
1160 ret = handshake(ehci, &ehci->regs->status, STS_HALT,
1161 STS_HALT, 16 * 125);
1162 if (ret) {
1163 pr_err("halt handshake fatal error\n");
1164 dbg_log_event(NULL, "HALT: fatal", 0);
1165 goto fail;
1166 }
1167
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301168retry:
1169 retries++;
1170 dbg_log_event(NULL, "RESET: start", retries);
1171 pr_debug("reset begin %d\n", retries);
1172 mehci->reset_again = 0;
1173 spin_lock_irqsave(&ehci->lock, flags);
1174 ehci_writel(ehci, val, status_reg);
1175 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_USEC - 1),
1176 &mehci->timer->gptimer0_ld);
1177 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1178 &mehci->timer->gptimer0_ctrl);
1179 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1180 &ehci->regs->intr_enable);
1181
1182 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_SOF_USEC - 1),
1183 &mehci->timer->gptimer1_ld);
1184 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1185 &mehci->timer->gptimer1_ctrl);
1186
1187 spin_unlock_irqrestore(&ehci->lock, flags);
1188 wait_for_completion(&mehci->gpt0_completion);
1189
1190 if (!mehci->reset_again)
1191 goto done;
1192
1193 if (handshake(ehci, status_reg, PORT_RESET, 0, 10 * 1000)) {
1194 pr_err("reset handshake fatal error\n");
1195 dbg_log_event(NULL, "RESET: fatal", retries);
1196 goto fail;
1197 }
1198
1199 if (retries < RESET_RETRY_LIMIT)
1200 goto retry;
1201
1202 /* complete reset in tight loop */
1203 pr_info("RESET in tight loop\n");
1204 dbg_log_event(NULL, "RESET: tight", 0);
1205
1206 spin_lock_irqsave(&ehci->lock, flags);
1207 ehci_writel(ehci, val, status_reg);
1208 while (cnt--)
1209 udelay(1);
1210 ret = msm_hsic_reset_done(hcd);
1211 spin_unlock_irqrestore(&ehci->lock, flags);
1212 if (ret) {
1213 pr_err("RESET in tight loop failed\n");
1214 dbg_log_event(NULL, "RESET: tight failed", 0);
1215 goto fail;
1216 }
1217
1218done:
1219 dbg_log_event(NULL, "RESET: done", retries);
1220 pr_debug("reset completed\n");
1221fail:
1222 mehci->bus_reset = 0;
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301223 if (next_latency)
1224 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301225}
1226
Hemant Kumar45d211b2012-05-31 17:58:43 -07001227static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
1228{
Pavankumar Kondetia723f742012-09-14 14:02:36 +05301229 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1230
1231 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
1232 dbg_log_event(NULL, "RH suspend attempt failed", 0);
1233 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
1234 __func__);
1235 return -EAGAIN;
1236 }
1237
Hemant Kumar45d211b2012-05-31 17:58:43 -07001238 dbg_log_event(NULL, "Suspend RH", 0);
1239 return ehci_bus_suspend(hcd);
1240}
1241
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001242#define RESUME_RETRY_LIMIT 3
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301243#define RESUME_SIGNAL_TIME_USEC (21 * 1000)
1244#define RESUME_SIGNAL_TIME_SOF_USEC (23 * 1000)
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001245static int msm_hsic_resume_thread(void *data)
1246{
1247 struct msm_hsic_hcd *mehci = data;
1248 struct usb_hcd *hcd = hsic_to_hcd(mehci);
1249 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1250 u32 temp;
1251 unsigned long resume_needed = 0;
1252 int retry_cnt = 0;
1253 int tight_resume = 0;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301254 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301255 s32 next_latency = 0;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001256
1257 dbg_log_event(NULL, "Resume RH", 0);
1258
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301259 if (pdata && pdata->swfi_latency) {
1260 next_latency = pdata->swfi_latency + 1;
1261 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
1262 if (pdata->standalone_latency)
1263 next_latency = pdata->standalone_latency + 1;
1264 else
1265 next_latency = PM_QOS_DEFAULT_VALUE;
1266 }
1267
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001268 /* keep delay between bus states */
1269 if (time_before(jiffies, ehci->next_statechange))
1270 usleep_range(5000, 5000);
1271
1272 spin_lock_irq(&ehci->lock);
1273 if (!HCD_HW_ACCESSIBLE(hcd)) {
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001274 mehci->resume_status = -ESHUTDOWN;
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301275 goto exit;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001276 }
1277
1278 if (unlikely(ehci->debug)) {
1279 if (!dbgp_reset_prep())
1280 ehci->debug = NULL;
1281 else
1282 dbgp_external_startup();
1283 }
1284
1285 /* at least some APM implementations will try to deliver
1286 * IRQs right away, so delay them until we're ready.
1287 */
1288 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
1289
1290 /* re-init operational registers */
1291 ehci_writel(ehci, 0, &ehci->regs->segment);
1292 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
1293 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
1294
1295 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
1296 if (ehci->resume_sof_bug)
1297 ehci->command &= ~CMD_RUN;
1298
1299 /* restore CMD_RUN, framelist size, and irq threshold */
1300 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1301
1302 /* manually resume the ports we suspended during bus_suspend() */
1303resume_again:
1304 if (retry_cnt >= RESUME_RETRY_LIMIT) {
1305 pr_info("retry count(%d) reached max, resume in tight loop\n",
1306 retry_cnt);
1307 tight_resume = 1;
1308 }
1309
1310
1311 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1312 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
1313 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
1314 temp |= PORT_RESUME;
1315 set_bit(0, &resume_needed);
1316 }
1317 dbg_log_event(NULL, "FPR: Set", temp);
1318 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1319
1320 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1321 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1322 * controller in MSM clears FPR bit after driving the resume signal for
1323 * 20ms. Workaround is to stop SOFs before driving resume and then start
1324 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1325 * completion otherwise peripheral may enter undefined state. As
1326 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1327 * to time the resume sequence. If driver exceeds allowable time SOFs,
1328 * repeat the resume process.
1329 */
1330 if (ehci->resume_sof_bug && resume_needed) {
1331 if (!tight_resume) {
1332 mehci->resume_again = 0;
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301333 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_USEC - 1),
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001334 &mehci->timer->gptimer0_ld);
1335 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1336 &mehci->timer->gptimer0_ctrl);
1337 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1338 &ehci->regs->intr_enable);
1339
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301340 ehci_writel(ehci, GPT_LD(
1341 RESUME_SIGNAL_TIME_SOF_USEC - 1),
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001342 &mehci->timer->gptimer1_ld);
1343 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1344 &mehci->timer->gptimer1_ctrl);
1345
1346 spin_unlock_irq(&ehci->lock);
1347 wait_for_completion(&mehci->gpt0_completion);
1348 spin_lock_irq(&ehci->lock);
1349 } else {
1350 dbg_log_event(NULL, "FPR: Tightloop", 0);
1351 /* do the resume in a tight loop */
1352 handshake(ehci, &ehci->regs->port_status[0],
1353 PORT_RESUME, 0, 22 * 1000);
1354 ehci_writel(ehci, ehci_readl(ehci,
1355 &ehci->regs->command) | CMD_RUN,
1356 &ehci->regs->command);
1357 }
1358
1359 if (mehci->resume_again) {
1360 int temp;
1361
1362 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1363 pr_info("FPR: retry count: %d\n", retry_cnt);
1364 spin_unlock_irq(&ehci->lock);
1365 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1366 temp &= ~PORT_RWC_BITS;
1367 temp |= PORT_SUSPEND;
1368 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1369 /* Keep the bus idle for 5ms so that peripheral
1370 * can detect and initiate suspend
1371 */
1372 usleep_range(5000, 5000);
1373 dbg_log_event(NULL,
1374 "FPR: RResume",
1375 ehci_readl(ehci, &ehci->regs->port_status[0]));
1376 spin_lock_irq(&ehci->lock);
1377 mehci->resume_again = 0;
1378 retry_cnt++;
1379 goto resume_again;
1380 }
1381 }
1382
1383 dbg_log_event(NULL, "FPR: RT-Done", 0);
1384 mehci->resume_status = 1;
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301385exit:
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001386 spin_unlock_irq(&ehci->lock);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001387 complete(&mehci->rt_completion);
Pavankumar Kondeti4152d802013-07-22 15:32:17 +05301388 if (next_latency)
1389 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001390
1391 return 0;
1392}
1393
Hemant Kumar45d211b2012-05-31 17:58:43 -07001394static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1395{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001396 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1397 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1398 u32 temp;
1399 struct task_struct *resume_thread = NULL;
Vamsi Krishnabef91832013-03-11 14:10:20 -07001400 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1401
1402 if (pdata->resume_gpio)
1403 gpio_direction_output(pdata->resume_gpio, 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001404
Manu Gautam3c598392013-03-22 16:59:10 +05301405 if (!mehci->ehci.resume_sof_bug) {
1406 ehci_bus_resume(hcd);
1407 } else {
1408 mehci->resume_status = 0;
1409 resume_thread = kthread_run(msm_hsic_resume_thread,
1410 mehci, "hsic_resume_thread");
1411 if (IS_ERR(resume_thread)) {
1412 pr_err("Error creating resume thread:%lu\n",
1413 PTR_ERR(resume_thread));
1414 return PTR_ERR(resume_thread);
1415 }
1416
1417 wait_for_completion(&mehci->rt_completion);
1418
1419 if (mehci->resume_status < 0)
1420 return mehci->resume_status;
1421
1422 dbg_log_event(NULL, "FPR: Wokeup", 0);
1423 spin_lock_irq(&ehci->lock);
1424 (void) ehci_readl(ehci, &ehci->regs->command);
1425
1426 temp = 0;
1427 if (ehci->async->qh_next.qh)
1428 temp |= CMD_ASE;
1429 if (ehci->periodic_sched)
1430 temp |= CMD_PSE;
1431 if (temp) {
1432 ehci->command |= temp;
1433 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1434 }
1435
1436 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1437 hcd->state = HC_STATE_RUNNING;
1438 ehci->rh_state = EHCI_RH_RUNNING;
1439 ehci->command |= CMD_RUN;
1440
1441 /* Now we can safely re-enable irqs */
1442 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1443
1444 spin_unlock_irq(&ehci->lock);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001445 }
1446
Vamsi Krishnabef91832013-03-11 14:10:20 -07001447 if (pdata->resume_gpio)
1448 gpio_direction_output(pdata->resume_gpio, 0);
1449
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001450 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001451}
1452
Jack Phamc0d41732012-09-28 17:45:38 -07001453#else
1454
1455#define ehci_hsic_bus_suspend NULL
1456#define ehci_hsic_bus_resume NULL
1457
1458#endif /* CONFIG_PM */
1459
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001460static void ehci_msm_set_autosuspend_delay(struct usb_device *dev)
1461{
1462 if (!dev->parent) /*for root hub no delay*/
1463 pm_runtime_set_autosuspend_delay(&dev->dev, 0);
1464 else
1465 pm_runtime_set_autosuspend_delay(&dev->dev, 200);
1466}
1467
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02001468static int ehci_msm_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
1469 gfp_t mem_flags)
1470{
1471 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1472 struct usb_host_bam_type *usb_host_bam =
1473 (struct usb_host_bam_type *)urb->priv_data;
1474
1475 if (usb_host_bam && mehci && mehci->enable_hbm)
1476 return hbm_urb_enqueue(hcd, urb, mem_flags);
1477 return ehci_urb_enqueue(hcd, urb, mem_flags);
1478}
1479
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301480static struct hc_driver msm_hsic_driver = {
1481 .description = hcd_name,
1482 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1483 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1484
1485 /*
1486 * generic hardware linkage
1487 */
1488 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001489 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301490
1491 .reset = ehci_hsic_reset,
1492 .start = ehci_run,
1493
1494 .stop = ehci_stop,
1495 .shutdown = ehci_shutdown,
1496
1497 /*
1498 * managing i/o requests and associated device resources
1499 */
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02001500 .urb_enqueue = ehci_msm_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301501 .urb_dequeue = ehci_urb_dequeue,
1502 .endpoint_disable = ehci_endpoint_disable,
1503 .endpoint_reset = ehci_endpoint_reset,
1504 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1505
1506 /*
1507 * scheduling support
1508 */
1509 .get_frame_number = ehci_get_frame,
1510
1511 /*
1512 * root hub support
1513 */
1514 .hub_status_data = ehci_hub_status_data,
1515 .hub_control = ehci_hub_control,
1516 .relinquish_port = ehci_relinquish_port,
1517 .port_handed_over = ehci_port_handed_over,
1518
1519 /*
1520 * PM support
1521 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001522 .bus_suspend = ehci_hsic_bus_suspend,
1523 .bus_resume = ehci_hsic_bus_resume,
1524
Hemant Kumar4d50a432012-08-15 09:06:35 -07001525 .log_urb = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001526 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001527
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001528 .set_autosuspend_delay = ehci_msm_set_autosuspend_delay,
Pavankumar Kondeti23720492013-01-29 14:41:58 +05301529 .reset_sof_bug_handler = ehci_hsic_reset_sof_bug_handler,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301530};
1531
1532static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1533{
1534 int ret = 0;
1535
1536 if (!init)
1537 goto put_clocks;
1538
Lena Salman8c8ba382012-02-14 15:59:31 +02001539 /*core_clk is required for LINK protocol engine
1540 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001541 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1542 if (IS_ERR(mehci->core_clk)) {
1543 dev_err(mehci->dev, "failed to get core_clk\n");
1544 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301545 return ret;
1546 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301547
Ofir Cohen07944aa2012-12-23 13:41:57 +02001548 /* alt_core_clk is for LINK to be used during PHY RESET in
1549 * targets on which link does NOT use asynchronous reset methodology.
Lena Salman8c8ba382012-02-14 15:59:31 +02001550 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001551 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
Manu Gautam863b74132012-11-21 14:30:04 +05301552 if (IS_ERR(mehci->alt_core_clk))
1553 dev_dbg(mehci->dev, "failed to get alt_core_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301554
Lena Salman8c8ba382012-02-14 15:59:31 +02001555 /* phy_clk is required for HSIC PHY operation
1556 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001557 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1558 if (IS_ERR(mehci->phy_clk)) {
1559 dev_err(mehci->dev, "failed to get phy_clk\n");
1560 ret = PTR_ERR(mehci->phy_clk);
1561 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301562 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301563
1564 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001565 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301566 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001567 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301568 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001569 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301570 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301571
1572 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001573 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301574 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001575 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301576 ret = PTR_ERR(mehci->ahb_clk);
1577 goto put_cal_clk;
1578 }
1579
Ido Shayevitz5dfbb132013-04-18 13:22:07 +03001580 /*
1581 * Inactivity_clk is required for hsic bam inactivity timer.
1582 * This clock is not compulsory and is defined in clock lookup
1583 * only for targets that need to use the inactivity timer feature.
1584 */
1585 mehci->inactivity_clk = clk_get(mehci->dev, "inactivity_clk");
1586 if (IS_ERR(mehci->inactivity_clk))
1587 dev_dbg(mehci->dev, "failed to get inactivity_clk\n");
1588
Manu Gautam28b1bac2012-01-30 16:43:06 +05301589 clk_prepare_enable(mehci->core_clk);
1590 clk_prepare_enable(mehci->phy_clk);
1591 clk_prepare_enable(mehci->cal_clk);
1592 clk_prepare_enable(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +03001593 if (!IS_ERR(mehci->inactivity_clk))
1594 clk_prepare_enable(mehci->inactivity_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301595
1596 return 0;
1597
1598put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001599 if (!atomic_read(&mehci->in_lpm)) {
1600 clk_disable_unprepare(mehci->core_clk);
1601 clk_disable_unprepare(mehci->phy_clk);
1602 clk_disable_unprepare(mehci->cal_clk);
1603 clk_disable_unprepare(mehci->ahb_clk);
Ido Shayevitz5dfbb132013-04-18 13:22:07 +03001604 if (!IS_ERR(mehci->inactivity_clk))
1605 clk_disable_unprepare(mehci->inactivity_clk);
Jack Phamfd193eb2012-02-22 15:38:08 -08001606 }
Ido Shayevitz5dfbb132013-04-18 13:22:07 +03001607 if (!IS_ERR(mehci->inactivity_clk))
1608 clk_put(mehci->inactivity_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301609 clk_put(mehci->ahb_clk);
1610put_cal_clk:
1611 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001612put_phy_clk:
1613 clk_put(mehci->phy_clk);
1614put_alt_core_clk:
Manu Gautam863b74132012-11-21 14:30:04 +05301615 if (!IS_ERR(mehci->alt_core_clk))
1616 clk_put(mehci->alt_core_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001617 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301618
1619 return ret;
1620}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001621static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1622{
1623 struct msm_hsic_hcd *mehci = dev_id;
1624
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001625 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001626
1627 if (mehci)
1628 msm_hsic_config_gpios(mehci, 0);
1629
1630 return IRQ_HANDLED;
1631}
1632
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001633static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1634{
1635 struct msm_hsic_hcd *mehci = data;
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301636 int ret;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001637
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301638 if (irq == mehci->async_irq) {
1639 mehci->async_int_cnt++;
1640 dbg_log_event(NULL, "Remote Wakeup (ASYNC) IRQ",
1641 mehci->async_int_cnt);
1642 } else {
1643 mehci->wakeup_int_cnt++;
1644 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
1645 }
1646 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt %d cnt: %u, %u\n",
1647 __func__, irq, mehci->wakeup_int_cnt, mehci->async_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001648
Sudhir Sharma1673e302012-08-27 17:37:24 -07001649 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001650
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301651 if (mehci->wakeup_irq) {
1652 spin_lock(&mehci->wakeup_lock);
1653 if (mehci->wakeup_irq_enabled) {
1654 mehci->wakeup_irq_enabled = 0;
1655 disable_irq_wake(irq);
1656 disable_irq_nosync(irq);
1657 }
1658 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001659 }
1660
Sudhir Sharma1673e302012-08-27 17:37:24 -07001661 if (!atomic_read(&mehci->pm_usage_cnt)) {
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301662 ret = pm_runtime_get(mehci->dev);
1663 /*
1664 * HSIC runtime resume can race with us.
1665 * if we are active (ret == 1) or resuming
1666 * (ret == -EINPROGRESS), decrement the
1667 * PM usage counter before returning.
1668 */
1669 if ((ret == 1) || (ret == -EINPROGRESS))
1670 pm_runtime_put_noidle(mehci->dev);
1671 else
1672 atomic_set(&mehci->pm_usage_cnt, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001673 }
1674
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001675 return IRQ_HANDLED;
1676}
1677
Hemant Kumare6275972012-02-29 20:06:21 -08001678static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1679{
1680 if (debug_bus_voting_enabled)
1681 seq_printf(s, "enabled\n");
1682 else
1683 seq_printf(s, "disabled\n");
1684
1685 return 0;
1686}
1687
1688static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1689{
1690 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1691}
1692
1693static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1694 const char __user *ubuf, size_t count, loff_t *ppos)
1695{
1696 char buf[8];
1697 int ret;
1698 struct seq_file *s = file->private_data;
1699 struct msm_hsic_hcd *mehci = s->private;
1700
1701 memset(buf, 0x00, sizeof(buf));
1702
1703 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1704 return -EFAULT;
1705
1706 if (!strncmp(buf, "enable", 6)) {
1707 /* Do not vote here. Let hsic driver decide when to vote */
1708 debug_bus_voting_enabled = true;
1709 } else {
1710 debug_bus_voting_enabled = false;
1711 if (mehci->bus_perf_client) {
1712 ret = msm_bus_scale_client_update_request(
1713 mehci->bus_perf_client, 0);
1714 if (ret)
1715 dev_err(mehci->dev, "%s: Failed to devote "
1716 "for bus bw %d\n", __func__, ret);
1717 }
1718 }
1719
1720 return count;
1721}
1722
1723const struct file_operations ehci_hsic_msm_bus_fops = {
1724 .open = ehci_hsic_msm_bus_open,
1725 .read = seq_read,
1726 .write = ehci_hsic_msm_bus_write,
1727 .llseek = seq_lseek,
1728 .release = single_release,
1729};
1730
Hemant Kumar6fd65032012-05-23 13:02:24 -07001731static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1732{
1733 struct msm_hsic_hcd *mehci = s->private;
1734
1735 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1736
1737 return 0;
1738}
1739
1740static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1741{
1742 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1743}
1744
1745const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1746 .open = ehci_hsic_msm_wakeup_cnt_open,
1747 .read = seq_read,
1748 .llseek = seq_lseek,
1749 .release = single_release,
1750};
1751
Hemant Kumar45d211b2012-05-31 17:58:43 -07001752static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1753{
1754 unsigned long flags;
1755 unsigned i;
1756
1757 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1758
1759 i = dbg_hsic_data.idx;
1760 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1761 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1762 continue;
1763 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1764 }
1765
1766 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1767
1768 return 0;
1769}
1770
1771static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1772{
1773 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1774}
1775
1776const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1777 .open = ehci_hsic_msm_data_events_open,
1778 .read = seq_read,
1779 .llseek = seq_lseek,
1780 .release = single_release,
1781};
1782
1783static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1784{
1785 unsigned long flags;
1786 unsigned i;
1787
1788 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1789
1790 i = dbg_hsic_ctrl.idx;
1791 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1792 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1793 continue;
1794 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1795 }
1796
1797 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1798
1799 return 0;
1800}
1801
1802static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1803{
1804 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1805}
1806
1807const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1808 .open = ehci_hsic_msm_ctrl_events_open,
1809 .read = seq_read,
1810 .llseek = seq_lseek,
1811 .release = single_release,
1812};
1813
Hemant Kumare6275972012-02-29 20:06:21 -08001814static struct dentry *ehci_hsic_msm_dbg_root;
1815static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1816{
1817 struct dentry *ehci_hsic_msm_dentry;
1818
1819 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1820
1821 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1822 return -ENODEV;
1823
1824 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1825 S_IRUGO | S_IWUSR,
1826 ehci_hsic_msm_dbg_root, mehci,
1827 &ehci_hsic_msm_bus_fops);
1828
1829 if (!ehci_hsic_msm_dentry) {
1830 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1831 return -ENODEV;
1832 }
1833
Hemant Kumar6fd65032012-05-23 13:02:24 -07001834 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1835 S_IRUGO,
1836 ehci_hsic_msm_dbg_root, mehci,
1837 &ehci_hsic_msm_wakeup_cnt_fops);
1838
1839 if (!ehci_hsic_msm_dentry) {
1840 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1841 return -ENODEV;
1842 }
1843
Hemant Kumar45d211b2012-05-31 17:58:43 -07001844 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1845 S_IRUGO,
1846 ehci_hsic_msm_dbg_root, mehci,
1847 &ehci_hsic_msm_dbg_ctrl_fops);
1848
1849 if (!ehci_hsic_msm_dentry) {
1850 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1851 return -ENODEV;
1852 }
1853
1854 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1855 S_IRUGO,
1856 ehci_hsic_msm_dbg_root, mehci,
1857 &ehci_hsic_msm_dbg_data_fops);
1858
1859 if (!ehci_hsic_msm_dentry) {
1860 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1861 return -ENODEV;
1862 }
1863
Hemant Kumare6275972012-02-29 20:06:21 -08001864 return 0;
1865}
1866
1867static void ehci_hsic_msm_debugfs_cleanup(void)
1868{
1869 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1870}
1871
Manu Gautam863b74132012-11-21 14:30:04 +05301872struct msm_hsic_host_platform_data *msm_hsic_dt_to_pdata(
1873 struct platform_device *pdev)
1874{
1875 struct device_node *node = pdev->dev.of_node;
1876 struct msm_hsic_host_platform_data *pdata;
Ido Shayevitzca5dc492013-01-09 14:49:59 +02001877 int res_gpio;
Manu Gautam863b74132012-11-21 14:30:04 +05301878
1879 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1880 if (!pdata) {
1881 dev_err(&pdev->dev, "unable to allocate platform data\n");
1882 return NULL;
1883 }
Manu Gautam863b74132012-11-21 14:30:04 +05301884
Ido Shayevitzca5dc492013-01-09 14:49:59 +02001885 res_gpio = of_get_named_gpio(node, "hsic,strobe-gpio", 0);
1886 if (res_gpio < 0)
1887 res_gpio = 0;
1888 pdata->strobe = res_gpio;
1889
1890 res_gpio = of_get_named_gpio(node, "hsic,data-gpio", 0);
1891 if (res_gpio < 0)
1892 res_gpio = 0;
1893 pdata->data = res_gpio;
Manu Gautam863b74132012-11-21 14:30:04 +05301894
Vamsi Krishnabef91832013-03-11 14:10:20 -07001895 res_gpio = of_get_named_gpio(node, "hsic,resume-gpio", 0);
1896 if (res_gpio < 0)
1897 res_gpio = 0;
1898 pdata->resume_gpio = res_gpio;
1899
Manu Gautam3c598392013-03-22 16:59:10 +05301900 pdata->phy_sof_workaround = of_property_read_bool(node,
1901 "qcom,phy-sof-workaround");
Manu Gautamcaa99d42013-07-25 12:01:02 +05301902 pdata->phy_susp_sof_workaround = of_property_read_bool(node,
1903 "qcom,phy-susp-sof-workaround");
Manu Gautam863b74132012-11-21 14:30:04 +05301904 pdata->ignore_cal_pad_config = of_property_read_bool(node,
1905 "hsic,ignore-cal-pad-config");
1906 of_property_read_u32(node, "hsic,strobe-pad-offset",
1907 &pdata->strobe_pad_offset);
1908 of_property_read_u32(node, "hsic,data-pad-offset",
1909 &pdata->data_pad_offset);
Ming-yi Lin9eed5e02013-07-18 14:06:24 +08001910 of_property_read_u32(node, "hsic,reset-delay",
1911 &pdata->reset_delay);
Vamsi Krishnafaee5da2013-06-14 12:41:10 -07001912 of_property_read_u32(node, "hsic,log2-itc",
1913 &pdata->log2_irq_thresh);
1914 if (pdata->log2_irq_thresh > 6)
1915 pdata->log2_irq_thresh = 0;
Manu Gautam863b74132012-11-21 14:30:04 +05301916
Ido Shayevitz95c46882013-01-20 13:47:46 +02001917 pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
1918
Shimrit Malichi36a0c852013-03-10 11:39:10 +02001919 pdata->pool_64_bit_align = of_property_read_bool(node,
1920 "qcom,pool-64-bit-align");
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02001921 pdata->enable_hbm = of_property_read_bool(node,
1922 "qcom,enable-hbm");
Shimrit Malichi08f07342013-04-24 13:09:12 +03001923 pdata->disable_park_mode = (of_property_read_bool(node,
1924 "qcom,disable-park-mode"));
Ido Shayevitzaa165c52013-05-12 16:01:28 +02001925 pdata->consider_ipa_handshake = (of_property_read_bool(node,
1926 "hsic,consider-ipa-handshake"));
Amit Blay1dfbbcc2013-05-26 17:33:13 +03001927 pdata->ahb_async_bridge_bypass = of_property_read_bool(node,
1928 "qcom,ahb-async-bridge-bypass");
Vamsi Krishna4f66c2c2013-06-21 11:33:59 -07001929 pdata->disable_cerr = of_property_read_bool(node,
1930 "hsic,disable-cerr");
Shimrit Malichi36a0c852013-03-10 11:39:10 +02001931
Manu Gautam863b74132012-11-21 14:30:04 +05301932 return pdata;
1933}
1934
1935
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301936static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1937{
1938 struct usb_hcd *hcd;
1939 struct resource *res;
1940 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301941 struct msm_hsic_host_platform_data *pdata;
Manu Gautam16562792013-03-13 07:04:11 +05301942 unsigned long wakeup_irq_flags = 0;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301943 int ret;
1944
1945 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1946
Manu Gautam863b74132012-11-21 14:30:04 +05301947 if (pdev->dev.of_node) {
1948 dev_dbg(&pdev->dev, "device tree enabled\n");
1949 pdev->dev.platform_data = msm_hsic_dt_to_pdata(pdev);
1950 dev_set_name(&pdev->dev, ehci_msm_hsic_driver.driver.name);
Manu Gautam16562792013-03-13 07:04:11 +05301951 } else {
1952 /* explicitly pass wakeup_irq flag for !DT */
1953 wakeup_irq_flags = IRQF_TRIGGER_HIGH;
Manu Gautam863b74132012-11-21 14:30:04 +05301954 }
1955 if (!pdev->dev.platform_data)
1956 dev_dbg(&pdev->dev, "No platform data given\n");
1957
Ofir Cohen4cc55372012-11-20 11:17:24 +02001958 if (!pdev->dev.dma_mask)
1959 pdev->dev.dma_mask = &ehci_msm_hsic_dma_mask;
1960 if (!pdev->dev.coherent_dma_mask)
1961 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
1962
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301963 /* After parent device's probe is executed, it will be put in suspend
1964 * mode. When child device's probe is called, driver core is not
1965 * resuming parent device due to which parent will be in suspend even
1966 * though child is active. Hence resume the parent device explicitly.
1967 */
1968 if (pdev->dev.parent)
1969 pm_runtime_get_sync(pdev->dev.parent);
1970
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301971 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1972 dev_name(&pdev->dev));
1973 if (!hcd) {
1974 dev_err(&pdev->dev, "Unable to create HCD\n");
1975 return -ENOMEM;
1976 }
1977
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301978 hcd_to_bus(hcd)->skip_resume = true;
1979
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301980 hcd->irq = platform_get_irq(pdev, 0);
1981 if (hcd->irq < 0) {
1982 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1983 ret = hcd->irq;
1984 goto put_hcd;
1985 }
1986
1987 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1988 if (!res) {
1989 dev_err(&pdev->dev, "Unable to get memory resource\n");
1990 ret = -ENODEV;
1991 goto put_hcd;
1992 }
1993
1994 hcd->rsrc_start = res->start;
1995 hcd->rsrc_len = resource_size(res);
1996 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1997 if (!hcd->regs) {
1998 dev_err(&pdev->dev, "ioremap failed\n");
1999 ret = -ENOMEM;
2000 goto put_hcd;
2001 }
2002
2003 mehci = hcd_to_hsic(hcd);
2004 mehci->dev = &pdev->dev;
Hemant Kumar30d361c2012-08-20 14:44:40 -07002005 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302006
Hemant Kumard343c012012-09-06 19:57:14 -07002007 spin_lock_init(&mehci->wakeup_lock);
2008
Manu Gautam3c598392013-03-22 16:59:10 +05302009 if (pdata->phy_sof_workaround) {
Manu Gautamcaa99d42013-07-25 12:01:02 +05302010 /* Enable ALL workarounds related to PHY SOF bugs */
Manu Gautam3c598392013-03-22 16:59:10 +05302011 mehci->ehci.susp_sof_bug = 1;
2012 mehci->ehci.reset_sof_bug = 1;
2013 mehci->ehci.resume_sof_bug = 1;
Manu Gautamcaa99d42013-07-25 12:01:02 +05302014 } else if (pdata->phy_susp_sof_workaround) {
2015 /* Only SUSP SOF hardware bug exists, rest all not present */
2016 mehci->ehci.susp_sof_bug = 1;
Manu Gautam3c598392013-03-22 16:59:10 +05302017 }
Hemant Kumar38ce5d82012-05-29 13:00:58 -07002018
Ming-yi Lin9eed5e02013-07-18 14:06:24 +08002019 if (pdata->reset_delay)
2020 mehci->ehci.reset_delay = pdata->reset_delay;
2021
Shimrit Malichi36a0c852013-03-10 11:39:10 +02002022 mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02002023 mehci->enable_hbm = pdata->enable_hbm;
Hemant Kumare4040492012-06-21 17:35:42 -07002024
Vamsi Krishna4f66c2c2013-06-21 11:33:59 -07002025 if (pdata) {
Hemant Kumar30d361c2012-08-20 14:44:40 -07002026 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Vamsi Krishna4f66c2c2013-06-21 11:33:59 -07002027 mehci->ehci.disable_cerr = pdata->disable_cerr;
2028 }
Hemant Kumar933e0402012-05-22 11:11:40 -07002029
Ofir Cohen4cc55372012-11-20 11:17:24 +02002030 ret = msm_hsic_init_gdsc(mehci, 1);
2031 if (ret) {
2032 dev_err(&pdev->dev, "unable to initialize GDSC\n");
2033 ret = -ENODEV;
2034 goto put_hcd;
2035 }
2036
Vamsi Krishna34f01582011-12-14 19:54:42 -08002037 res = platform_get_resource_byname(pdev,
2038 IORESOURCE_IRQ,
2039 "peripheral_status_irq");
2040 if (res)
2041 mehci->peripheral_status_irq = res->start;
2042
Jack Pham0cc75c42012-10-10 02:03:50 +02002043 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "wakeup");
Hemant Kumar6fd65032012-05-23 13:02:24 -07002044 if (res) {
Jack Pham0cc75c42012-10-10 02:03:50 +02002045 mehci->wakeup_irq = res->start;
Hemant Kumar6fd65032012-05-23 13:02:24 -07002046 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
2047 }
2048
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302049 ret = msm_hsic_init_clocks(mehci, 1);
2050 if (ret) {
2051 dev_err(&pdev->dev, "unable to initialize clocks\n");
2052 ret = -ENODEV;
2053 goto unmap;
2054 }
2055
2056 ret = msm_hsic_init_vddcx(mehci, 1);
2057 if (ret) {
2058 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
2059 ret = -ENODEV;
2060 goto deinit_clocks;
2061 }
2062
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07002063 init_completion(&mehci->rt_completion);
2064 init_completion(&mehci->gpt0_completion);
Ofir Cohen5dddb152012-11-14 11:18:50 +02002065
2066 msm_hsic_phy_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302067
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002068 ehci_wq = create_singlethread_workqueue("ehci_wq");
2069 if (!ehci_wq) {
2070 dev_err(&pdev->dev, "unable to create workqueue\n");
2071 ret = -ENOMEM;
2072 goto deinit_vddcx;
2073 }
2074
2075 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
2076
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302077 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
2078 if (ret) {
2079 dev_err(&pdev->dev, "unable to register HCD\n");
Ofir Cohen5dddb152012-11-14 11:18:50 +02002080 goto destroy_wq;
2081 }
2082
2083 ret = msm_hsic_start(mehci);
2084 if (ret) {
2085 dev_err(&pdev->dev, "unable to initialize PHY\n");
2086 goto destroy_wq;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302087 }
2088
2089 device_init_wakeup(&pdev->dev, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07002090 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
2091 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08002092
2093 if (mehci->peripheral_status_irq) {
2094 ret = request_threaded_irq(mehci->peripheral_status_irq,
2095 NULL, hsic_peripheral_status_change,
2096 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
2097 | IRQF_SHARED,
2098 "hsic_peripheral_status", mehci);
2099 if (ret)
2100 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
2101 __func__, mehci->peripheral_status_irq, ret);
2102 }
2103
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002104 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07002105 if (mehci->wakeup_irq) {
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07002106 /* In case if wakeup gpio is pulled high at this point
2107 * remote wakeup interrupt fires right after request_irq.
2108 * Remote wake up interrupt only needs to be enabled when
2109 * HSIC bus goes to suspend.
2110 */
2111 irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002112 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Manu Gautam16562792013-03-13 07:04:11 +05302113 wakeup_irq_flags,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002114 "msm_hsic_wakeup", mehci);
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07002115 if (ret) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002116 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
2117 mehci->wakeup_irq, ret);
2118 mehci->wakeup_irq = 0;
2119 }
2120 }
2121
Manu Gautam3fb60ca2013-02-13 18:33:33 +05302122 mehci->async_irq = platform_get_irq_byname(pdev, "async_irq");
2123 if (mehci->async_irq < 0) {
2124 dev_dbg(&pdev->dev, "platform_get_irq for async_int failed\n");
2125 mehci->async_irq = 0;
2126 } else {
2127 ret = request_irq(mehci->async_irq, msm_hsic_wakeup_irq,
2128 IRQF_TRIGGER_RISING, "msm_hsic_async", mehci);
2129 if (ret) {
2130 dev_err(&pdev->dev, "request irq failed (ASYNC INT)\n");
2131 mehci->async_irq = 0;
Manu Gautam16562792013-03-13 07:04:11 +05302132 } else if (!mehci->wakeup_irq) {
2133 /* Async IRQ is used only in absence of dedicated irq */
Manu Gautam3fb60ca2013-02-13 18:33:33 +05302134 enable_irq_wake(mehci->async_irq);
2135 }
2136 }
2137
Hemant Kumare6275972012-02-29 20:06:21 -08002138 ret = ehci_hsic_msm_debugfs_init(mehci);
2139 if (ret)
2140 dev_dbg(&pdev->dev, "mode debugfs file is"
2141 "not available\n");
2142
2143 if (pdata && pdata->bus_scale_table) {
2144 mehci->bus_perf_client =
2145 msm_bus_scale_register_client(pdata->bus_scale_table);
2146 /* Configure BUS performance parameters for MAX bandwidth */
2147 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002148 mehci->bus_vote = true;
2149 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08002150 } else {
2151 dev_err(&pdev->dev, "%s: Failed to register BUS "
2152 "scaling client!!\n", __func__);
2153 }
2154 }
2155
Hemant Kumar105d07f2012-07-02 15:33:07 -07002156 __mehci = mehci;
2157
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07002158 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05302159 pm_qos_add_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07002160 PM_QOS_CPU_DMA_LATENCY, pdata->standalone_latency + 1);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05302161
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302162 /*
2163 * This pdev->dev is assigned parent of root-hub by USB core,
2164 * hence, runtime framework automatically calls this driver's
2165 * runtime APIs based on root-hub's state.
2166 */
2167 pm_runtime_set_active(&pdev->dev);
2168 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05302169 /* Decrement the parent device's counter after probe.
2170 * As child is active, parent will not be put into
2171 * suspend mode.
2172 */
2173 if (pdev->dev.parent)
2174 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302175
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02002176 if (mehci->enable_hbm)
Shimrit Malichi08f07342013-04-24 13:09:12 +03002177 hbm_init(hcd, pdata->disable_park_mode);
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02002178
Jack Pham06306d52013-06-06 15:28:13 -07002179 if (pdata && pdata->consider_ipa_handshake)
2180 msm_bam_set_hsic_host_dev(&pdev->dev);
Ido Shayevitzaa165c52013-05-12 16:01:28 +02002181
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302182 return 0;
2183
Ofir Cohen5dddb152012-11-14 11:18:50 +02002184destroy_wq:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002185 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302186deinit_vddcx:
2187 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02002188 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302189deinit_clocks:
2190 msm_hsic_init_clocks(mehci, 0);
2191unmap:
2192 iounmap(hcd->regs);
2193put_hcd:
2194 usb_put_hcd(hcd);
2195
2196 return ret;
2197}
2198
2199static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
2200{
2201 struct usb_hcd *hcd = platform_get_drvdata(pdev);
2202 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05302203 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
2204
Jack Pham06306d52013-06-06 15:28:13 -07002205 if (pdata && pdata->consider_ipa_handshake)
2206 msm_bam_set_hsic_host_dev(NULL);
Ido Shayevitzaa165c52013-05-12 16:01:28 +02002207
Ido Shayevitz65943492013-02-20 18:55:59 +02002208 /* If the device was removed no need to call pm_runtime_disable */
2209 if (pdev->dev.power.power_state.event != PM_EVENT_INVALID)
2210 pm_runtime_disable(&pdev->dev);
2211
2212 pm_runtime_set_suspended(&pdev->dev);
2213
Shimrit Malichi82d7cbc2013-03-12 15:36:54 +02002214 if (mehci->enable_hbm)
2215 hbm_uninit();
2216
Pavankumar Kondeti21a840e2013-02-12 21:43:56 +05302217 /* Remove the HCD prior to releasing our resources. */
2218 usb_remove_hcd(hcd);
2219
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07002220 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05302221 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302222
Vamsi Krishna34f01582011-12-14 19:54:42 -08002223 if (mehci->peripheral_status_irq)
2224 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07002225
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002226 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07002227 if (mehci->wakeup_irq_enabled)
2228 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08002229 free_irq(mehci->wakeup_irq, mehci);
2230 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08002231
Manu Gautam3fb60ca2013-02-13 18:33:33 +05302232 if (mehci->async_irq) {
Manu Gautam1a1a9c62013-03-19 17:37:11 +05302233 /* Async IRQ is used only in absence of dedicated wakeup irq */
2234 if (!mehci->wakeup_irq)
2235 disable_irq_wake(mehci->async_irq);
Manu Gautam3fb60ca2013-02-13 18:33:33 +05302236 free_irq(mehci->async_irq, mehci);
2237 }
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002238 /*
2239 * If the update request is called after unregister, the request will
2240 * fail. Results are undefined if unregister is called in the middle of
2241 * update request.
2242 */
2243 mehci->bus_vote = false;
2244 cancel_work_sync(&mehci->bus_vote_w);
2245
Hemant Kumare6275972012-02-29 20:06:21 -08002246 if (mehci->bus_perf_client)
2247 msm_bus_scale_unregister_client(mehci->bus_perf_client);
2248
2249 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302250 device_init_wakeup(&pdev->dev, 0);
Ido Shayevitze50d9142013-02-17 20:43:26 +02002251
Hemant Kumar2309eaa2012-08-14 16:46:42 -07002252 destroy_workqueue(ehci_wq);
2253
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05302254 msm_hsic_config_gpios(mehci, 0);
Vamsi Krishnabef91832013-03-11 14:10:20 -07002255
2256 if (pdata && pdata->resume_gpio)
2257 gpio_free(pdata->resume_gpio);
2258
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302259 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02002260 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302261
2262 msm_hsic_init_clocks(mehci, 0);
Sudhir Sharma1673e302012-08-27 17:37:24 -07002263 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302264 iounmap(hcd->regs);
2265 usb_put_hcd(hcd);
2266
2267 return 0;
2268}
2269
2270#ifdef CONFIG_PM_SLEEP
2271static int msm_hsic_pm_suspend(struct device *dev)
2272{
2273 struct usb_hcd *hcd = dev_get_drvdata(dev);
2274 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2275
2276 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
2277
Hemant Kumar45d211b2012-05-31 17:58:43 -07002278 dbg_log_event(NULL, "PM Suspend", 0);
2279
Pavankumar Kondeti1081f3e2013-04-25 13:51:24 +05302280 if (!atomic_read(&mehci->in_lpm)) {
2281 dev_info(dev, "abort suspend\n");
2282 dbg_log_event(NULL, "PM Suspend abort", 0);
2283 return -EBUSY;
2284 }
2285
Manu Gautam16562792013-03-13 07:04:11 +05302286 if (device_may_wakeup(dev) && !mehci->async_irq)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302287 enable_irq_wake(hcd->irq);
2288
Pavankumar Kondeti1081f3e2013-04-25 13:51:24 +05302289 return 0;
Jack Phamfe441ea2012-03-23 17:03:15 -07002290}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302291
Jack Pham16b06f82012-08-14 20:03:59 -07002292static int msm_hsic_pm_suspend_noirq(struct device *dev)
2293{
2294 struct usb_hcd *hcd = dev_get_drvdata(dev);
2295 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2296
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05302297 if (atomic_read(&mehci->async_int)) {
Jack Pham16b06f82012-08-14 20:03:59 -07002298 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
2299 return -EBUSY;
2300 }
2301
2302 return 0;
2303}
2304
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302305static int msm_hsic_pm_resume(struct device *dev)
2306{
2307 int ret;
2308 struct usb_hcd *hcd = dev_get_drvdata(dev);
2309 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2310
Jack Pham16b06f82012-08-14 20:03:59 -07002311 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002312 dbg_log_event(NULL, "PM Resume", 0);
2313
Manu Gautam16562792013-03-13 07:04:11 +05302314 if (device_may_wakeup(dev) && !mehci->async_irq)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302315 disable_irq_wake(hcd->irq);
2316
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05302317 /*
2318 * Keep HSIC in Low Power Mode if system is resumed
2319 * by any other wakeup source. HSIC is resumed later
2320 * when remote wakeup is received or interface driver
2321 * start I/O.
2322 */
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05302323 if (!atomic_read(&mehci->pm_usage_cnt) &&
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05302324 !atomic_read(&mehci->async_int) &&
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05302325 pm_runtime_suspended(dev))
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05302326 return 0;
2327
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302328 ret = msm_hsic_resume(mehci);
2329 if (ret)
2330 return ret;
2331
2332 /* Bring the device to full powered state upon system resume */
2333 pm_runtime_disable(dev);
2334 pm_runtime_set_active(dev);
2335 pm_runtime_enable(dev);
2336
2337 return 0;
2338}
2339#endif
2340
2341#ifdef CONFIG_PM_RUNTIME
2342static int msm_hsic_runtime_idle(struct device *dev)
2343{
2344 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302345 return 0;
2346}
2347
2348static int msm_hsic_runtime_suspend(struct device *dev)
2349{
2350 struct usb_hcd *hcd = dev_get_drvdata(dev);
2351 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2352
2353 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002354
2355 dbg_log_event(NULL, "Run Time PM Suspend", 0);
2356
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302357 return msm_hsic_suspend(mehci);
2358}
2359
2360static int msm_hsic_runtime_resume(struct device *dev)
2361{
2362 struct usb_hcd *hcd = dev_get_drvdata(dev);
2363 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2364
2365 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002366
2367 dbg_log_event(NULL, "Run Time PM Resume", 0);
2368
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302369 return msm_hsic_resume(mehci);
2370}
2371#endif
2372
2373#ifdef CONFIG_PM
2374static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
2375 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07002376 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302377 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
2378 msm_hsic_runtime_idle)
2379};
2380#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02002381static const struct of_device_id hsic_host_dt_match[] = {
2382 { .compatible = "qcom,hsic-host",
2383 },
2384 {}
2385};
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302386static struct platform_driver ehci_msm_hsic_driver = {
2387 .probe = ehci_hsic_msm_probe,
2388 .remove = __devexit_p(ehci_hsic_msm_remove),
2389 .driver = {
2390 .name = "msm_hsic_host",
2391#ifdef CONFIG_PM
2392 .pm = &msm_hsic_dev_pm_ops,
2393#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02002394 .of_match_table = hsic_host_dt_match,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302395 },
2396};