blob: d06b21b998b2c7cec3b8d856f55101e89b334807 [file] [log] [blame]
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301/* ehci-msm-hsic.c - HSUSB Host Controller Driver Implementation
2 *
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05303 * Copyright (c) 2011-2013, Linux Foundation. All rights reserved.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05304 *
5 * Partly derived from ehci-fsl.c and ehci-hcd.c
6 * Copyright (c) 2000-2004 by David Brownell
7 * Copyright (c) 2005 MontaVista Software
8 *
9 * All source code in this file is licensed under the following license except
10 * where indicated.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published
14 * by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * See the GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, you can find it at http://www.fsf.org
23 */
24
25#include <linux/platform_device.h>
26#include <linux/clk.h>
27#include <linux/err.h>
Hemant Kumare6275972012-02-29 20:06:21 -080028#include <linux/debugfs.h>
29#include <linux/seq_file.h>
Sudhir Sharma1673e302012-08-27 17:37:24 -070030#include <linux/wakelock.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053031#include <linux/pm_runtime.h>
32#include <linux/regulator/consumer.h>
33
Manu Gautam863b74132012-11-21 14:30:04 +053034#include <linux/usb/ulpi.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053035#include <linux/usb/msm_hsusb_hw.h>
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +053036#include <linux/usb/msm_hsusb.h>
37#include <linux/gpio.h>
Manu Gautam863b74132012-11-21 14:30:04 +053038#include <linux/of_gpio.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030039#include <linux/spinlock.h>
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -070040#include <linux/irq.h>
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070041#include <linux/kthread.h>
42#include <linux/wait.h>
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +053043#include <linux/pm_qos.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030044
45#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053046#include <mach/clk.h>
47#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053048#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080049#include <linux/spinlock.h>
Hemant Kumar45d211b2012-05-31 17:58:43 -070050#include <linux/cpu.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030051#include <mach/rpm-regulator.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053052
53#define MSM_USB_BASE (hcd->regs)
Hemant Kumar105d07f2012-07-02 15:33:07 -070054#define USB_REG_START_OFFSET 0x90
55#define USB_REG_END_OFFSET 0x250
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053056
Hemant Kumar2309eaa2012-08-14 16:46:42 -070057static struct workqueue_struct *ehci_wq;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070058struct ehci_timer {
59#define GPT_LD(p) ((p) & 0x00FFFFFF)
60 u32 gptimer0_ld;
61#define GPT_RUN BIT(31)
62#define GPT_RESET BIT(30)
63#define GPT_MODE BIT(24)
64#define GPT_CNT(p) ((p) & 0x00FFFFFF)
65 u32 gptimer0_ctrl;
66
67 u32 gptimer1_ld;
68 u32 gptimer1_ctrl;
69};
Hemant Kumar2309eaa2012-08-14 16:46:42 -070070
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053071struct msm_hsic_hcd {
72 struct ehci_hcd ehci;
Hemant Kumard343c012012-09-06 19:57:14 -070073 spinlock_t wakeup_lock;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053074 struct device *dev;
75 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080076 struct clk *core_clk;
77 struct clk *alt_core_clk;
78 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053079 struct clk *cal_clk;
80 struct regulator *hsic_vddcx;
Ofir Cohen4cc55372012-11-20 11:17:24 +020081 struct regulator *hsic_gdsc;
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +053082 atomic_t async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053083 atomic_t in_lpm;
Sudhir Sharma1673e302012-08-27 17:37:24 -070084 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080085 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080086 int wakeup_irq;
Jack Phamfe441ea2012-03-23 17:03:15 -070087 bool wakeup_irq_enabled;
Sudhir Sharma1673e302012-08-27 17:37:24 -070088 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080089 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070090 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030091 enum usb_vdd_type vdd_type;
Hemant Kumar2309eaa2012-08-14 16:46:42 -070092
93 struct work_struct bus_vote_w;
94 bool bus_vote;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070095
96 /* gp timer */
97 struct ehci_timer __iomem *timer;
98 struct completion gpt0_completion;
99 struct completion rt_completion;
100 int resume_status;
101 int resume_again;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +0530102
103 struct pm_qos_request pm_qos_req_dma;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530104};
105
Hemant Kumar105d07f2012-07-02 15:33:07 -0700106struct msm_hsic_hcd *__mehci;
107
Hemant Kumare6275972012-02-29 20:06:21 -0800108static bool debug_bus_voting_enabled = true;
Ofir Cohen4cc55372012-11-20 11:17:24 +0200109static u64 ehci_msm_hsic_dma_mask = DMA_BIT_MASK(32);
110
Manu Gautam863b74132012-11-21 14:30:04 +0530111static struct platform_driver ehci_msm_hsic_driver;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700112
Hemant Kumar4d50a432012-08-15 09:06:35 -0700113static unsigned int enable_payload_log = 1;
114module_param(enable_payload_log, uint, S_IRUGO | S_IWUSR);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700115static unsigned int enable_dbg_log = 1;
116module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
117/*by default log ep0 and efs sync ep*/
118static unsigned int ep_addr_rxdbg_mask = 9;
119module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
120static unsigned int ep_addr_txdbg_mask = 9;
121module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
122
123/* Maximum debug message length */
Hemant Kumar4d50a432012-08-15 09:06:35 -0700124#define DBG_MSG_LEN 128UL
Hemant Kumar45d211b2012-05-31 17:58:43 -0700125
126/* Maximum number of messages */
127#define DBG_MAX_MSG 256UL
128
129#define TIME_BUF_LEN 20
Hemant Kumar4d50a432012-08-15 09:06:35 -0700130#define HEX_DUMP_LEN 72
Hemant Kumar45d211b2012-05-31 17:58:43 -0700131
132enum event_type {
133 EVENT_UNDEF = -1,
134 URB_SUBMIT,
135 URB_COMPLETE,
136 EVENT_NONE,
137};
138
139#define EVENT_STR_LEN 5
140
Hemant Kumar45d211b2012-05-31 17:58:43 -0700141static enum event_type str_to_event(const char *name)
142{
143 if (!strncasecmp("S", name, EVENT_STR_LEN))
144 return URB_SUBMIT;
145 if (!strncasecmp("C", name, EVENT_STR_LEN))
146 return URB_COMPLETE;
147 if (!strncasecmp("", name, EVENT_STR_LEN))
148 return EVENT_NONE;
149
150 return EVENT_UNDEF;
151}
152
153/*log ep0 activity*/
154static struct {
155 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
156 unsigned idx; /* index */
157 rwlock_t lck; /* lock */
158} dbg_hsic_ctrl = {
159 .idx = 0,
160 .lck = __RW_LOCK_UNLOCKED(lck)
161};
162
163static struct {
164 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
165 unsigned idx; /* index */
166 rwlock_t lck; /* lock */
167} dbg_hsic_data = {
168 .idx = 0,
169 .lck = __RW_LOCK_UNLOCKED(lck)
170};
171
172/**
173 * dbg_inc: increments debug event index
174 * @idx: buffer index
175 */
176static void dbg_inc(unsigned *idx)
177{
178 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
179}
180
181/*get_timestamp - returns time of day in us */
182static char *get_timestamp(char *tbuf)
183{
184 unsigned long long t;
185 unsigned long nanosec_rem;
186
187 t = cpu_clock(smp_processor_id());
188 nanosec_rem = do_div(t, 1000000000)/1000;
189 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
190 nanosec_rem);
191 return tbuf;
192}
193
194static int allow_dbg_log(int ep_addr)
195{
196 int dir, num;
197
198 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
199 num = ep_addr & ~USB_DIR_IN;
200 num = 1 << num;
201
202 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
203 return 1;
204 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
205 return 1;
206
207 return 0;
208}
209
Hemant Kumar4d50a432012-08-15 09:06:35 -0700210static char *get_hex_data(char *dbuf, struct urb *urb, int event, int status)
211{
212 int ep_addr = urb->ep->desc.bEndpointAddress;
213 char *ubuf = urb->transfer_buffer;
214 size_t len = event ? \
215 urb->actual_length : urb->transfer_buffer_length;
216
217 if (status == -EINPROGRESS)
218 status = 0;
219
220 /*Only dump ep in completions and epout submissions*/
221 if (len && !status &&
222 (((ep_addr & USB_DIR_IN) && event) ||
223 (!(ep_addr & USB_DIR_IN) && !event))) {
224 if (len >= 32)
225 len = 32;
226 hex_dump_to_buffer(ubuf, len, 32, 4, dbuf, HEX_DUMP_LEN, 0);
227 } else {
228 dbuf = "";
229 }
230
231 return dbuf;
232}
233
Hemant Kumar45d211b2012-05-31 17:58:43 -0700234static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
235{
236 unsigned long flags;
237 int ep_addr;
238 char tbuf[TIME_BUF_LEN];
Hemant Kumar4d50a432012-08-15 09:06:35 -0700239 char dbuf[HEX_DUMP_LEN];
Hemant Kumar45d211b2012-05-31 17:58:43 -0700240
241 if (!enable_dbg_log)
242 return;
243
244 if (!urb) {
245 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
246 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700247 "%s: %s : %u", get_timestamp(tbuf), event, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700248 dbg_inc(&dbg_hsic_ctrl.idx);
249 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
250 return;
251 }
252
253 ep_addr = urb->ep->desc.bEndpointAddress;
254 if (!allow_dbg_log(ep_addr))
255 return;
256
257 if ((ep_addr & 0x0f) == 0x0) {
258 /*submit event*/
259 if (!str_to_event(event)) {
260 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
261 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
262 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
Hemant Kumar4d50a432012-08-15 09:06:35 -0700263 "%02x %02x %04x %04x %04x %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700264 get_timestamp(tbuf), event, urb,
265 (ep_addr & USB_DIR_IN) ? "in" : "out",
266 urb->setup_packet[0], urb->setup_packet[1],
267 (urb->setup_packet[3] << 8) |
268 urb->setup_packet[2],
269 (urb->setup_packet[5] << 8) |
270 urb->setup_packet[4],
271 (urb->setup_packet[7] << 8) |
272 urb->setup_packet[6],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700273 urb->transfer_buffer_length, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700274
275 dbg_inc(&dbg_hsic_ctrl.idx);
276 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
277 } else {
278 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
279 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700280 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700281 get_timestamp(tbuf), event, urb,
282 (ep_addr & USB_DIR_IN) ? "in" : "out",
283 urb->actual_length, extra);
284
285 dbg_inc(&dbg_hsic_ctrl.idx);
286 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
287 }
288 } else {
289 write_lock_irqsave(&dbg_hsic_data.lck, flags);
290 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700291 "%s: [%s : %p]:ep%d[%s] %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700292 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
293 (ep_addr & USB_DIR_IN) ? "in" : "out",
294 str_to_event(event) ? urb->actual_length :
Hemant Kumar4d50a432012-08-15 09:06:35 -0700295 urb->transfer_buffer_length, extra,
296 enable_payload_log ? get_hex_data(dbuf, urb,
297 str_to_event(event), extra) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700298
299 dbg_inc(&dbg_hsic_data.idx);
300 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
301 }
302}
303
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530304static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
305{
306 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
307}
308
309static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
310{
311 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
312}
313
Hemant Kumar105d07f2012-07-02 15:33:07 -0700314static void dump_hsic_regs(struct usb_hcd *hcd)
315{
316 int i;
317 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
318
319 if (atomic_read(&mehci->in_lpm))
320 return;
321
322 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
323 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
324 readl_relaxed(hcd->regs + i),
325 readl_relaxed(hcd->regs + i + 4),
326 readl_relaxed(hcd->regs + i + 8),
327 readl_relaxed(hcd->regs + i + 0xc));
328}
329
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530330#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
331
Amit Blayd6ea6102012-06-07 16:26:24 +0300332#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Hemant Kumar3b743cd2012-10-17 13:48:10 -0700333#define USB_PHY_VDD_DIG_VOL_MIN 945000 /* uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700334#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530335
Lena Salman8c8ba382012-02-14 15:59:31 +0200336#define HSIC_DBG1_REG 0x38
337
Amit Blayd6ea6102012-06-07 16:26:24 +0300338static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
339 { /* VDD_CX CORNER Voting */
340 [VDD_NONE] = RPM_VREG_CORNER_NONE,
341 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
342 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
343 },
344 { /* VDD_CX Voltage Voting */
345 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
346 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
347 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
348 },
349};
350
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530351static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
352{
353 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300354 int none_vol, min_vol, max_vol;
355
356 if (!mehci->hsic_vddcx) {
357 mehci->vdd_type = VDDCX_CORNER;
358 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
359 "hsic_vdd_dig");
360 if (IS_ERR(mehci->hsic_vddcx)) {
361 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
362 "HSIC_VDDCX");
363 if (IS_ERR(mehci->hsic_vddcx)) {
364 dev_err(mehci->dev, "unable to get hsic vddcx\n");
365 return PTR_ERR(mehci->hsic_vddcx);
366 }
367 mehci->vdd_type = VDDCX;
368 }
369 }
370
371 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
372 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
373 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530374
375 if (!init)
376 goto disable_reg;
377
Amit Blayd6ea6102012-06-07 16:26:24 +0300378 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530379 if (ret) {
380 dev_err(mehci->dev, "unable to set the voltage"
381 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530382 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530383 }
384
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530385 ret = regulator_enable(mehci->hsic_vddcx);
386 if (ret) {
387 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
388 goto reg_enable_err;
389 }
390
391 return 0;
392
393disable_reg:
394 regulator_disable(mehci->hsic_vddcx);
395reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300396 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
397
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530398 return ret;
399
400}
401
Ofir Cohen4cc55372012-11-20 11:17:24 +0200402/* Global Distributed Switch Controller (GDSC) init */
403static int msm_hsic_init_gdsc(struct msm_hsic_hcd *mehci, int init)
404{
405 int ret = 0;
406
407 if (IS_ERR(mehci->hsic_gdsc))
408 return 0;
409
410 if (!mehci->hsic_gdsc) {
411 mehci->hsic_gdsc = devm_regulator_get(mehci->dev,
412 "HSIC_GDSC");
413 if (IS_ERR(mehci->hsic_gdsc))
414 return 0;
415 }
416
417 if (init) {
418 ret = regulator_enable(mehci->hsic_gdsc);
419 if (ret) {
420 dev_err(mehci->dev, "unable to enable hsic gdsc\n");
421 return ret;
422 }
423 } else {
424 regulator_disable(mehci->hsic_gdsc);
425 }
426
427 return 0;
428
429}
430
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700431static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
432{
433 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700434 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700435
436 /* initiate read operation */
437 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
438 USB_ULPI_VIEWPORT);
439
440 /* wait for completion */
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700441 while (cnt < ULPI_IO_TIMEOUT_USEC) {
442 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
443 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700444 udelay(1);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700445 cnt++;
446 }
447
448 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
449 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
450 readl_relaxed(USB_ULPI_VIEWPORT));
451 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
452 readl_relaxed(USB_PORTSC),
453 readl_relaxed(USB_USBCMD),
454 readl_relaxed(USB_FRINDEX));
455
456 /*frame counter increments afte 125us*/
457 udelay(130);
458 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
459 readl_relaxed(USB_FRINDEX));
460 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700461 }
462
463 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
464}
465
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530466static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
467{
468 struct usb_hcd *hcd = hsic_to_hcd(mehci);
469 int cnt = 0;
470
471 /* initiate write operation */
472 writel_relaxed(ULPI_RUN | ULPI_WRITE |
473 ULPI_ADDR(reg) | ULPI_DATA(val),
474 USB_ULPI_VIEWPORT);
475
476 /* wait for completion */
477 while (cnt < ULPI_IO_TIMEOUT_USEC) {
478 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
479 break;
480 udelay(1);
481 cnt++;
482 }
483
484 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700485 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
486 readl_relaxed(USB_ULPI_VIEWPORT));
487 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
488 readl_relaxed(USB_PORTSC),
489 readl_relaxed(USB_USBCMD),
490 readl_relaxed(USB_FRINDEX));
491
492 /*frame counter increments afte 125us*/
493 udelay(130);
494 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
495 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530496 return -ETIMEDOUT;
497 }
498
499 return 0;
500}
501
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700502#define HSIC_DBG1 0X38
503#define ULPI_MANUAL_ENABLE BIT(4)
504#define ULPI_LINESTATE_DATA BIT(5)
505#define ULPI_LINESTATE_STROBE BIT(6)
506static void ehci_msm_enable_ulpi_control(struct usb_hcd *hcd, u32 linestate)
507{
508 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
509 int val;
510
511 switch (linestate) {
512 case PORT_RESET:
513 val = ulpi_read(mehci, HSIC_DBG1);
514 val |= ULPI_MANUAL_ENABLE;
515 val &= ~(ULPI_LINESTATE_DATA | ULPI_LINESTATE_STROBE);
516 ulpi_write(mehci, val, HSIC_DBG1);
517 break;
518 default:
519 pr_info("%s: Unknown linestate:%0x\n", __func__, linestate);
520 }
521}
522
523static void ehci_msm_disable_ulpi_control(struct usb_hcd *hcd)
524{
525 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
526 int val;
527
528 val = ulpi_read(mehci, HSIC_DBG1);
529 val &= ~ULPI_MANUAL_ENABLE;
530 ulpi_write(mehci, val, HSIC_DBG1);
531}
532
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530533static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
534{
535 int rc = 0;
536 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800537 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530538
539 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800540
Lena Salman8c8ba382012-02-14 15:59:31 +0200541 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530542 return rc;
543
Vamsi Krishna34f01582011-12-14 19:54:42 -0800544 if (gpio_status == gpio_en)
545 return 0;
546
547 gpio_status = gpio_en;
548
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530549 if (!gpio_en)
550 goto free_gpio;
551
552 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
553 if (rc < 0) {
554 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
555 return rc;
556 }
557
558 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
559 if (rc < 0) {
560 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
561 goto free_strobe;
Hemant Kumar6fd65032012-05-23 13:02:24 -0700562 }
563
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530564 return 0;
565
566free_gpio:
567 gpio_free(pdata->data);
568free_strobe:
569 gpio_free(pdata->strobe);
570
571 return rc;
572}
573
Vamsi Krishna64b48612012-06-14 16:08:11 -0700574static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530575{
576 int ret;
577
Ofir Cohen07944aa2012-12-23 13:41:57 +0200578 /* alt_core_clk exists in targets that do not use asynchronous reset */
579 if (!IS_ERR(mehci->alt_core_clk)) {
580 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
581 if (ret) {
582 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
583 return;
584 }
585
586 /* Since a hw bug, turn off the clock before complete reset */
587 clk_disable(mehci->core_clk);
588
589 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
590 if (ret)
591 dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
592 ret);
593
594 usleep_range(10000, 12000);
595
596 clk_enable(mehci->core_clk);
597 } else {
598 /* Using asynchronous block reset to the hardware */
599 clk_disable_unprepare(mehci->core_clk);
600 clk_disable_unprepare(mehci->phy_clk);
601 clk_disable_unprepare(mehci->cal_clk);
602 clk_disable_unprepare(mehci->ahb_clk);
603
604 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
605 if (ret) {
606 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
607 return;
608 }
609 usleep_range(10000, 12000);
610
611 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
612 if (ret)
613 dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
614 ret);
615 /*
616 * Required delay between the deassertion and
617 * clock enablement.
618 */
619 ndelay(200);
620 clk_prepare_enable(mehci->core_clk);
621 clk_prepare_enable(mehci->phy_clk);
622 clk_prepare_enable(mehci->cal_clk);
623 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530624 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530625}
626
Vamsi Krishna64b48612012-06-14 16:08:11 -0700627#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
628#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530629#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
630#define HSIC_LV_MODE 0x04
631#define HSIC_PAD_CALIBRATION 0xA8
632#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530633#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
Ofir Cohen5dddb152012-11-14 11:18:50 +0200634
635static void msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530636{
637 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530638
Vamsi Krishna64b48612012-06-14 16:08:11 -0700639 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530640
Vamsi Krishna64b48612012-06-14 16:08:11 -0700641 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530642 writel_relaxed(0x80000000, USB_PORTSC);
Vamsi Krishna64b48612012-06-14 16:08:11 -0700643 mb();
Ofir Cohen5dddb152012-11-14 11:18:50 +0200644}
645
646static int msm_hsic_start(struct msm_hsic_hcd *mehci)
647{
648 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
649 int ret;
Manu Gautam863b74132012-11-21 14:30:04 +0530650 void __iomem *reg;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530651
Lena Salman8c8ba382012-02-14 15:59:31 +0200652 /* HSIC init sequence when HSIC signals (Strobe/Data) are
653 routed via GPIOs */
654 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530655
Manu Gautam863b74132012-11-21 14:30:04 +0530656 if (!pdata->ignore_cal_pad_config) {
657 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
658 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
659 mb();
660 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700661
Lena Salman8c8ba382012-02-14 15:59:31 +0200662 /*set periodic calibration interval to ~2.048sec in
663 HSIC_IO_CAL_REG */
664 ulpi_write(mehci, 0xFF, 0x33);
665
666 /* Enable periodic IO calibration in HSIC_CFG register */
667 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
668
Vamsi Krishna64b48612012-06-14 16:08:11 -0700669 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200670 ret = msm_hsic_config_gpios(mehci, 1);
671 if (ret) {
672 dev_err(mehci->dev, " gpio configuarion failed\n");
673 return ret;
674 }
Manu Gautam863b74132012-11-21 14:30:04 +0530675 if (pdata->strobe_pad_offset) {
676 /* Set CORE_CTL_EN in STROBE GPIO PAD_CTL register */
677 reg = MSM_TLMM_BASE + pdata->strobe_pad_offset;
678 writel_relaxed(readl_relaxed(reg) | 0x2000000, reg);
679 } else {
680 /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */
681 reg = HSIC_STROBE_GPIO_PAD_CTL;
682 writel_relaxed(HSIC_GPIO_PAD_VAL, reg);
683 }
684
685 if (pdata->data_pad_offset) {
686 /* Set CORE_CTL_EN in HSIC_DATA GPIO PAD_CTL register */
687 reg = MSM_TLMM_BASE + pdata->data_pad_offset;
688 writel_relaxed(readl_relaxed(reg) | 0x2000000, reg);
689 } else {
690 /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */
691 reg = HSIC_DATA_GPIO_PAD_CTL;
692 writel_relaxed(HSIC_GPIO_PAD_VAL, reg);
693 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700694
695 mb();
696
Lena Salman8c8ba382012-02-14 15:59:31 +0200697 /* Enable HSIC mode in HSIC_CFG register */
698 ulpi_write(mehci, 0x01, 0x31);
699 } else {
700 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
701 via dedicated I/O */
702
703 /* programmable length of connect signaling (33.2ns) */
704 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
705 if (ret) {
706 pr_err("%s: Unable to program length of connect "
707 "signaling\n", __func__);
708 }
709
710 /*set periodic calibration interval to ~2.048sec in
711 HSIC_IO_CAL_REG */
712 ulpi_write(mehci, 0xFF, 0x33);
713
714 /* Enable HSIC mode in HSIC_CFG register */
715 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530716 }
717
Hemant Kumar6fd65032012-05-23 13:02:24 -0700718 /*disable auto resume*/
719 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
720
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530721 return 0;
722}
723
724#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
725#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
726
727#ifdef CONFIG_PM_SLEEP
Ofir Cohen5dddb152012-11-14 11:18:50 +0200728static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
729{
730 /* reset HSIC phy */
731 msm_hsic_phy_reset(mehci);
732
733 /* HSIC init procedure (caliberation) */
734 return msm_hsic_start(mehci);
735}
736
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530737static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
738{
739 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530740 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530741 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300742 int none_vol, max_vol;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700743 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530744
745 if (atomic_read(&mehci->in_lpm)) {
746 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
747 return 0;
748 }
749
750 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700751
Sudhir Sharma1673e302012-08-27 17:37:24 -0700752 /* make sure we don't race against a remote wakeup */
753 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700754 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Sudhir Sharma1673e302012-08-27 17:37:24 -0700755 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700756 enable_irq(hcd->irq);
757 return -EBUSY;
758 }
759
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530760 /*
761 * PHY may take some time or even fail to enter into low power
762 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
763 * in failure case.
764 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700765 val = readl_relaxed(USB_PORTSC);
766 val &= ~PORT_RWC_BITS;
767 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530768 writel_relaxed(val, USB_PORTSC);
769 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
770 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
771 break;
772 udelay(1);
773 cnt++;
774 }
775
776 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
777 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530778 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530779 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530780 }
781
782 /*
783 * PHY has capability to generate interrupt asynchronously in low
784 * power mode (LPM). This interrupt is level triggered. So USB IRQ
785 * line must be disabled till async interrupt enable bit is cleared
786 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
Pavankumar Kondeti0c9f29c2013-01-28 21:37:59 +0530787 * block data communication from PHY. Enable asynchronous interrupt
788 * only when wakeup gpio IRQ is not present.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530789 */
Pavankumar Kondeti0c9f29c2013-01-28 21:37:59 +0530790 if (mehci->wakeup_irq)
791 writel_relaxed(readl_relaxed(USB_USBCMD) |
792 ULPI_STP_CTRL, USB_USBCMD);
793 else
794 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530795 ULPI_STP_CTRL, USB_USBCMD);
796
797 /*
798 * Ensure that hardware is put in low power mode before
799 * clocks are turned OFF and VDD is allowed to minimize.
800 */
801 mb();
802
Manu Gautam28b1bac2012-01-30 16:43:06 +0530803 clk_disable_unprepare(mehci->core_clk);
804 clk_disable_unprepare(mehci->phy_clk);
805 clk_disable_unprepare(mehci->cal_clk);
806 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530807
Amit Blayd6ea6102012-06-07 16:26:24 +0300808 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
809 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
810
811 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700812 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300813 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700814
Hemant Kumare6275972012-02-29 20:06:21 -0800815 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700816 mehci->bus_vote = false;
817 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800818 }
819
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530820 atomic_set(&mehci->in_lpm, 1);
821 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700822
823 mehci->wakeup_irq_enabled = 1;
824 enable_irq_wake(mehci->wakeup_irq);
825 enable_irq(mehci->wakeup_irq);
826
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700827 if (pdata && pdata->standalone_latency)
828 pm_qos_update_request(&mehci->pm_qos_req_dma,
829 PM_QOS_DEFAULT_VALUE);
830
Sudhir Sharma1673e302012-08-27 17:37:24 -0700831 wake_unlock(&mehci->wlock);
832
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530833 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
834
835 return 0;
836}
837
838static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
839{
840 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530841 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530842 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300843 int min_vol, max_vol;
Hemant Kumard343c012012-09-06 19:57:14 -0700844 unsigned long flags;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700845 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530846
847 if (!atomic_read(&mehci->in_lpm)) {
848 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
849 return 0;
850 }
851
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530852 /* Handles race with Async interrupt */
853 disable_irq(hcd->irq);
854
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700855 if (pdata && pdata->standalone_latency)
856 pm_qos_update_request(&mehci->pm_qos_req_dma,
857 pdata->standalone_latency + 1);
858
Hemant Kumard343c012012-09-06 19:57:14 -0700859 spin_lock_irqsave(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700860 if (mehci->wakeup_irq_enabled) {
861 disable_irq_wake(mehci->wakeup_irq);
862 disable_irq_nosync(mehci->wakeup_irq);
863 mehci->wakeup_irq_enabled = 0;
864 }
Hemant Kumard343c012012-09-06 19:57:14 -0700865 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700866
Sudhir Sharma1673e302012-08-27 17:37:24 -0700867 wake_lock(&mehci->wlock);
868
Hemant Kumare6275972012-02-29 20:06:21 -0800869 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700870 mehci->bus_vote = true;
871 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800872 }
873
Amit Blayd6ea6102012-06-07 16:26:24 +0300874 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
875 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
876
877 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700878 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300879 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700880
Manu Gautam28b1bac2012-01-30 16:43:06 +0530881 clk_prepare_enable(mehci->core_clk);
882 clk_prepare_enable(mehci->phy_clk);
883 clk_prepare_enable(mehci->cal_clk);
884 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530885
886 temp = readl_relaxed(USB_USBCMD);
887 temp &= ~ASYNC_INTR_CTRL;
888 temp &= ~ULPI_STP_CTRL;
889 writel_relaxed(temp, USB_USBCMD);
890
891 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
892 goto skip_phy_resume;
893
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700894 temp = readl_relaxed(USB_PORTSC);
895 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530896 writel_relaxed(temp, USB_PORTSC);
897 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
898 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
899 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
900 break;
901 udelay(1);
902 cnt++;
903 }
904
905 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
906 /*
907 * This is a fatal error. Reset the link and
908 * PHY to make hsic working.
909 */
910 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530911 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530912 msm_hsic_reset(mehci);
913 }
914
915skip_phy_resume:
916
Hemant Kumar6fd65032012-05-23 13:02:24 -0700917 usb_hcd_resume_root_hub(hcd);
918
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530919 atomic_set(&mehci->in_lpm, 0);
920
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530921 if (atomic_read(&mehci->async_int)) {
922 atomic_set(&mehci->async_int, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530923 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700924 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700925 }
926
Sudhir Sharma1673e302012-08-27 17:37:24 -0700927 if (atomic_read(&mehci->pm_usage_cnt)) {
928 atomic_set(&mehci->pm_usage_cnt, 0);
929 pm_runtime_put_noidle(mehci->dev);
930 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700931
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530932 enable_irq(hcd->irq);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530933 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
934
935 return 0;
936}
937#endif
938
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700939static void ehci_hsic_bus_vote_w(struct work_struct *w)
940{
941 struct msm_hsic_hcd *mehci =
942 container_of(w, struct msm_hsic_hcd, bus_vote_w);
943 int ret;
944
945 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
946 mehci->bus_vote);
947 if (ret)
948 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
949 __func__, ret);
950}
951
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700952#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530953static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
954{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700955 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530956 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700957 u32 status;
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530958 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530959
960 if (atomic_read(&mehci->in_lpm)) {
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700961 dev_dbg(mehci->dev, "phy async intr\n");
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530962 dbg_log_event(NULL, "Async IRQ", 0);
963 ret = pm_runtime_get(mehci->dev);
964 if ((ret == 1) || (ret == -EINPROGRESS)) {
965 pm_runtime_put_noidle(mehci->dev);
966 } else {
967 disable_irq_nosync(hcd->irq);
968 atomic_set(&mehci->async_int, 1);
969 }
970
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530971 return IRQ_HANDLED;
972 }
973
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700974 status = ehci_readl(ehci, &ehci->regs->status);
975
976 if (status & STS_GPTIMER0_INTERRUPT) {
977 int timeleft;
978
979 dbg_log_event(NULL, "FPR: gpt0_isr", 0);
980
981 timeleft = GPT_CNT(ehci_readl(ehci,
982 &mehci->timer->gptimer1_ctrl));
983 if (timeleft) {
984 ehci_writel(ehci, ehci_readl(ehci,
985 &ehci->regs->command) | CMD_RUN,
986 &ehci->regs->command);
987 } else
988 mehci->resume_again = 1;
989
990 dbg_log_event(NULL, "FPR: timeleft", timeleft);
991
992 complete(&mehci->gpt0_completion);
993 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
994 }
995
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530996 return ehci_irq(hcd);
997}
998
999static int ehci_hsic_reset(struct usb_hcd *hcd)
1000{
1001 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001002 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301003 int retval;
1004
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001005 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301006 ehci->caps = USB_CAPLENGTH;
1007 ehci->regs = USB_CAPLENGTH +
1008 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
1009 dbg_hcs_params(ehci, "reset");
1010 dbg_hcc_params(ehci, "reset");
1011
1012 /* cache the data to minimize the chip reads*/
1013 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
1014
1015 hcd->has_tt = 1;
1016 ehci->sbrn = HCD_USB2;
1017
1018 retval = ehci_halt(ehci);
1019 if (retval)
1020 return retval;
1021
1022 /* data structure init */
1023 retval = ehci_init(hcd);
1024 if (retval)
1025 return retval;
1026
1027 retval = ehci_reset(ehci);
1028 if (retval)
1029 return retval;
1030
1031 /* bursts of unspecified length. */
1032 writel_relaxed(0, USB_AHBBURST);
1033 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +05301034 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301035 /* Disable streaming mode and select host mode */
1036 writel_relaxed(0x13, USB_USBMODE);
1037
1038 ehci_port_power(ehci, 1);
1039 return 0;
1040}
1041
Jack Phamc0d41732012-09-28 17:45:38 -07001042#ifdef CONFIG_PM
1043
Hemant Kumar45d211b2012-05-31 17:58:43 -07001044static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
1045{
Pavankumar Kondetia723f742012-09-14 14:02:36 +05301046 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1047
1048 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
1049 dbg_log_event(NULL, "RH suspend attempt failed", 0);
1050 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
1051 __func__);
1052 return -EAGAIN;
1053 }
1054
Hemant Kumar45d211b2012-05-31 17:58:43 -07001055 dbg_log_event(NULL, "Suspend RH", 0);
1056 return ehci_bus_suspend(hcd);
1057}
1058
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001059#define RESUME_RETRY_LIMIT 3
1060#define RESUME_SIGNAL_TIME_MS (21 * 999)
1061#define RESUME_SIGNAL_TIME_SOF_MS (23 * 999)
1062static int msm_hsic_resume_thread(void *data)
1063{
1064 struct msm_hsic_hcd *mehci = data;
1065 struct usb_hcd *hcd = hsic_to_hcd(mehci);
1066 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1067 u32 temp;
1068 unsigned long resume_needed = 0;
1069 int retry_cnt = 0;
1070 int tight_resume = 0;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301071 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001072
1073 dbg_log_event(NULL, "Resume RH", 0);
1074
1075 /* keep delay between bus states */
1076 if (time_before(jiffies, ehci->next_statechange))
1077 usleep_range(5000, 5000);
1078
1079 spin_lock_irq(&ehci->lock);
1080 if (!HCD_HW_ACCESSIBLE(hcd)) {
1081 spin_unlock_irq(&ehci->lock);
1082 mehci->resume_status = -ESHUTDOWN;
1083 complete(&mehci->rt_completion);
1084 return 0;
1085 }
1086
1087 if (unlikely(ehci->debug)) {
1088 if (!dbgp_reset_prep())
1089 ehci->debug = NULL;
1090 else
1091 dbgp_external_startup();
1092 }
1093
1094 /* at least some APM implementations will try to deliver
1095 * IRQs right away, so delay them until we're ready.
1096 */
1097 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
1098
1099 /* re-init operational registers */
1100 ehci_writel(ehci, 0, &ehci->regs->segment);
1101 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
1102 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
1103
1104 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
1105 if (ehci->resume_sof_bug)
1106 ehci->command &= ~CMD_RUN;
1107
1108 /* restore CMD_RUN, framelist size, and irq threshold */
1109 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1110
1111 /* manually resume the ports we suspended during bus_suspend() */
1112resume_again:
1113 if (retry_cnt >= RESUME_RETRY_LIMIT) {
1114 pr_info("retry count(%d) reached max, resume in tight loop\n",
1115 retry_cnt);
1116 tight_resume = 1;
1117 }
1118
1119
1120 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1121 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
1122 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
1123 temp |= PORT_RESUME;
1124 set_bit(0, &resume_needed);
1125 }
1126 dbg_log_event(NULL, "FPR: Set", temp);
1127 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1128
1129 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1130 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1131 * controller in MSM clears FPR bit after driving the resume signal for
1132 * 20ms. Workaround is to stop SOFs before driving resume and then start
1133 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1134 * completion otherwise peripheral may enter undefined state. As
1135 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1136 * to time the resume sequence. If driver exceeds allowable time SOFs,
1137 * repeat the resume process.
1138 */
1139 if (ehci->resume_sof_bug && resume_needed) {
1140 if (!tight_resume) {
1141 mehci->resume_again = 0;
1142 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_MS),
1143 &mehci->timer->gptimer0_ld);
1144 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1145 &mehci->timer->gptimer0_ctrl);
1146 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1147 &ehci->regs->intr_enable);
1148
1149 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_SOF_MS),
1150 &mehci->timer->gptimer1_ld);
1151 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1152 &mehci->timer->gptimer1_ctrl);
1153
1154 spin_unlock_irq(&ehci->lock);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301155 if (pdata && pdata->swfi_latency)
1156 pm_qos_update_request(&mehci->pm_qos_req_dma,
1157 pdata->swfi_latency + 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001158 wait_for_completion(&mehci->gpt0_completion);
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001159 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301160 pm_qos_update_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001161 pdata->standalone_latency + 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001162 spin_lock_irq(&ehci->lock);
1163 } else {
1164 dbg_log_event(NULL, "FPR: Tightloop", 0);
1165 /* do the resume in a tight loop */
1166 handshake(ehci, &ehci->regs->port_status[0],
1167 PORT_RESUME, 0, 22 * 1000);
1168 ehci_writel(ehci, ehci_readl(ehci,
1169 &ehci->regs->command) | CMD_RUN,
1170 &ehci->regs->command);
1171 }
1172
1173 if (mehci->resume_again) {
1174 int temp;
1175
1176 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1177 pr_info("FPR: retry count: %d\n", retry_cnt);
1178 spin_unlock_irq(&ehci->lock);
1179 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1180 temp &= ~PORT_RWC_BITS;
1181 temp |= PORT_SUSPEND;
1182 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1183 /* Keep the bus idle for 5ms so that peripheral
1184 * can detect and initiate suspend
1185 */
1186 usleep_range(5000, 5000);
1187 dbg_log_event(NULL,
1188 "FPR: RResume",
1189 ehci_readl(ehci, &ehci->regs->port_status[0]));
1190 spin_lock_irq(&ehci->lock);
1191 mehci->resume_again = 0;
1192 retry_cnt++;
1193 goto resume_again;
1194 }
1195 }
1196
1197 dbg_log_event(NULL, "FPR: RT-Done", 0);
1198 mehci->resume_status = 1;
1199 spin_unlock_irq(&ehci->lock);
1200
1201 complete(&mehci->rt_completion);
1202
1203 return 0;
1204}
1205
Hemant Kumar45d211b2012-05-31 17:58:43 -07001206static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1207{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001208 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1209 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1210 u32 temp;
1211 struct task_struct *resume_thread = NULL;
1212
1213 mehci->resume_status = 0;
1214 resume_thread = kthread_run(msm_hsic_resume_thread,
1215 mehci, "hsic_resume_thread");
1216 if (IS_ERR(resume_thread)) {
1217 pr_err("Error creating resume thread:%lu\n",
1218 PTR_ERR(resume_thread));
1219 return PTR_ERR(resume_thread);
1220 }
1221
1222 wait_for_completion(&mehci->rt_completion);
1223
1224 if (mehci->resume_status < 0)
1225 return mehci->resume_status;
1226
1227 dbg_log_event(NULL, "FPR: Wokeup", 0);
1228 spin_lock_irq(&ehci->lock);
1229 (void) ehci_readl(ehci, &ehci->regs->command);
1230
1231 temp = 0;
1232 if (ehci->async->qh_next.qh)
1233 temp |= CMD_ASE;
1234 if (ehci->periodic_sched)
1235 temp |= CMD_PSE;
1236 if (temp) {
1237 ehci->command |= temp;
1238 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1239 }
1240
1241 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1242 hcd->state = HC_STATE_RUNNING;
1243 ehci->rh_state = EHCI_RH_RUNNING;
1244
1245 /* Now we can safely re-enable irqs */
1246 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1247
1248 spin_unlock_irq(&ehci->lock);
1249
1250 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001251}
1252
Jack Phamc0d41732012-09-28 17:45:38 -07001253#else
1254
1255#define ehci_hsic_bus_suspend NULL
1256#define ehci_hsic_bus_resume NULL
1257
1258#endif /* CONFIG_PM */
1259
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001260static void ehci_msm_set_autosuspend_delay(struct usb_device *dev)
1261{
1262 if (!dev->parent) /*for root hub no delay*/
1263 pm_runtime_set_autosuspend_delay(&dev->dev, 0);
1264 else
1265 pm_runtime_set_autosuspend_delay(&dev->dev, 200);
1266}
1267
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301268static struct hc_driver msm_hsic_driver = {
1269 .description = hcd_name,
1270 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1271 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1272
1273 /*
1274 * generic hardware linkage
1275 */
1276 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001277 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301278
1279 .reset = ehci_hsic_reset,
1280 .start = ehci_run,
1281
1282 .stop = ehci_stop,
1283 .shutdown = ehci_shutdown,
1284
1285 /*
1286 * managing i/o requests and associated device resources
1287 */
Hemant Kumar4d50a432012-08-15 09:06:35 -07001288 .urb_enqueue = ehci_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301289 .urb_dequeue = ehci_urb_dequeue,
1290 .endpoint_disable = ehci_endpoint_disable,
1291 .endpoint_reset = ehci_endpoint_reset,
1292 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1293
1294 /*
1295 * scheduling support
1296 */
1297 .get_frame_number = ehci_get_frame,
1298
1299 /*
1300 * root hub support
1301 */
1302 .hub_status_data = ehci_hub_status_data,
1303 .hub_control = ehci_hub_control,
1304 .relinquish_port = ehci_relinquish_port,
1305 .port_handed_over = ehci_port_handed_over,
1306
1307 /*
1308 * PM support
1309 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001310 .bus_suspend = ehci_hsic_bus_suspend,
1311 .bus_resume = ehci_hsic_bus_resume,
1312
Hemant Kumar4d50a432012-08-15 09:06:35 -07001313 .log_urb = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001314 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001315
1316 .enable_ulpi_control = ehci_msm_enable_ulpi_control,
1317 .disable_ulpi_control = ehci_msm_disable_ulpi_control,
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001318
1319 .set_autosuspend_delay = ehci_msm_set_autosuspend_delay,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301320};
1321
1322static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1323{
1324 int ret = 0;
1325
1326 if (!init)
1327 goto put_clocks;
1328
Lena Salman8c8ba382012-02-14 15:59:31 +02001329 /*core_clk is required for LINK protocol engine
1330 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001331 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1332 if (IS_ERR(mehci->core_clk)) {
1333 dev_err(mehci->dev, "failed to get core_clk\n");
1334 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301335 return ret;
1336 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301337
Ofir Cohen07944aa2012-12-23 13:41:57 +02001338 /* alt_core_clk is for LINK to be used during PHY RESET in
1339 * targets on which link does NOT use asynchronous reset methodology.
Lena Salman8c8ba382012-02-14 15:59:31 +02001340 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001341 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
Manu Gautam863b74132012-11-21 14:30:04 +05301342 if (IS_ERR(mehci->alt_core_clk))
1343 dev_dbg(mehci->dev, "failed to get alt_core_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301344
Lena Salman8c8ba382012-02-14 15:59:31 +02001345 /* phy_clk is required for HSIC PHY operation
1346 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001347 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1348 if (IS_ERR(mehci->phy_clk)) {
1349 dev_err(mehci->dev, "failed to get phy_clk\n");
1350 ret = PTR_ERR(mehci->phy_clk);
1351 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301352 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301353
1354 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001355 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301356 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001357 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301358 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001359 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301360 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301361
1362 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001363 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301364 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001365 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301366 ret = PTR_ERR(mehci->ahb_clk);
1367 goto put_cal_clk;
1368 }
1369
Manu Gautam28b1bac2012-01-30 16:43:06 +05301370 clk_prepare_enable(mehci->core_clk);
1371 clk_prepare_enable(mehci->phy_clk);
1372 clk_prepare_enable(mehci->cal_clk);
1373 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301374
1375 return 0;
1376
1377put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001378 if (!atomic_read(&mehci->in_lpm)) {
1379 clk_disable_unprepare(mehci->core_clk);
1380 clk_disable_unprepare(mehci->phy_clk);
1381 clk_disable_unprepare(mehci->cal_clk);
1382 clk_disable_unprepare(mehci->ahb_clk);
1383 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301384 clk_put(mehci->ahb_clk);
1385put_cal_clk:
1386 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001387put_phy_clk:
1388 clk_put(mehci->phy_clk);
1389put_alt_core_clk:
Manu Gautam863b74132012-11-21 14:30:04 +05301390 if (!IS_ERR(mehci->alt_core_clk))
1391 clk_put(mehci->alt_core_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001392 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301393
1394 return ret;
1395}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001396static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1397{
1398 struct msm_hsic_hcd *mehci = dev_id;
1399
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001400 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001401
1402 if (mehci)
1403 msm_hsic_config_gpios(mehci, 0);
1404
1405 return IRQ_HANDLED;
1406}
1407
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001408static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1409{
1410 struct msm_hsic_hcd *mehci = data;
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301411 int ret;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001412
Hemant Kumar6fd65032012-05-23 13:02:24 -07001413 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001414 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001415 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
1416 __func__, mehci->wakeup_int_cnt);
1417
Sudhir Sharma1673e302012-08-27 17:37:24 -07001418 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001419
Hemant Kumard343c012012-09-06 19:57:14 -07001420 spin_lock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001421 if (mehci->wakeup_irq_enabled) {
1422 mehci->wakeup_irq_enabled = 0;
1423 disable_irq_wake(irq);
1424 disable_irq_nosync(irq);
1425 }
Hemant Kumard343c012012-09-06 19:57:14 -07001426 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001427
Sudhir Sharma1673e302012-08-27 17:37:24 -07001428 if (!atomic_read(&mehci->pm_usage_cnt)) {
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301429 ret = pm_runtime_get(mehci->dev);
1430 /*
1431 * HSIC runtime resume can race with us.
1432 * if we are active (ret == 1) or resuming
1433 * (ret == -EINPROGRESS), decrement the
1434 * PM usage counter before returning.
1435 */
1436 if ((ret == 1) || (ret == -EINPROGRESS))
1437 pm_runtime_put_noidle(mehci->dev);
1438 else
1439 atomic_set(&mehci->pm_usage_cnt, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001440 }
1441
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001442 return IRQ_HANDLED;
1443}
1444
Hemant Kumare6275972012-02-29 20:06:21 -08001445static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1446{
1447 if (debug_bus_voting_enabled)
1448 seq_printf(s, "enabled\n");
1449 else
1450 seq_printf(s, "disabled\n");
1451
1452 return 0;
1453}
1454
1455static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1456{
1457 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1458}
1459
1460static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1461 const char __user *ubuf, size_t count, loff_t *ppos)
1462{
1463 char buf[8];
1464 int ret;
1465 struct seq_file *s = file->private_data;
1466 struct msm_hsic_hcd *mehci = s->private;
1467
1468 memset(buf, 0x00, sizeof(buf));
1469
1470 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1471 return -EFAULT;
1472
1473 if (!strncmp(buf, "enable", 6)) {
1474 /* Do not vote here. Let hsic driver decide when to vote */
1475 debug_bus_voting_enabled = true;
1476 } else {
1477 debug_bus_voting_enabled = false;
1478 if (mehci->bus_perf_client) {
1479 ret = msm_bus_scale_client_update_request(
1480 mehci->bus_perf_client, 0);
1481 if (ret)
1482 dev_err(mehci->dev, "%s: Failed to devote "
1483 "for bus bw %d\n", __func__, ret);
1484 }
1485 }
1486
1487 return count;
1488}
1489
1490const struct file_operations ehci_hsic_msm_bus_fops = {
1491 .open = ehci_hsic_msm_bus_open,
1492 .read = seq_read,
1493 .write = ehci_hsic_msm_bus_write,
1494 .llseek = seq_lseek,
1495 .release = single_release,
1496};
1497
Hemant Kumar6fd65032012-05-23 13:02:24 -07001498static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1499{
1500 struct msm_hsic_hcd *mehci = s->private;
1501
1502 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1503
1504 return 0;
1505}
1506
1507static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1508{
1509 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1510}
1511
1512const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1513 .open = ehci_hsic_msm_wakeup_cnt_open,
1514 .read = seq_read,
1515 .llseek = seq_lseek,
1516 .release = single_release,
1517};
1518
Hemant Kumar45d211b2012-05-31 17:58:43 -07001519static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1520{
1521 unsigned long flags;
1522 unsigned i;
1523
1524 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1525
1526 i = dbg_hsic_data.idx;
1527 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1528 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1529 continue;
1530 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1531 }
1532
1533 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1534
1535 return 0;
1536}
1537
1538static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1539{
1540 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1541}
1542
1543const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1544 .open = ehci_hsic_msm_data_events_open,
1545 .read = seq_read,
1546 .llseek = seq_lseek,
1547 .release = single_release,
1548};
1549
1550static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1551{
1552 unsigned long flags;
1553 unsigned i;
1554
1555 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1556
1557 i = dbg_hsic_ctrl.idx;
1558 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1559 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1560 continue;
1561 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1562 }
1563
1564 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1565
1566 return 0;
1567}
1568
1569static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1570{
1571 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1572}
1573
1574const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1575 .open = ehci_hsic_msm_ctrl_events_open,
1576 .read = seq_read,
1577 .llseek = seq_lseek,
1578 .release = single_release,
1579};
1580
Hemant Kumare6275972012-02-29 20:06:21 -08001581static struct dentry *ehci_hsic_msm_dbg_root;
1582static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1583{
1584 struct dentry *ehci_hsic_msm_dentry;
1585
1586 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1587
1588 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1589 return -ENODEV;
1590
1591 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1592 S_IRUGO | S_IWUSR,
1593 ehci_hsic_msm_dbg_root, mehci,
1594 &ehci_hsic_msm_bus_fops);
1595
1596 if (!ehci_hsic_msm_dentry) {
1597 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1598 return -ENODEV;
1599 }
1600
Hemant Kumar6fd65032012-05-23 13:02:24 -07001601 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1602 S_IRUGO,
1603 ehci_hsic_msm_dbg_root, mehci,
1604 &ehci_hsic_msm_wakeup_cnt_fops);
1605
1606 if (!ehci_hsic_msm_dentry) {
1607 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1608 return -ENODEV;
1609 }
1610
Hemant Kumar45d211b2012-05-31 17:58:43 -07001611 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1612 S_IRUGO,
1613 ehci_hsic_msm_dbg_root, mehci,
1614 &ehci_hsic_msm_dbg_ctrl_fops);
1615
1616 if (!ehci_hsic_msm_dentry) {
1617 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1618 return -ENODEV;
1619 }
1620
1621 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1622 S_IRUGO,
1623 ehci_hsic_msm_dbg_root, mehci,
1624 &ehci_hsic_msm_dbg_data_fops);
1625
1626 if (!ehci_hsic_msm_dentry) {
1627 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1628 return -ENODEV;
1629 }
1630
Hemant Kumare6275972012-02-29 20:06:21 -08001631 return 0;
1632}
1633
1634static void ehci_hsic_msm_debugfs_cleanup(void)
1635{
1636 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1637}
1638
Manu Gautam863b74132012-11-21 14:30:04 +05301639struct msm_hsic_host_platform_data *msm_hsic_dt_to_pdata(
1640 struct platform_device *pdev)
1641{
1642 struct device_node *node = pdev->dev.of_node;
1643 struct msm_hsic_host_platform_data *pdata;
Ido Shayevitzca5dc492013-01-09 14:49:59 +02001644 int res_gpio;
Manu Gautam863b74132012-11-21 14:30:04 +05301645
1646 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1647 if (!pdata) {
1648 dev_err(&pdev->dev, "unable to allocate platform data\n");
1649 return NULL;
1650 }
Manu Gautam863b74132012-11-21 14:30:04 +05301651
Ido Shayevitzca5dc492013-01-09 14:49:59 +02001652 res_gpio = of_get_named_gpio(node, "hsic,strobe-gpio", 0);
1653 if (res_gpio < 0)
1654 res_gpio = 0;
1655 pdata->strobe = res_gpio;
1656
1657 res_gpio = of_get_named_gpio(node, "hsic,data-gpio", 0);
1658 if (res_gpio < 0)
1659 res_gpio = 0;
1660 pdata->data = res_gpio;
Manu Gautam863b74132012-11-21 14:30:04 +05301661
1662 pdata->ignore_cal_pad_config = of_property_read_bool(node,
1663 "hsic,ignore-cal-pad-config");
1664 of_property_read_u32(node, "hsic,strobe-pad-offset",
1665 &pdata->strobe_pad_offset);
1666 of_property_read_u32(node, "hsic,data-pad-offset",
1667 &pdata->data_pad_offset);
1668
1669 return pdata;
1670}
1671
1672
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301673static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1674{
1675 struct usb_hcd *hcd;
1676 struct resource *res;
1677 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301678 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301679 int ret;
1680
1681 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1682
Manu Gautam863b74132012-11-21 14:30:04 +05301683 if (pdev->dev.of_node) {
1684 dev_dbg(&pdev->dev, "device tree enabled\n");
1685 pdev->dev.platform_data = msm_hsic_dt_to_pdata(pdev);
1686 dev_set_name(&pdev->dev, ehci_msm_hsic_driver.driver.name);
1687 }
1688 if (!pdev->dev.platform_data)
1689 dev_dbg(&pdev->dev, "No platform data given\n");
1690
Ofir Cohen4cc55372012-11-20 11:17:24 +02001691 if (!pdev->dev.dma_mask)
1692 pdev->dev.dma_mask = &ehci_msm_hsic_dma_mask;
1693 if (!pdev->dev.coherent_dma_mask)
1694 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
1695
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301696 /* After parent device's probe is executed, it will be put in suspend
1697 * mode. When child device's probe is called, driver core is not
1698 * resuming parent device due to which parent will be in suspend even
1699 * though child is active. Hence resume the parent device explicitly.
1700 */
1701 if (pdev->dev.parent)
1702 pm_runtime_get_sync(pdev->dev.parent);
1703
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301704 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1705 dev_name(&pdev->dev));
1706 if (!hcd) {
1707 dev_err(&pdev->dev, "Unable to create HCD\n");
1708 return -ENOMEM;
1709 }
1710
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301711 hcd_to_bus(hcd)->skip_resume = true;
1712
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301713 hcd->irq = platform_get_irq(pdev, 0);
1714 if (hcd->irq < 0) {
1715 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1716 ret = hcd->irq;
1717 goto put_hcd;
1718 }
1719
1720 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1721 if (!res) {
1722 dev_err(&pdev->dev, "Unable to get memory resource\n");
1723 ret = -ENODEV;
1724 goto put_hcd;
1725 }
1726
1727 hcd->rsrc_start = res->start;
1728 hcd->rsrc_len = resource_size(res);
1729 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1730 if (!hcd->regs) {
1731 dev_err(&pdev->dev, "ioremap failed\n");
1732 ret = -ENOMEM;
1733 goto put_hcd;
1734 }
1735
1736 mehci = hcd_to_hsic(hcd);
1737 mehci->dev = &pdev->dev;
Hemant Kumar30d361c2012-08-20 14:44:40 -07001738 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301739
Hemant Kumard343c012012-09-06 19:57:14 -07001740 spin_lock_init(&mehci->wakeup_lock);
1741
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001742 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001743 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001744
Hemant Kumare4040492012-06-21 17:35:42 -07001745 mehci->ehci.resume_sof_bug = 1;
1746
Hemant Kumar30d361c2012-08-20 14:44:40 -07001747 if (pdata)
1748 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Hemant Kumar933e0402012-05-22 11:11:40 -07001749
Ofir Cohen4cc55372012-11-20 11:17:24 +02001750 ret = msm_hsic_init_gdsc(mehci, 1);
1751 if (ret) {
1752 dev_err(&pdev->dev, "unable to initialize GDSC\n");
1753 ret = -ENODEV;
1754 goto put_hcd;
1755 }
1756
Vamsi Krishna34f01582011-12-14 19:54:42 -08001757 res = platform_get_resource_byname(pdev,
1758 IORESOURCE_IRQ,
1759 "peripheral_status_irq");
1760 if (res)
1761 mehci->peripheral_status_irq = res->start;
1762
Jack Pham0cc75c42012-10-10 02:03:50 +02001763 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "wakeup");
Hemant Kumar6fd65032012-05-23 13:02:24 -07001764 if (res) {
Jack Pham0cc75c42012-10-10 02:03:50 +02001765 mehci->wakeup_irq = res->start;
Hemant Kumar6fd65032012-05-23 13:02:24 -07001766 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1767 }
1768
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301769 ret = msm_hsic_init_clocks(mehci, 1);
1770 if (ret) {
1771 dev_err(&pdev->dev, "unable to initialize clocks\n");
1772 ret = -ENODEV;
1773 goto unmap;
1774 }
1775
1776 ret = msm_hsic_init_vddcx(mehci, 1);
1777 if (ret) {
1778 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1779 ret = -ENODEV;
1780 goto deinit_clocks;
1781 }
1782
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001783 init_completion(&mehci->rt_completion);
1784 init_completion(&mehci->gpt0_completion);
Ofir Cohen5dddb152012-11-14 11:18:50 +02001785
1786 msm_hsic_phy_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301787
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001788 ehci_wq = create_singlethread_workqueue("ehci_wq");
1789 if (!ehci_wq) {
1790 dev_err(&pdev->dev, "unable to create workqueue\n");
1791 ret = -ENOMEM;
1792 goto deinit_vddcx;
1793 }
1794
1795 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1796
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301797 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1798 if (ret) {
1799 dev_err(&pdev->dev, "unable to register HCD\n");
Ofir Cohen5dddb152012-11-14 11:18:50 +02001800 goto destroy_wq;
1801 }
1802
1803 ret = msm_hsic_start(mehci);
1804 if (ret) {
1805 dev_err(&pdev->dev, "unable to initialize PHY\n");
1806 goto destroy_wq;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301807 }
1808
1809 device_init_wakeup(&pdev->dev, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001810 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1811 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001812
1813 if (mehci->peripheral_status_irq) {
1814 ret = request_threaded_irq(mehci->peripheral_status_irq,
1815 NULL, hsic_peripheral_status_change,
1816 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1817 | IRQF_SHARED,
1818 "hsic_peripheral_status", mehci);
1819 if (ret)
1820 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1821 __func__, mehci->peripheral_status_irq, ret);
1822 }
1823
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001824 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001825 if (mehci->wakeup_irq) {
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07001826 /* In case if wakeup gpio is pulled high at this point
1827 * remote wakeup interrupt fires right after request_irq.
1828 * Remote wake up interrupt only needs to be enabled when
1829 * HSIC bus goes to suspend.
1830 */
1831 irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001832 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001833 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001834 "msm_hsic_wakeup", mehci);
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07001835 if (ret) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001836 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1837 mehci->wakeup_irq, ret);
1838 mehci->wakeup_irq = 0;
1839 }
1840 }
1841
Hemant Kumare6275972012-02-29 20:06:21 -08001842 ret = ehci_hsic_msm_debugfs_init(mehci);
1843 if (ret)
1844 dev_dbg(&pdev->dev, "mode debugfs file is"
1845 "not available\n");
1846
1847 if (pdata && pdata->bus_scale_table) {
1848 mehci->bus_perf_client =
1849 msm_bus_scale_register_client(pdata->bus_scale_table);
1850 /* Configure BUS performance parameters for MAX bandwidth */
1851 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001852 mehci->bus_vote = true;
1853 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001854 } else {
1855 dev_err(&pdev->dev, "%s: Failed to register BUS "
1856 "scaling client!!\n", __func__);
1857 }
1858 }
1859
Hemant Kumar105d07f2012-07-02 15:33:07 -07001860 __mehci = mehci;
1861
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001862 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301863 pm_qos_add_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001864 PM_QOS_CPU_DMA_LATENCY, pdata->standalone_latency + 1);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301865
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301866 /*
1867 * This pdev->dev is assigned parent of root-hub by USB core,
1868 * hence, runtime framework automatically calls this driver's
1869 * runtime APIs based on root-hub's state.
1870 */
1871 pm_runtime_set_active(&pdev->dev);
1872 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301873 /* Decrement the parent device's counter after probe.
1874 * As child is active, parent will not be put into
1875 * suspend mode.
1876 */
1877 if (pdev->dev.parent)
1878 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301879
1880 return 0;
1881
Ofir Cohen5dddb152012-11-14 11:18:50 +02001882destroy_wq:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001883 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301884deinit_vddcx:
1885 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02001886 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301887deinit_clocks:
1888 msm_hsic_init_clocks(mehci, 0);
1889unmap:
1890 iounmap(hcd->regs);
1891put_hcd:
1892 usb_put_hcd(hcd);
1893
1894 return ret;
1895}
1896
1897static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1898{
1899 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1900 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301901 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1902
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001903 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301904 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301905
Vamsi Krishna34f01582011-12-14 19:54:42 -08001906 if (mehci->peripheral_status_irq)
1907 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001908
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001909 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001910 if (mehci->wakeup_irq_enabled)
1911 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001912 free_irq(mehci->wakeup_irq, mehci);
1913 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001914
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001915 /*
1916 * If the update request is called after unregister, the request will
1917 * fail. Results are undefined if unregister is called in the middle of
1918 * update request.
1919 */
1920 mehci->bus_vote = false;
1921 cancel_work_sync(&mehci->bus_vote_w);
1922
Hemant Kumare6275972012-02-29 20:06:21 -08001923 if (mehci->bus_perf_client)
1924 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1925
1926 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301927 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301928 pm_runtime_set_suspended(&pdev->dev);
1929
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001930 destroy_workqueue(ehci_wq);
1931
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301932 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301933 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301934 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02001935 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301936
1937 msm_hsic_init_clocks(mehci, 0);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001938 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301939 iounmap(hcd->regs);
1940 usb_put_hcd(hcd);
1941
1942 return 0;
1943}
1944
1945#ifdef CONFIG_PM_SLEEP
1946static int msm_hsic_pm_suspend(struct device *dev)
1947{
Jack Phambe05fbb2012-05-16 10:56:26 -07001948 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301949 struct usb_hcd *hcd = dev_get_drvdata(dev);
1950 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1951
1952 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1953
Hemant Kumar45d211b2012-05-31 17:58:43 -07001954 dbg_log_event(NULL, "PM Suspend", 0);
1955
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301956 if (device_may_wakeup(dev))
1957 enable_irq_wake(hcd->irq);
1958
Jack Phambe05fbb2012-05-16 10:56:26 -07001959 ret = msm_hsic_suspend(mehci);
1960
1961 if (ret && device_may_wakeup(dev))
1962 disable_irq_wake(hcd->irq);
1963
1964 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001965}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301966
Jack Pham16b06f82012-08-14 20:03:59 -07001967static int msm_hsic_pm_suspend_noirq(struct device *dev)
1968{
1969 struct usb_hcd *hcd = dev_get_drvdata(dev);
1970 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1971
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05301972 if (atomic_read(&mehci->async_int)) {
Jack Pham16b06f82012-08-14 20:03:59 -07001973 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
1974 return -EBUSY;
1975 }
1976
1977 return 0;
1978}
1979
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301980static int msm_hsic_pm_resume(struct device *dev)
1981{
1982 int ret;
1983 struct usb_hcd *hcd = dev_get_drvdata(dev);
1984 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1985
Jack Pham16b06f82012-08-14 20:03:59 -07001986 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001987 dbg_log_event(NULL, "PM Resume", 0);
1988
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301989 if (device_may_wakeup(dev))
1990 disable_irq_wake(hcd->irq);
1991
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301992 /*
1993 * Keep HSIC in Low Power Mode if system is resumed
1994 * by any other wakeup source. HSIC is resumed later
1995 * when remote wakeup is received or interface driver
1996 * start I/O.
1997 */
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05301998 if (!atomic_read(&mehci->pm_usage_cnt) &&
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05301999 !atomic_read(&mehci->async_int) &&
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05302000 pm_runtime_suspended(dev))
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05302001 return 0;
2002
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302003 ret = msm_hsic_resume(mehci);
2004 if (ret)
2005 return ret;
2006
2007 /* Bring the device to full powered state upon system resume */
2008 pm_runtime_disable(dev);
2009 pm_runtime_set_active(dev);
2010 pm_runtime_enable(dev);
2011
2012 return 0;
2013}
2014#endif
2015
2016#ifdef CONFIG_PM_RUNTIME
2017static int msm_hsic_runtime_idle(struct device *dev)
2018{
2019 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302020 return 0;
2021}
2022
2023static int msm_hsic_runtime_suspend(struct device *dev)
2024{
2025 struct usb_hcd *hcd = dev_get_drvdata(dev);
2026 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2027
2028 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002029
2030 dbg_log_event(NULL, "Run Time PM Suspend", 0);
2031
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302032 return msm_hsic_suspend(mehci);
2033}
2034
2035static int msm_hsic_runtime_resume(struct device *dev)
2036{
2037 struct usb_hcd *hcd = dev_get_drvdata(dev);
2038 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2039
2040 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002041
2042 dbg_log_event(NULL, "Run Time PM Resume", 0);
2043
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302044 return msm_hsic_resume(mehci);
2045}
2046#endif
2047
2048#ifdef CONFIG_PM
2049static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
2050 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07002051 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302052 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
2053 msm_hsic_runtime_idle)
2054};
2055#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02002056static const struct of_device_id hsic_host_dt_match[] = {
2057 { .compatible = "qcom,hsic-host",
2058 },
2059 {}
2060};
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302061static struct platform_driver ehci_msm_hsic_driver = {
2062 .probe = ehci_hsic_msm_probe,
2063 .remove = __devexit_p(ehci_hsic_msm_remove),
2064 .driver = {
2065 .name = "msm_hsic_host",
2066#ifdef CONFIG_PM
2067 .pm = &msm_hsic_dev_pm_ops,
2068#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02002069 .of_match_table = hsic_host_dt_match,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302070 },
2071};