blob: 3ec158bdaf2a8cb53279f129915c4b817e502cdb [file] [log] [blame]
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301/* ehci-msm-hsic.c - HSUSB Host Controller Driver Implementation
2 *
Ido Shayevitz95c46882013-01-20 13:47:46 +02003 * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05304 *
5 * Partly derived from ehci-fsl.c and ehci-hcd.c
6 * Copyright (c) 2000-2004 by David Brownell
7 * Copyright (c) 2005 MontaVista Software
8 *
9 * All source code in this file is licensed under the following license except
10 * where indicated.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published
14 * by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * See the GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, you can find it at http://www.fsf.org
23 */
24
25#include <linux/platform_device.h>
26#include <linux/clk.h>
27#include <linux/err.h>
Hemant Kumare6275972012-02-29 20:06:21 -080028#include <linux/debugfs.h>
29#include <linux/seq_file.h>
Sudhir Sharma1673e302012-08-27 17:37:24 -070030#include <linux/wakelock.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053031#include <linux/pm_runtime.h>
32#include <linux/regulator/consumer.h>
33
Manu Gautam863b74132012-11-21 14:30:04 +053034#include <linux/usb/ulpi.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053035#include <linux/usb/msm_hsusb_hw.h>
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +053036#include <linux/usb/msm_hsusb.h>
37#include <linux/gpio.h>
Manu Gautam863b74132012-11-21 14:30:04 +053038#include <linux/of_gpio.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030039#include <linux/spinlock.h>
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -070040#include <linux/irq.h>
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070041#include <linux/kthread.h>
42#include <linux/wait.h>
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +053043#include <linux/pm_qos.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030044
45#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053046#include <mach/clk.h>
47#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053048#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080049#include <linux/spinlock.h>
Hemant Kumar45d211b2012-05-31 17:58:43 -070050#include <linux/cpu.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030051#include <mach/rpm-regulator.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053052
53#define MSM_USB_BASE (hcd->regs)
Hemant Kumar105d07f2012-07-02 15:33:07 -070054#define USB_REG_START_OFFSET 0x90
55#define USB_REG_END_OFFSET 0x250
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053056
Hemant Kumar2309eaa2012-08-14 16:46:42 -070057static struct workqueue_struct *ehci_wq;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070058struct ehci_timer {
59#define GPT_LD(p) ((p) & 0x00FFFFFF)
60 u32 gptimer0_ld;
61#define GPT_RUN BIT(31)
62#define GPT_RESET BIT(30)
63#define GPT_MODE BIT(24)
64#define GPT_CNT(p) ((p) & 0x00FFFFFF)
65 u32 gptimer0_ctrl;
66
67 u32 gptimer1_ld;
68 u32 gptimer1_ctrl;
69};
Hemant Kumar2309eaa2012-08-14 16:46:42 -070070
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053071struct msm_hsic_hcd {
72 struct ehci_hcd ehci;
Hemant Kumard343c012012-09-06 19:57:14 -070073 spinlock_t wakeup_lock;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053074 struct device *dev;
75 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080076 struct clk *core_clk;
77 struct clk *alt_core_clk;
78 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053079 struct clk *cal_clk;
80 struct regulator *hsic_vddcx;
Ofir Cohen4cc55372012-11-20 11:17:24 +020081 struct regulator *hsic_gdsc;
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +053082 atomic_t async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053083 atomic_t in_lpm;
Sudhir Sharma1673e302012-08-27 17:37:24 -070084 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080085 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080086 int wakeup_irq;
Jack Phamfe441ea2012-03-23 17:03:15 -070087 bool wakeup_irq_enabled;
Manu Gautam3fb60ca2013-02-13 18:33:33 +053088 int async_irq;
89 uint32_t async_int_cnt;
Sudhir Sharma1673e302012-08-27 17:37:24 -070090 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080091 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070092 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030093 enum usb_vdd_type vdd_type;
Hemant Kumar2309eaa2012-08-14 16:46:42 -070094
95 struct work_struct bus_vote_w;
96 bool bus_vote;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -070097
98 /* gp timer */
99 struct ehci_timer __iomem *timer;
100 struct completion gpt0_completion;
101 struct completion rt_completion;
102 int resume_status;
103 int resume_again;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +0530104
105 struct pm_qos_request pm_qos_req_dma;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530106};
107
Hemant Kumar105d07f2012-07-02 15:33:07 -0700108struct msm_hsic_hcd *__mehci;
109
Hemant Kumare6275972012-02-29 20:06:21 -0800110static bool debug_bus_voting_enabled = true;
Ofir Cohen4cc55372012-11-20 11:17:24 +0200111static u64 ehci_msm_hsic_dma_mask = DMA_BIT_MASK(32);
112
Manu Gautam863b74132012-11-21 14:30:04 +0530113static struct platform_driver ehci_msm_hsic_driver;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700114
Hemant Kumar4d50a432012-08-15 09:06:35 -0700115static unsigned int enable_payload_log = 1;
116module_param(enable_payload_log, uint, S_IRUGO | S_IWUSR);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700117static unsigned int enable_dbg_log = 1;
118module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
119/*by default log ep0 and efs sync ep*/
120static unsigned int ep_addr_rxdbg_mask = 9;
121module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
122static unsigned int ep_addr_txdbg_mask = 9;
123module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
124
125/* Maximum debug message length */
Hemant Kumar4d50a432012-08-15 09:06:35 -0700126#define DBG_MSG_LEN 128UL
Hemant Kumar45d211b2012-05-31 17:58:43 -0700127
128/* Maximum number of messages */
129#define DBG_MAX_MSG 256UL
130
131#define TIME_BUF_LEN 20
Hemant Kumar4d50a432012-08-15 09:06:35 -0700132#define HEX_DUMP_LEN 72
Hemant Kumar45d211b2012-05-31 17:58:43 -0700133
134enum event_type {
135 EVENT_UNDEF = -1,
136 URB_SUBMIT,
137 URB_COMPLETE,
138 EVENT_NONE,
139};
140
141#define EVENT_STR_LEN 5
142
Hemant Kumar45d211b2012-05-31 17:58:43 -0700143static enum event_type str_to_event(const char *name)
144{
145 if (!strncasecmp("S", name, EVENT_STR_LEN))
146 return URB_SUBMIT;
147 if (!strncasecmp("C", name, EVENT_STR_LEN))
148 return URB_COMPLETE;
149 if (!strncasecmp("", name, EVENT_STR_LEN))
150 return EVENT_NONE;
151
152 return EVENT_UNDEF;
153}
154
155/*log ep0 activity*/
156static struct {
157 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
158 unsigned idx; /* index */
159 rwlock_t lck; /* lock */
160} dbg_hsic_ctrl = {
161 .idx = 0,
162 .lck = __RW_LOCK_UNLOCKED(lck)
163};
164
165static struct {
166 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
167 unsigned idx; /* index */
168 rwlock_t lck; /* lock */
169} dbg_hsic_data = {
170 .idx = 0,
171 .lck = __RW_LOCK_UNLOCKED(lck)
172};
173
174/**
175 * dbg_inc: increments debug event index
176 * @idx: buffer index
177 */
178static void dbg_inc(unsigned *idx)
179{
180 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
181}
182
183/*get_timestamp - returns time of day in us */
184static char *get_timestamp(char *tbuf)
185{
186 unsigned long long t;
187 unsigned long nanosec_rem;
188
189 t = cpu_clock(smp_processor_id());
190 nanosec_rem = do_div(t, 1000000000)/1000;
191 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
192 nanosec_rem);
193 return tbuf;
194}
195
196static int allow_dbg_log(int ep_addr)
197{
198 int dir, num;
199
200 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
201 num = ep_addr & ~USB_DIR_IN;
202 num = 1 << num;
203
204 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
205 return 1;
206 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
207 return 1;
208
209 return 0;
210}
211
Hemant Kumar4d50a432012-08-15 09:06:35 -0700212static char *get_hex_data(char *dbuf, struct urb *urb, int event, int status)
213{
214 int ep_addr = urb->ep->desc.bEndpointAddress;
215 char *ubuf = urb->transfer_buffer;
216 size_t len = event ? \
217 urb->actual_length : urb->transfer_buffer_length;
218
219 if (status == -EINPROGRESS)
220 status = 0;
221
222 /*Only dump ep in completions and epout submissions*/
223 if (len && !status &&
224 (((ep_addr & USB_DIR_IN) && event) ||
225 (!(ep_addr & USB_DIR_IN) && !event))) {
226 if (len >= 32)
227 len = 32;
228 hex_dump_to_buffer(ubuf, len, 32, 4, dbuf, HEX_DUMP_LEN, 0);
229 } else {
230 dbuf = "";
231 }
232
233 return dbuf;
234}
235
Hemant Kumar45d211b2012-05-31 17:58:43 -0700236static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
237{
238 unsigned long flags;
239 int ep_addr;
240 char tbuf[TIME_BUF_LEN];
Hemant Kumar4d50a432012-08-15 09:06:35 -0700241 char dbuf[HEX_DUMP_LEN];
Hemant Kumar45d211b2012-05-31 17:58:43 -0700242
243 if (!enable_dbg_log)
244 return;
245
246 if (!urb) {
247 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
248 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700249 "%s: %s : %u", get_timestamp(tbuf), event, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700250 dbg_inc(&dbg_hsic_ctrl.idx);
251 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
252 return;
253 }
254
255 ep_addr = urb->ep->desc.bEndpointAddress;
256 if (!allow_dbg_log(ep_addr))
257 return;
258
259 if ((ep_addr & 0x0f) == 0x0) {
260 /*submit event*/
261 if (!str_to_event(event)) {
262 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
263 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
264 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
Hemant Kumar4d50a432012-08-15 09:06:35 -0700265 "%02x %02x %04x %04x %04x %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700266 get_timestamp(tbuf), event, urb,
267 (ep_addr & USB_DIR_IN) ? "in" : "out",
268 urb->setup_packet[0], urb->setup_packet[1],
269 (urb->setup_packet[3] << 8) |
270 urb->setup_packet[2],
271 (urb->setup_packet[5] << 8) |
272 urb->setup_packet[4],
273 (urb->setup_packet[7] << 8) |
274 urb->setup_packet[6],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700275 urb->transfer_buffer_length, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700276
277 dbg_inc(&dbg_hsic_ctrl.idx);
278 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
279 } else {
280 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
281 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
Hemant Kumar4d50a432012-08-15 09:06:35 -0700282 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700283 get_timestamp(tbuf), event, urb,
284 (ep_addr & USB_DIR_IN) ? "in" : "out",
285 urb->actual_length, extra);
286
287 dbg_inc(&dbg_hsic_ctrl.idx);
288 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
289 }
290 } else {
291 write_lock_irqsave(&dbg_hsic_data.lck, flags);
292 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
Hemant Kumar4d50a432012-08-15 09:06:35 -0700293 "%s: [%s : %p]:ep%d[%s] %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700294 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
295 (ep_addr & USB_DIR_IN) ? "in" : "out",
296 str_to_event(event) ? urb->actual_length :
Hemant Kumar4d50a432012-08-15 09:06:35 -0700297 urb->transfer_buffer_length, extra,
298 enable_payload_log ? get_hex_data(dbuf, urb,
299 str_to_event(event), extra) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700300
301 dbg_inc(&dbg_hsic_data.idx);
302 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
303 }
304}
305
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530306static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
307{
308 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
309}
310
311static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
312{
313 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
314}
315
Hemant Kumar105d07f2012-07-02 15:33:07 -0700316static void dump_hsic_regs(struct usb_hcd *hcd)
317{
318 int i;
319 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
320
321 if (atomic_read(&mehci->in_lpm))
322 return;
323
324 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
325 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
326 readl_relaxed(hcd->regs + i),
327 readl_relaxed(hcd->regs + i + 4),
328 readl_relaxed(hcd->regs + i + 8),
329 readl_relaxed(hcd->regs + i + 0xc));
330}
331
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530332#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
333
Amit Blayd6ea6102012-06-07 16:26:24 +0300334#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Hemant Kumar3b743cd2012-10-17 13:48:10 -0700335#define USB_PHY_VDD_DIG_VOL_MIN 945000 /* uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700336#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530337
Lena Salman8c8ba382012-02-14 15:59:31 +0200338#define HSIC_DBG1_REG 0x38
339
Amit Blayd6ea6102012-06-07 16:26:24 +0300340static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
341 { /* VDD_CX CORNER Voting */
342 [VDD_NONE] = RPM_VREG_CORNER_NONE,
343 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
344 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
345 },
346 { /* VDD_CX Voltage Voting */
347 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
348 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
349 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
350 },
351};
352
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530353static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
354{
355 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300356 int none_vol, min_vol, max_vol;
357
358 if (!mehci->hsic_vddcx) {
359 mehci->vdd_type = VDDCX_CORNER;
360 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
361 "hsic_vdd_dig");
362 if (IS_ERR(mehci->hsic_vddcx)) {
363 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
364 "HSIC_VDDCX");
365 if (IS_ERR(mehci->hsic_vddcx)) {
366 dev_err(mehci->dev, "unable to get hsic vddcx\n");
367 return PTR_ERR(mehci->hsic_vddcx);
368 }
369 mehci->vdd_type = VDDCX;
370 }
371 }
372
373 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
374 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
375 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530376
377 if (!init)
378 goto disable_reg;
379
Amit Blayd6ea6102012-06-07 16:26:24 +0300380 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530381 if (ret) {
382 dev_err(mehci->dev, "unable to set the voltage"
383 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530384 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530385 }
386
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530387 ret = regulator_enable(mehci->hsic_vddcx);
388 if (ret) {
389 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
390 goto reg_enable_err;
391 }
392
393 return 0;
394
395disable_reg:
396 regulator_disable(mehci->hsic_vddcx);
397reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300398 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
399
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530400 return ret;
401
402}
403
Ofir Cohen4cc55372012-11-20 11:17:24 +0200404/* Global Distributed Switch Controller (GDSC) init */
405static int msm_hsic_init_gdsc(struct msm_hsic_hcd *mehci, int init)
406{
407 int ret = 0;
408
409 if (IS_ERR(mehci->hsic_gdsc))
410 return 0;
411
412 if (!mehci->hsic_gdsc) {
413 mehci->hsic_gdsc = devm_regulator_get(mehci->dev,
414 "HSIC_GDSC");
415 if (IS_ERR(mehci->hsic_gdsc))
416 return 0;
417 }
418
419 if (init) {
420 ret = regulator_enable(mehci->hsic_gdsc);
421 if (ret) {
422 dev_err(mehci->dev, "unable to enable hsic gdsc\n");
423 return ret;
424 }
425 } else {
426 regulator_disable(mehci->hsic_gdsc);
427 }
428
429 return 0;
430
431}
432
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700433static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
434{
435 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700436 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700437
438 /* initiate read operation */
439 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
440 USB_ULPI_VIEWPORT);
441
442 /* wait for completion */
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700443 while (cnt < ULPI_IO_TIMEOUT_USEC) {
444 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
445 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700446 udelay(1);
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700447 cnt++;
448 }
449
450 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
451 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
452 readl_relaxed(USB_ULPI_VIEWPORT));
453 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
454 readl_relaxed(USB_PORTSC),
455 readl_relaxed(USB_USBCMD),
456 readl_relaxed(USB_FRINDEX));
457
458 /*frame counter increments afte 125us*/
459 udelay(130);
460 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
461 readl_relaxed(USB_FRINDEX));
462 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700463 }
464
465 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
466}
467
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530468static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
469{
470 struct usb_hcd *hcd = hsic_to_hcd(mehci);
471 int cnt = 0;
472
473 /* initiate write operation */
474 writel_relaxed(ULPI_RUN | ULPI_WRITE |
475 ULPI_ADDR(reg) | ULPI_DATA(val),
476 USB_ULPI_VIEWPORT);
477
478 /* wait for completion */
479 while (cnt < ULPI_IO_TIMEOUT_USEC) {
480 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
481 break;
482 udelay(1);
483 cnt++;
484 }
485
486 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Hemant Kumar8fdc3982012-08-21 12:22:27 -0700487 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
488 readl_relaxed(USB_ULPI_VIEWPORT));
489 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
490 readl_relaxed(USB_PORTSC),
491 readl_relaxed(USB_USBCMD),
492 readl_relaxed(USB_FRINDEX));
493
494 /*frame counter increments afte 125us*/
495 udelay(130);
496 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
497 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530498 return -ETIMEDOUT;
499 }
500
501 return 0;
502}
503
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700504#define HSIC_DBG1 0X38
505#define ULPI_MANUAL_ENABLE BIT(4)
506#define ULPI_LINESTATE_DATA BIT(5)
507#define ULPI_LINESTATE_STROBE BIT(6)
508static void ehci_msm_enable_ulpi_control(struct usb_hcd *hcd, u32 linestate)
509{
510 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
511 int val;
512
513 switch (linestate) {
514 case PORT_RESET:
515 val = ulpi_read(mehci, HSIC_DBG1);
516 val |= ULPI_MANUAL_ENABLE;
517 val &= ~(ULPI_LINESTATE_DATA | ULPI_LINESTATE_STROBE);
518 ulpi_write(mehci, val, HSIC_DBG1);
519 break;
520 default:
521 pr_info("%s: Unknown linestate:%0x\n", __func__, linestate);
522 }
523}
524
525static void ehci_msm_disable_ulpi_control(struct usb_hcd *hcd)
526{
527 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
528 int val;
529
530 val = ulpi_read(mehci, HSIC_DBG1);
531 val &= ~ULPI_MANUAL_ENABLE;
532 ulpi_write(mehci, val, HSIC_DBG1);
533}
534
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530535static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
536{
537 int rc = 0;
538 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800539 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530540
541 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800542
Lena Salman8c8ba382012-02-14 15:59:31 +0200543 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530544 return rc;
545
Vamsi Krishna34f01582011-12-14 19:54:42 -0800546 if (gpio_status == gpio_en)
547 return 0;
548
549 gpio_status = gpio_en;
550
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530551 if (!gpio_en)
552 goto free_gpio;
553
554 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
555 if (rc < 0) {
556 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
557 return rc;
558 }
559
560 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
561 if (rc < 0) {
562 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
563 goto free_strobe;
Hemant Kumar6fd65032012-05-23 13:02:24 -0700564 }
565
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530566 return 0;
567
568free_gpio:
569 gpio_free(pdata->data);
570free_strobe:
571 gpio_free(pdata->strobe);
572
573 return rc;
574}
575
Vamsi Krishna64b48612012-06-14 16:08:11 -0700576static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530577{
578 int ret;
579
Ofir Cohen07944aa2012-12-23 13:41:57 +0200580 /* alt_core_clk exists in targets that do not use asynchronous reset */
581 if (!IS_ERR(mehci->alt_core_clk)) {
582 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
583 if (ret) {
584 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
585 return;
586 }
587
588 /* Since a hw bug, turn off the clock before complete reset */
589 clk_disable(mehci->core_clk);
590
591 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
592 if (ret)
593 dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
594 ret);
595
596 usleep_range(10000, 12000);
597
598 clk_enable(mehci->core_clk);
599 } else {
600 /* Using asynchronous block reset to the hardware */
601 clk_disable_unprepare(mehci->core_clk);
602 clk_disable_unprepare(mehci->phy_clk);
603 clk_disable_unprepare(mehci->cal_clk);
604 clk_disable_unprepare(mehci->ahb_clk);
605
606 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
607 if (ret) {
608 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
609 return;
610 }
611 usleep_range(10000, 12000);
612
613 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
614 if (ret)
615 dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
616 ret);
617 /*
618 * Required delay between the deassertion and
619 * clock enablement.
620 */
621 ndelay(200);
622 clk_prepare_enable(mehci->core_clk);
623 clk_prepare_enable(mehci->phy_clk);
624 clk_prepare_enable(mehci->cal_clk);
625 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530626 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530627}
628
Vamsi Krishna64b48612012-06-14 16:08:11 -0700629#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
630#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530631#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
632#define HSIC_LV_MODE 0x04
633#define HSIC_PAD_CALIBRATION 0xA8
634#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530635#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
Ofir Cohen5dddb152012-11-14 11:18:50 +0200636
637static void msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530638{
639 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530640
Vamsi Krishna64b48612012-06-14 16:08:11 -0700641 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530642
Vamsi Krishna64b48612012-06-14 16:08:11 -0700643 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530644 writel_relaxed(0x80000000, USB_PORTSC);
Vamsi Krishna64b48612012-06-14 16:08:11 -0700645 mb();
Ofir Cohen5dddb152012-11-14 11:18:50 +0200646}
647
648static int msm_hsic_start(struct msm_hsic_hcd *mehci)
649{
650 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
651 int ret;
Manu Gautam863b74132012-11-21 14:30:04 +0530652 void __iomem *reg;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530653
Lena Salman8c8ba382012-02-14 15:59:31 +0200654 /* HSIC init sequence when HSIC signals (Strobe/Data) are
655 routed via GPIOs */
656 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530657
Manu Gautam863b74132012-11-21 14:30:04 +0530658 if (!pdata->ignore_cal_pad_config) {
659 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
660 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
661 mb();
662 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700663
Lena Salman8c8ba382012-02-14 15:59:31 +0200664 /*set periodic calibration interval to ~2.048sec in
665 HSIC_IO_CAL_REG */
666 ulpi_write(mehci, 0xFF, 0x33);
667
668 /* Enable periodic IO calibration in HSIC_CFG register */
669 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
670
Vamsi Krishna64b48612012-06-14 16:08:11 -0700671 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200672 ret = msm_hsic_config_gpios(mehci, 1);
673 if (ret) {
674 dev_err(mehci->dev, " gpio configuarion failed\n");
675 return ret;
676 }
Manu Gautam863b74132012-11-21 14:30:04 +0530677 if (pdata->strobe_pad_offset) {
678 /* Set CORE_CTL_EN in STROBE GPIO PAD_CTL register */
679 reg = MSM_TLMM_BASE + pdata->strobe_pad_offset;
680 writel_relaxed(readl_relaxed(reg) | 0x2000000, reg);
681 } else {
682 /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */
683 reg = HSIC_STROBE_GPIO_PAD_CTL;
684 writel_relaxed(HSIC_GPIO_PAD_VAL, reg);
685 }
686
687 if (pdata->data_pad_offset) {
688 /* Set CORE_CTL_EN in HSIC_DATA GPIO PAD_CTL register */
689 reg = MSM_TLMM_BASE + pdata->data_pad_offset;
690 writel_relaxed(readl_relaxed(reg) | 0x2000000, reg);
691 } else {
692 /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */
693 reg = HSIC_DATA_GPIO_PAD_CTL;
694 writel_relaxed(HSIC_GPIO_PAD_VAL, reg);
695 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700696
697 mb();
698
Lena Salman8c8ba382012-02-14 15:59:31 +0200699 /* Enable HSIC mode in HSIC_CFG register */
700 ulpi_write(mehci, 0x01, 0x31);
701 } else {
702 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
703 via dedicated I/O */
704
705 /* programmable length of connect signaling (33.2ns) */
706 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
707 if (ret) {
708 pr_err("%s: Unable to program length of connect "
709 "signaling\n", __func__);
710 }
711
712 /*set periodic calibration interval to ~2.048sec in
713 HSIC_IO_CAL_REG */
714 ulpi_write(mehci, 0xFF, 0x33);
715
716 /* Enable HSIC mode in HSIC_CFG register */
717 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530718 }
719
Hemant Kumar6fd65032012-05-23 13:02:24 -0700720 /*disable auto resume*/
721 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
722
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530723 return 0;
724}
725
726#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
727#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
728
729#ifdef CONFIG_PM_SLEEP
Ofir Cohen5dddb152012-11-14 11:18:50 +0200730static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
731{
732 /* reset HSIC phy */
733 msm_hsic_phy_reset(mehci);
734
735 /* HSIC init procedure (caliberation) */
736 return msm_hsic_start(mehci);
737}
738
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530739static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
740{
741 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530742 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530743 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300744 int none_vol, max_vol;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700745 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530746
747 if (atomic_read(&mehci->in_lpm)) {
748 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
749 return 0;
750 }
751
752 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700753
Sudhir Sharma1673e302012-08-27 17:37:24 -0700754 /* make sure we don't race against a remote wakeup */
755 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700756 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Sudhir Sharma1673e302012-08-27 17:37:24 -0700757 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700758 enable_irq(hcd->irq);
759 return -EBUSY;
760 }
761
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530762 /*
763 * PHY may take some time or even fail to enter into low power
764 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
765 * in failure case.
766 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700767 val = readl_relaxed(USB_PORTSC);
768 val &= ~PORT_RWC_BITS;
769 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530770 writel_relaxed(val, USB_PORTSC);
771 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
772 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
773 break;
774 udelay(1);
775 cnt++;
776 }
777
778 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
779 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530780 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530781 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530782 }
783
784 /*
785 * PHY has capability to generate interrupt asynchronously in low
786 * power mode (LPM). This interrupt is level triggered. So USB IRQ
787 * line must be disabled till async interrupt enable bit is cleared
788 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
Pavankumar Kondeti0c9f29c2013-01-28 21:37:59 +0530789 * block data communication from PHY. Enable asynchronous interrupt
790 * only when wakeup gpio IRQ is not present.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530791 */
Pavankumar Kondeti0c9f29c2013-01-28 21:37:59 +0530792 if (mehci->wakeup_irq)
793 writel_relaxed(readl_relaxed(USB_USBCMD) |
794 ULPI_STP_CTRL, USB_USBCMD);
795 else
796 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530797 ULPI_STP_CTRL, USB_USBCMD);
798
799 /*
800 * Ensure that hardware is put in low power mode before
801 * clocks are turned OFF and VDD is allowed to minimize.
802 */
803 mb();
804
Manu Gautam28b1bac2012-01-30 16:43:06 +0530805 clk_disable_unprepare(mehci->core_clk);
806 clk_disable_unprepare(mehci->phy_clk);
807 clk_disable_unprepare(mehci->cal_clk);
808 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530809
Amit Blayd6ea6102012-06-07 16:26:24 +0300810 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
811 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
812
813 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700814 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300815 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700816
Hemant Kumare6275972012-02-29 20:06:21 -0800817 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700818 mehci->bus_vote = false;
819 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800820 }
821
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530822 atomic_set(&mehci->in_lpm, 1);
823 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700824
Manu Gautam3fb60ca2013-02-13 18:33:33 +0530825 if (mehci->wakeup_irq) {
826 mehci->wakeup_irq_enabled = 1;
827 enable_irq_wake(mehci->wakeup_irq);
828 enable_irq(mehci->wakeup_irq);
829 }
Hemant Kumar6fd65032012-05-23 13:02:24 -0700830
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700831 if (pdata && pdata->standalone_latency)
832 pm_qos_update_request(&mehci->pm_qos_req_dma,
833 PM_QOS_DEFAULT_VALUE);
834
Sudhir Sharma1673e302012-08-27 17:37:24 -0700835 wake_unlock(&mehci->wlock);
836
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530837 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
838
839 return 0;
840}
841
842static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
843{
844 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530845 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530846 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300847 int min_vol, max_vol;
Hemant Kumard343c012012-09-06 19:57:14 -0700848 unsigned long flags;
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700849 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530850
851 if (!atomic_read(&mehci->in_lpm)) {
852 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
853 return 0;
854 }
855
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530856 /* Handles race with Async interrupt */
857 disable_irq(hcd->irq);
858
Hemant Kumarbc8bdf62012-10-17 12:29:51 -0700859 if (pdata && pdata->standalone_latency)
860 pm_qos_update_request(&mehci->pm_qos_req_dma,
861 pdata->standalone_latency + 1);
862
Manu Gautam3fb60ca2013-02-13 18:33:33 +0530863 if (mehci->wakeup_irq) {
864 spin_lock_irqsave(&mehci->wakeup_lock, flags);
865 if (mehci->wakeup_irq_enabled) {
866 disable_irq_wake(mehci->wakeup_irq);
867 disable_irq_nosync(mehci->wakeup_irq);
868 mehci->wakeup_irq_enabled = 0;
869 }
870 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700871 }
872
Sudhir Sharma1673e302012-08-27 17:37:24 -0700873 wake_lock(&mehci->wlock);
874
Hemant Kumare6275972012-02-29 20:06:21 -0800875 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700876 mehci->bus_vote = true;
877 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800878 }
879
Amit Blayd6ea6102012-06-07 16:26:24 +0300880 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
881 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
882
883 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700884 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300885 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700886
Manu Gautam28b1bac2012-01-30 16:43:06 +0530887 clk_prepare_enable(mehci->core_clk);
888 clk_prepare_enable(mehci->phy_clk);
889 clk_prepare_enable(mehci->cal_clk);
890 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530891
892 temp = readl_relaxed(USB_USBCMD);
893 temp &= ~ASYNC_INTR_CTRL;
894 temp &= ~ULPI_STP_CTRL;
895 writel_relaxed(temp, USB_USBCMD);
896
897 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
898 goto skip_phy_resume;
899
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700900 temp = readl_relaxed(USB_PORTSC);
901 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530902 writel_relaxed(temp, USB_PORTSC);
903 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
904 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
905 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
906 break;
907 udelay(1);
908 cnt++;
909 }
910
911 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
912 /*
913 * This is a fatal error. Reset the link and
914 * PHY to make hsic working.
915 */
916 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530917 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530918 msm_hsic_reset(mehci);
919 }
920
921skip_phy_resume:
922
Hemant Kumar6fd65032012-05-23 13:02:24 -0700923 usb_hcd_resume_root_hub(hcd);
924
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530925 atomic_set(&mehci->in_lpm, 0);
926
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530927 if (atomic_read(&mehci->async_int)) {
928 atomic_set(&mehci->async_int, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530929 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700930 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700931 }
932
Sudhir Sharma1673e302012-08-27 17:37:24 -0700933 if (atomic_read(&mehci->pm_usage_cnt)) {
934 atomic_set(&mehci->pm_usage_cnt, 0);
935 pm_runtime_put_noidle(mehci->dev);
936 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700937
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530938 enable_irq(hcd->irq);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530939 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
940
941 return 0;
942}
943#endif
944
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700945static void ehci_hsic_bus_vote_w(struct work_struct *w)
946{
947 struct msm_hsic_hcd *mehci =
948 container_of(w, struct msm_hsic_hcd, bus_vote_w);
949 int ret;
950
951 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
952 mehci->bus_vote);
953 if (ret)
954 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
955 __func__, ret);
956}
957
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700958#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530959static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
960{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700961 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530962 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700963 u32 status;
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530964 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530965
966 if (atomic_read(&mehci->in_lpm)) {
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700967 dev_dbg(mehci->dev, "phy async intr\n");
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +0530968 dbg_log_event(NULL, "Async IRQ", 0);
969 ret = pm_runtime_get(mehci->dev);
970 if ((ret == 1) || (ret == -EINPROGRESS)) {
971 pm_runtime_put_noidle(mehci->dev);
972 } else {
973 disable_irq_nosync(hcd->irq);
974 atomic_set(&mehci->async_int, 1);
975 }
976
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530977 return IRQ_HANDLED;
978 }
979
Vamsi Krishnafce1bd22012-08-17 17:12:26 -0700980 status = ehci_readl(ehci, &ehci->regs->status);
981
982 if (status & STS_GPTIMER0_INTERRUPT) {
983 int timeleft;
984
985 dbg_log_event(NULL, "FPR: gpt0_isr", 0);
986
987 timeleft = GPT_CNT(ehci_readl(ehci,
988 &mehci->timer->gptimer1_ctrl));
989 if (timeleft) {
990 ehci_writel(ehci, ehci_readl(ehci,
991 &ehci->regs->command) | CMD_RUN,
992 &ehci->regs->command);
993 } else
994 mehci->resume_again = 1;
995
996 dbg_log_event(NULL, "FPR: timeleft", timeleft);
997
998 complete(&mehci->gpt0_completion);
999 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
1000 }
1001
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301002 return ehci_irq(hcd);
1003}
1004
1005static int ehci_hsic_reset(struct usb_hcd *hcd)
1006{
1007 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001008 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301009 int retval;
1010
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001011 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301012 ehci->caps = USB_CAPLENGTH;
1013 ehci->regs = USB_CAPLENGTH +
1014 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
1015 dbg_hcs_params(ehci, "reset");
1016 dbg_hcc_params(ehci, "reset");
1017
1018 /* cache the data to minimize the chip reads*/
1019 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
1020
1021 hcd->has_tt = 1;
1022 ehci->sbrn = HCD_USB2;
1023
1024 retval = ehci_halt(ehci);
1025 if (retval)
1026 return retval;
1027
1028 /* data structure init */
1029 retval = ehci_init(hcd);
1030 if (retval)
1031 return retval;
1032
1033 retval = ehci_reset(ehci);
1034 if (retval)
1035 return retval;
1036
1037 /* bursts of unspecified length. */
1038 writel_relaxed(0, USB_AHBBURST);
1039 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +05301040 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301041 /* Disable streaming mode and select host mode */
1042 writel_relaxed(0x13, USB_USBMODE);
1043
1044 ehci_port_power(ehci, 1);
1045 return 0;
1046}
1047
Jack Phamc0d41732012-09-28 17:45:38 -07001048#ifdef CONFIG_PM
1049
Hemant Kumar45d211b2012-05-31 17:58:43 -07001050static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
1051{
Pavankumar Kondetia723f742012-09-14 14:02:36 +05301052 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1053
1054 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
1055 dbg_log_event(NULL, "RH suspend attempt failed", 0);
1056 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
1057 __func__);
1058 return -EAGAIN;
1059 }
1060
Hemant Kumar45d211b2012-05-31 17:58:43 -07001061 dbg_log_event(NULL, "Suspend RH", 0);
1062 return ehci_bus_suspend(hcd);
1063}
1064
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001065#define RESUME_RETRY_LIMIT 3
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301066#define RESUME_SIGNAL_TIME_USEC (21 * 1000)
1067#define RESUME_SIGNAL_TIME_SOF_USEC (23 * 1000)
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001068static int msm_hsic_resume_thread(void *data)
1069{
1070 struct msm_hsic_hcd *mehci = data;
1071 struct usb_hcd *hcd = hsic_to_hcd(mehci);
1072 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1073 u32 temp;
1074 unsigned long resume_needed = 0;
1075 int retry_cnt = 0;
1076 int tight_resume = 0;
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301077 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001078
1079 dbg_log_event(NULL, "Resume RH", 0);
1080
1081 /* keep delay between bus states */
1082 if (time_before(jiffies, ehci->next_statechange))
1083 usleep_range(5000, 5000);
1084
1085 spin_lock_irq(&ehci->lock);
1086 if (!HCD_HW_ACCESSIBLE(hcd)) {
1087 spin_unlock_irq(&ehci->lock);
1088 mehci->resume_status = -ESHUTDOWN;
1089 complete(&mehci->rt_completion);
1090 return 0;
1091 }
1092
1093 if (unlikely(ehci->debug)) {
1094 if (!dbgp_reset_prep())
1095 ehci->debug = NULL;
1096 else
1097 dbgp_external_startup();
1098 }
1099
1100 /* at least some APM implementations will try to deliver
1101 * IRQs right away, so delay them until we're ready.
1102 */
1103 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
1104
1105 /* re-init operational registers */
1106 ehci_writel(ehci, 0, &ehci->regs->segment);
1107 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
1108 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
1109
1110 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
1111 if (ehci->resume_sof_bug)
1112 ehci->command &= ~CMD_RUN;
1113
1114 /* restore CMD_RUN, framelist size, and irq threshold */
1115 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1116
1117 /* manually resume the ports we suspended during bus_suspend() */
1118resume_again:
1119 if (retry_cnt >= RESUME_RETRY_LIMIT) {
1120 pr_info("retry count(%d) reached max, resume in tight loop\n",
1121 retry_cnt);
1122 tight_resume = 1;
1123 }
1124
1125
1126 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1127 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
1128 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
1129 temp |= PORT_RESUME;
1130 set_bit(0, &resume_needed);
1131 }
1132 dbg_log_event(NULL, "FPR: Set", temp);
1133 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1134
1135 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1136 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1137 * controller in MSM clears FPR bit after driving the resume signal for
1138 * 20ms. Workaround is to stop SOFs before driving resume and then start
1139 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1140 * completion otherwise peripheral may enter undefined state. As
1141 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1142 * to time the resume sequence. If driver exceeds allowable time SOFs,
1143 * repeat the resume process.
1144 */
1145 if (ehci->resume_sof_bug && resume_needed) {
1146 if (!tight_resume) {
1147 mehci->resume_again = 0;
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301148 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_USEC - 1),
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001149 &mehci->timer->gptimer0_ld);
1150 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1151 &mehci->timer->gptimer0_ctrl);
1152 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1153 &ehci->regs->intr_enable);
1154
Pavankumar Kondetic4f817d2013-01-29 19:08:12 +05301155 ehci_writel(ehci, GPT_LD(
1156 RESUME_SIGNAL_TIME_SOF_USEC - 1),
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001157 &mehci->timer->gptimer1_ld);
1158 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1159 &mehci->timer->gptimer1_ctrl);
1160
1161 spin_unlock_irq(&ehci->lock);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301162 if (pdata && pdata->swfi_latency)
1163 pm_qos_update_request(&mehci->pm_qos_req_dma,
1164 pdata->swfi_latency + 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001165 wait_for_completion(&mehci->gpt0_completion);
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001166 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301167 pm_qos_update_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001168 pdata->standalone_latency + 1);
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001169 spin_lock_irq(&ehci->lock);
1170 } else {
1171 dbg_log_event(NULL, "FPR: Tightloop", 0);
1172 /* do the resume in a tight loop */
1173 handshake(ehci, &ehci->regs->port_status[0],
1174 PORT_RESUME, 0, 22 * 1000);
1175 ehci_writel(ehci, ehci_readl(ehci,
1176 &ehci->regs->command) | CMD_RUN,
1177 &ehci->regs->command);
1178 }
1179
1180 if (mehci->resume_again) {
1181 int temp;
1182
1183 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1184 pr_info("FPR: retry count: %d\n", retry_cnt);
1185 spin_unlock_irq(&ehci->lock);
1186 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1187 temp &= ~PORT_RWC_BITS;
1188 temp |= PORT_SUSPEND;
1189 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1190 /* Keep the bus idle for 5ms so that peripheral
1191 * can detect and initiate suspend
1192 */
1193 usleep_range(5000, 5000);
1194 dbg_log_event(NULL,
1195 "FPR: RResume",
1196 ehci_readl(ehci, &ehci->regs->port_status[0]));
1197 spin_lock_irq(&ehci->lock);
1198 mehci->resume_again = 0;
1199 retry_cnt++;
1200 goto resume_again;
1201 }
1202 }
1203
1204 dbg_log_event(NULL, "FPR: RT-Done", 0);
1205 mehci->resume_status = 1;
1206 spin_unlock_irq(&ehci->lock);
1207
1208 complete(&mehci->rt_completion);
1209
1210 return 0;
1211}
1212
Hemant Kumar45d211b2012-05-31 17:58:43 -07001213static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1214{
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001215 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1216 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1217 u32 temp;
1218 struct task_struct *resume_thread = NULL;
1219
1220 mehci->resume_status = 0;
1221 resume_thread = kthread_run(msm_hsic_resume_thread,
1222 mehci, "hsic_resume_thread");
1223 if (IS_ERR(resume_thread)) {
1224 pr_err("Error creating resume thread:%lu\n",
1225 PTR_ERR(resume_thread));
1226 return PTR_ERR(resume_thread);
1227 }
1228
1229 wait_for_completion(&mehci->rt_completion);
1230
1231 if (mehci->resume_status < 0)
1232 return mehci->resume_status;
1233
1234 dbg_log_event(NULL, "FPR: Wokeup", 0);
1235 spin_lock_irq(&ehci->lock);
1236 (void) ehci_readl(ehci, &ehci->regs->command);
1237
1238 temp = 0;
1239 if (ehci->async->qh_next.qh)
1240 temp |= CMD_ASE;
1241 if (ehci->periodic_sched)
1242 temp |= CMD_PSE;
1243 if (temp) {
1244 ehci->command |= temp;
1245 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1246 }
1247
1248 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1249 hcd->state = HC_STATE_RUNNING;
1250 ehci->rh_state = EHCI_RH_RUNNING;
Manu Gautam3a8eb532013-02-13 18:29:02 +05301251 ehci->command |= CMD_RUN;
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001252
1253 /* Now we can safely re-enable irqs */
1254 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1255
1256 spin_unlock_irq(&ehci->lock);
1257
1258 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001259}
1260
Jack Phamc0d41732012-09-28 17:45:38 -07001261#else
1262
1263#define ehci_hsic_bus_suspend NULL
1264#define ehci_hsic_bus_resume NULL
1265
1266#endif /* CONFIG_PM */
1267
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001268static void ehci_msm_set_autosuspend_delay(struct usb_device *dev)
1269{
1270 if (!dev->parent) /*for root hub no delay*/
1271 pm_runtime_set_autosuspend_delay(&dev->dev, 0);
1272 else
1273 pm_runtime_set_autosuspend_delay(&dev->dev, 200);
1274}
1275
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301276static struct hc_driver msm_hsic_driver = {
1277 .description = hcd_name,
1278 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1279 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1280
1281 /*
1282 * generic hardware linkage
1283 */
1284 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001285 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301286
1287 .reset = ehci_hsic_reset,
1288 .start = ehci_run,
1289
1290 .stop = ehci_stop,
1291 .shutdown = ehci_shutdown,
1292
1293 /*
1294 * managing i/o requests and associated device resources
1295 */
Hemant Kumar4d50a432012-08-15 09:06:35 -07001296 .urb_enqueue = ehci_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301297 .urb_dequeue = ehci_urb_dequeue,
1298 .endpoint_disable = ehci_endpoint_disable,
1299 .endpoint_reset = ehci_endpoint_reset,
1300 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1301
1302 /*
1303 * scheduling support
1304 */
1305 .get_frame_number = ehci_get_frame,
1306
1307 /*
1308 * root hub support
1309 */
1310 .hub_status_data = ehci_hub_status_data,
1311 .hub_control = ehci_hub_control,
1312 .relinquish_port = ehci_relinquish_port,
1313 .port_handed_over = ehci_port_handed_over,
1314
1315 /*
1316 * PM support
1317 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001318 .bus_suspend = ehci_hsic_bus_suspend,
1319 .bus_resume = ehci_hsic_bus_resume,
1320
Hemant Kumar4d50a432012-08-15 09:06:35 -07001321 .log_urb = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001322 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001323
1324 .enable_ulpi_control = ehci_msm_enable_ulpi_control,
1325 .disable_ulpi_control = ehci_msm_disable_ulpi_control,
Hemant Kumara3d4a6e2012-10-16 17:57:08 -07001326
1327 .set_autosuspend_delay = ehci_msm_set_autosuspend_delay,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301328};
1329
1330static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1331{
1332 int ret = 0;
1333
1334 if (!init)
1335 goto put_clocks;
1336
Lena Salman8c8ba382012-02-14 15:59:31 +02001337 /*core_clk is required for LINK protocol engine
1338 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001339 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1340 if (IS_ERR(mehci->core_clk)) {
1341 dev_err(mehci->dev, "failed to get core_clk\n");
1342 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301343 return ret;
1344 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301345
Ofir Cohen07944aa2012-12-23 13:41:57 +02001346 /* alt_core_clk is for LINK to be used during PHY RESET in
1347 * targets on which link does NOT use asynchronous reset methodology.
Lena Salman8c8ba382012-02-14 15:59:31 +02001348 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001349 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
Manu Gautam863b74132012-11-21 14:30:04 +05301350 if (IS_ERR(mehci->alt_core_clk))
1351 dev_dbg(mehci->dev, "failed to get alt_core_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301352
Lena Salman8c8ba382012-02-14 15:59:31 +02001353 /* phy_clk is required for HSIC PHY operation
1354 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001355 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1356 if (IS_ERR(mehci->phy_clk)) {
1357 dev_err(mehci->dev, "failed to get phy_clk\n");
1358 ret = PTR_ERR(mehci->phy_clk);
1359 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301360 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301361
1362 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001363 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301364 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001365 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301366 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001367 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301368 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301369
1370 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001371 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301372 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001373 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301374 ret = PTR_ERR(mehci->ahb_clk);
1375 goto put_cal_clk;
1376 }
1377
Manu Gautam28b1bac2012-01-30 16:43:06 +05301378 clk_prepare_enable(mehci->core_clk);
1379 clk_prepare_enable(mehci->phy_clk);
1380 clk_prepare_enable(mehci->cal_clk);
1381 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301382
1383 return 0;
1384
1385put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001386 if (!atomic_read(&mehci->in_lpm)) {
1387 clk_disable_unprepare(mehci->core_clk);
1388 clk_disable_unprepare(mehci->phy_clk);
1389 clk_disable_unprepare(mehci->cal_clk);
1390 clk_disable_unprepare(mehci->ahb_clk);
1391 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301392 clk_put(mehci->ahb_clk);
1393put_cal_clk:
1394 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001395put_phy_clk:
1396 clk_put(mehci->phy_clk);
1397put_alt_core_clk:
Manu Gautam863b74132012-11-21 14:30:04 +05301398 if (!IS_ERR(mehci->alt_core_clk))
1399 clk_put(mehci->alt_core_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001400 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301401
1402 return ret;
1403}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001404static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1405{
1406 struct msm_hsic_hcd *mehci = dev_id;
1407
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001408 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001409
1410 if (mehci)
1411 msm_hsic_config_gpios(mehci, 0);
1412
1413 return IRQ_HANDLED;
1414}
1415
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001416static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1417{
1418 struct msm_hsic_hcd *mehci = data;
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301419 int ret;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001420
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301421 if (irq == mehci->async_irq) {
1422 mehci->async_int_cnt++;
1423 dbg_log_event(NULL, "Remote Wakeup (ASYNC) IRQ",
1424 mehci->async_int_cnt);
1425 } else {
1426 mehci->wakeup_int_cnt++;
1427 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
1428 }
1429 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt %d cnt: %u, %u\n",
1430 __func__, irq, mehci->wakeup_int_cnt, mehci->async_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001431
Sudhir Sharma1673e302012-08-27 17:37:24 -07001432 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001433
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301434 if (mehci->wakeup_irq) {
1435 spin_lock(&mehci->wakeup_lock);
1436 if (mehci->wakeup_irq_enabled) {
1437 mehci->wakeup_irq_enabled = 0;
1438 disable_irq_wake(irq);
1439 disable_irq_nosync(irq);
1440 }
1441 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001442 }
1443
Sudhir Sharma1673e302012-08-27 17:37:24 -07001444 if (!atomic_read(&mehci->pm_usage_cnt)) {
Pavankumar Kondeti968cf272012-09-27 12:04:12 +05301445 ret = pm_runtime_get(mehci->dev);
1446 /*
1447 * HSIC runtime resume can race with us.
1448 * if we are active (ret == 1) or resuming
1449 * (ret == -EINPROGRESS), decrement the
1450 * PM usage counter before returning.
1451 */
1452 if ((ret == 1) || (ret == -EINPROGRESS))
1453 pm_runtime_put_noidle(mehci->dev);
1454 else
1455 atomic_set(&mehci->pm_usage_cnt, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001456 }
1457
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001458 return IRQ_HANDLED;
1459}
1460
Hemant Kumare6275972012-02-29 20:06:21 -08001461static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1462{
1463 if (debug_bus_voting_enabled)
1464 seq_printf(s, "enabled\n");
1465 else
1466 seq_printf(s, "disabled\n");
1467
1468 return 0;
1469}
1470
1471static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1472{
1473 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1474}
1475
1476static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1477 const char __user *ubuf, size_t count, loff_t *ppos)
1478{
1479 char buf[8];
1480 int ret;
1481 struct seq_file *s = file->private_data;
1482 struct msm_hsic_hcd *mehci = s->private;
1483
1484 memset(buf, 0x00, sizeof(buf));
1485
1486 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1487 return -EFAULT;
1488
1489 if (!strncmp(buf, "enable", 6)) {
1490 /* Do not vote here. Let hsic driver decide when to vote */
1491 debug_bus_voting_enabled = true;
1492 } else {
1493 debug_bus_voting_enabled = false;
1494 if (mehci->bus_perf_client) {
1495 ret = msm_bus_scale_client_update_request(
1496 mehci->bus_perf_client, 0);
1497 if (ret)
1498 dev_err(mehci->dev, "%s: Failed to devote "
1499 "for bus bw %d\n", __func__, ret);
1500 }
1501 }
1502
1503 return count;
1504}
1505
1506const struct file_operations ehci_hsic_msm_bus_fops = {
1507 .open = ehci_hsic_msm_bus_open,
1508 .read = seq_read,
1509 .write = ehci_hsic_msm_bus_write,
1510 .llseek = seq_lseek,
1511 .release = single_release,
1512};
1513
Hemant Kumar6fd65032012-05-23 13:02:24 -07001514static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1515{
1516 struct msm_hsic_hcd *mehci = s->private;
1517
1518 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1519
1520 return 0;
1521}
1522
1523static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1524{
1525 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1526}
1527
1528const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1529 .open = ehci_hsic_msm_wakeup_cnt_open,
1530 .read = seq_read,
1531 .llseek = seq_lseek,
1532 .release = single_release,
1533};
1534
Hemant Kumar45d211b2012-05-31 17:58:43 -07001535static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1536{
1537 unsigned long flags;
1538 unsigned i;
1539
1540 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1541
1542 i = dbg_hsic_data.idx;
1543 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1544 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1545 continue;
1546 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1547 }
1548
1549 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1550
1551 return 0;
1552}
1553
1554static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1555{
1556 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1557}
1558
1559const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1560 .open = ehci_hsic_msm_data_events_open,
1561 .read = seq_read,
1562 .llseek = seq_lseek,
1563 .release = single_release,
1564};
1565
1566static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1567{
1568 unsigned long flags;
1569 unsigned i;
1570
1571 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1572
1573 i = dbg_hsic_ctrl.idx;
1574 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1575 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1576 continue;
1577 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1578 }
1579
1580 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1581
1582 return 0;
1583}
1584
1585static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1586{
1587 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1588}
1589
1590const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1591 .open = ehci_hsic_msm_ctrl_events_open,
1592 .read = seq_read,
1593 .llseek = seq_lseek,
1594 .release = single_release,
1595};
1596
Hemant Kumare6275972012-02-29 20:06:21 -08001597static struct dentry *ehci_hsic_msm_dbg_root;
1598static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1599{
1600 struct dentry *ehci_hsic_msm_dentry;
1601
1602 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1603
1604 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1605 return -ENODEV;
1606
1607 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1608 S_IRUGO | S_IWUSR,
1609 ehci_hsic_msm_dbg_root, mehci,
1610 &ehci_hsic_msm_bus_fops);
1611
1612 if (!ehci_hsic_msm_dentry) {
1613 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1614 return -ENODEV;
1615 }
1616
Hemant Kumar6fd65032012-05-23 13:02:24 -07001617 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1618 S_IRUGO,
1619 ehci_hsic_msm_dbg_root, mehci,
1620 &ehci_hsic_msm_wakeup_cnt_fops);
1621
1622 if (!ehci_hsic_msm_dentry) {
1623 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1624 return -ENODEV;
1625 }
1626
Hemant Kumar45d211b2012-05-31 17:58:43 -07001627 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1628 S_IRUGO,
1629 ehci_hsic_msm_dbg_root, mehci,
1630 &ehci_hsic_msm_dbg_ctrl_fops);
1631
1632 if (!ehci_hsic_msm_dentry) {
1633 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1634 return -ENODEV;
1635 }
1636
1637 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1638 S_IRUGO,
1639 ehci_hsic_msm_dbg_root, mehci,
1640 &ehci_hsic_msm_dbg_data_fops);
1641
1642 if (!ehci_hsic_msm_dentry) {
1643 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1644 return -ENODEV;
1645 }
1646
Hemant Kumare6275972012-02-29 20:06:21 -08001647 return 0;
1648}
1649
1650static void ehci_hsic_msm_debugfs_cleanup(void)
1651{
1652 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1653}
1654
Manu Gautam863b74132012-11-21 14:30:04 +05301655struct msm_hsic_host_platform_data *msm_hsic_dt_to_pdata(
1656 struct platform_device *pdev)
1657{
1658 struct device_node *node = pdev->dev.of_node;
1659 struct msm_hsic_host_platform_data *pdata;
Ido Shayevitzca5dc492013-01-09 14:49:59 +02001660 int res_gpio;
Manu Gautam863b74132012-11-21 14:30:04 +05301661
1662 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1663 if (!pdata) {
1664 dev_err(&pdev->dev, "unable to allocate platform data\n");
1665 return NULL;
1666 }
Manu Gautam863b74132012-11-21 14:30:04 +05301667
Ido Shayevitzca5dc492013-01-09 14:49:59 +02001668 res_gpio = of_get_named_gpio(node, "hsic,strobe-gpio", 0);
1669 if (res_gpio < 0)
1670 res_gpio = 0;
1671 pdata->strobe = res_gpio;
1672
1673 res_gpio = of_get_named_gpio(node, "hsic,data-gpio", 0);
1674 if (res_gpio < 0)
1675 res_gpio = 0;
1676 pdata->data = res_gpio;
Manu Gautam863b74132012-11-21 14:30:04 +05301677
1678 pdata->ignore_cal_pad_config = of_property_read_bool(node,
1679 "hsic,ignore-cal-pad-config");
1680 of_property_read_u32(node, "hsic,strobe-pad-offset",
1681 &pdata->strobe_pad_offset);
1682 of_property_read_u32(node, "hsic,data-pad-offset",
1683 &pdata->data_pad_offset);
1684
Ido Shayevitz95c46882013-01-20 13:47:46 +02001685 pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
1686
Manu Gautam863b74132012-11-21 14:30:04 +05301687 return pdata;
1688}
1689
1690
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301691static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1692{
1693 struct usb_hcd *hcd;
1694 struct resource *res;
1695 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301696 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301697 int ret;
1698
1699 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1700
Manu Gautam863b74132012-11-21 14:30:04 +05301701 if (pdev->dev.of_node) {
1702 dev_dbg(&pdev->dev, "device tree enabled\n");
1703 pdev->dev.platform_data = msm_hsic_dt_to_pdata(pdev);
1704 dev_set_name(&pdev->dev, ehci_msm_hsic_driver.driver.name);
1705 }
1706 if (!pdev->dev.platform_data)
1707 dev_dbg(&pdev->dev, "No platform data given\n");
1708
Ofir Cohen4cc55372012-11-20 11:17:24 +02001709 if (!pdev->dev.dma_mask)
1710 pdev->dev.dma_mask = &ehci_msm_hsic_dma_mask;
1711 if (!pdev->dev.coherent_dma_mask)
1712 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
1713
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301714 /* After parent device's probe is executed, it will be put in suspend
1715 * mode. When child device's probe is called, driver core is not
1716 * resuming parent device due to which parent will be in suspend even
1717 * though child is active. Hence resume the parent device explicitly.
1718 */
1719 if (pdev->dev.parent)
1720 pm_runtime_get_sync(pdev->dev.parent);
1721
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301722 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1723 dev_name(&pdev->dev));
1724 if (!hcd) {
1725 dev_err(&pdev->dev, "Unable to create HCD\n");
1726 return -ENOMEM;
1727 }
1728
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05301729 hcd_to_bus(hcd)->skip_resume = true;
1730
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301731 hcd->irq = platform_get_irq(pdev, 0);
1732 if (hcd->irq < 0) {
1733 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1734 ret = hcd->irq;
1735 goto put_hcd;
1736 }
1737
1738 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1739 if (!res) {
1740 dev_err(&pdev->dev, "Unable to get memory resource\n");
1741 ret = -ENODEV;
1742 goto put_hcd;
1743 }
1744
1745 hcd->rsrc_start = res->start;
1746 hcd->rsrc_len = resource_size(res);
1747 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1748 if (!hcd->regs) {
1749 dev_err(&pdev->dev, "ioremap failed\n");
1750 ret = -ENOMEM;
1751 goto put_hcd;
1752 }
1753
1754 mehci = hcd_to_hsic(hcd);
1755 mehci->dev = &pdev->dev;
Hemant Kumar30d361c2012-08-20 14:44:40 -07001756 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301757
Hemant Kumard343c012012-09-06 19:57:14 -07001758 spin_lock_init(&mehci->wakeup_lock);
1759
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001760 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001761 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001762
Hemant Kumare4040492012-06-21 17:35:42 -07001763 mehci->ehci.resume_sof_bug = 1;
1764
Hemant Kumar30d361c2012-08-20 14:44:40 -07001765 if (pdata)
1766 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Hemant Kumar933e0402012-05-22 11:11:40 -07001767
Ofir Cohen4cc55372012-11-20 11:17:24 +02001768 ret = msm_hsic_init_gdsc(mehci, 1);
1769 if (ret) {
1770 dev_err(&pdev->dev, "unable to initialize GDSC\n");
1771 ret = -ENODEV;
1772 goto put_hcd;
1773 }
1774
Vamsi Krishna34f01582011-12-14 19:54:42 -08001775 res = platform_get_resource_byname(pdev,
1776 IORESOURCE_IRQ,
1777 "peripheral_status_irq");
1778 if (res)
1779 mehci->peripheral_status_irq = res->start;
1780
Jack Pham0cc75c42012-10-10 02:03:50 +02001781 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "wakeup");
Hemant Kumar6fd65032012-05-23 13:02:24 -07001782 if (res) {
Jack Pham0cc75c42012-10-10 02:03:50 +02001783 mehci->wakeup_irq = res->start;
Hemant Kumar6fd65032012-05-23 13:02:24 -07001784 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1785 }
1786
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301787 ret = msm_hsic_init_clocks(mehci, 1);
1788 if (ret) {
1789 dev_err(&pdev->dev, "unable to initialize clocks\n");
1790 ret = -ENODEV;
1791 goto unmap;
1792 }
1793
1794 ret = msm_hsic_init_vddcx(mehci, 1);
1795 if (ret) {
1796 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1797 ret = -ENODEV;
1798 goto deinit_clocks;
1799 }
1800
Vamsi Krishnafce1bd22012-08-17 17:12:26 -07001801 init_completion(&mehci->rt_completion);
1802 init_completion(&mehci->gpt0_completion);
Ofir Cohen5dddb152012-11-14 11:18:50 +02001803
1804 msm_hsic_phy_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301805
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001806 ehci_wq = create_singlethread_workqueue("ehci_wq");
1807 if (!ehci_wq) {
1808 dev_err(&pdev->dev, "unable to create workqueue\n");
1809 ret = -ENOMEM;
1810 goto deinit_vddcx;
1811 }
1812
1813 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1814
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301815 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1816 if (ret) {
1817 dev_err(&pdev->dev, "unable to register HCD\n");
Ofir Cohen5dddb152012-11-14 11:18:50 +02001818 goto destroy_wq;
1819 }
1820
1821 ret = msm_hsic_start(mehci);
1822 if (ret) {
1823 dev_err(&pdev->dev, "unable to initialize PHY\n");
1824 goto destroy_wq;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301825 }
1826
1827 device_init_wakeup(&pdev->dev, 1);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001828 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1829 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001830
1831 if (mehci->peripheral_status_irq) {
1832 ret = request_threaded_irq(mehci->peripheral_status_irq,
1833 NULL, hsic_peripheral_status_change,
1834 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1835 | IRQF_SHARED,
1836 "hsic_peripheral_status", mehci);
1837 if (ret)
1838 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1839 __func__, mehci->peripheral_status_irq, ret);
1840 }
1841
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001842 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001843 if (mehci->wakeup_irq) {
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07001844 /* In case if wakeup gpio is pulled high at this point
1845 * remote wakeup interrupt fires right after request_irq.
1846 * Remote wake up interrupt only needs to be enabled when
1847 * HSIC bus goes to suspend.
1848 */
1849 irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001850 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001851 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001852 "msm_hsic_wakeup", mehci);
Hemant Kumarbbcdcbc2012-08-30 14:23:38 -07001853 if (ret) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001854 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1855 mehci->wakeup_irq, ret);
1856 mehci->wakeup_irq = 0;
1857 }
1858 }
1859
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301860 mehci->async_irq = platform_get_irq_byname(pdev, "async_irq");
1861 if (mehci->async_irq < 0) {
1862 dev_dbg(&pdev->dev, "platform_get_irq for async_int failed\n");
1863 mehci->async_irq = 0;
1864 } else {
1865 ret = request_irq(mehci->async_irq, msm_hsic_wakeup_irq,
1866 IRQF_TRIGGER_RISING, "msm_hsic_async", mehci);
1867 if (ret) {
1868 dev_err(&pdev->dev, "request irq failed (ASYNC INT)\n");
1869 mehci->async_irq = 0;
1870 } else {
1871 enable_irq_wake(mehci->async_irq);
1872 }
1873 }
1874
Hemant Kumare6275972012-02-29 20:06:21 -08001875 ret = ehci_hsic_msm_debugfs_init(mehci);
1876 if (ret)
1877 dev_dbg(&pdev->dev, "mode debugfs file is"
1878 "not available\n");
1879
1880 if (pdata && pdata->bus_scale_table) {
1881 mehci->bus_perf_client =
1882 msm_bus_scale_register_client(pdata->bus_scale_table);
1883 /* Configure BUS performance parameters for MAX bandwidth */
1884 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001885 mehci->bus_vote = true;
1886 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001887 } else {
1888 dev_err(&pdev->dev, "%s: Failed to register BUS "
1889 "scaling client!!\n", __func__);
1890 }
1891 }
1892
Hemant Kumar105d07f2012-07-02 15:33:07 -07001893 __mehci = mehci;
1894
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001895 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301896 pm_qos_add_request(&mehci->pm_qos_req_dma,
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001897 PM_QOS_CPU_DMA_LATENCY, pdata->standalone_latency + 1);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301898
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301899 /*
1900 * This pdev->dev is assigned parent of root-hub by USB core,
1901 * hence, runtime framework automatically calls this driver's
1902 * runtime APIs based on root-hub's state.
1903 */
1904 pm_runtime_set_active(&pdev->dev);
1905 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301906 /* Decrement the parent device's counter after probe.
1907 * As child is active, parent will not be put into
1908 * suspend mode.
1909 */
1910 if (pdev->dev.parent)
1911 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301912
1913 return 0;
1914
Ofir Cohen5dddb152012-11-14 11:18:50 +02001915destroy_wq:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001916 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301917deinit_vddcx:
1918 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02001919 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301920deinit_clocks:
1921 msm_hsic_init_clocks(mehci, 0);
1922unmap:
1923 iounmap(hcd->regs);
1924put_hcd:
1925 usb_put_hcd(hcd);
1926
1927 return ret;
1928}
1929
1930static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1931{
1932 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1933 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301934 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1935
Ido Shayevitz65943492013-02-20 18:55:59 +02001936 /* If the device was removed no need to call pm_runtime_disable */
1937 if (pdev->dev.power.power_state.event != PM_EVENT_INVALID)
1938 pm_runtime_disable(&pdev->dev);
1939
1940 pm_runtime_set_suspended(&pdev->dev);
1941
Pavankumar Kondeti21a840e2013-02-12 21:43:56 +05301942 /* Remove the HCD prior to releasing our resources. */
1943 usb_remove_hcd(hcd);
1944
Hemant Kumarbc8bdf62012-10-17 12:29:51 -07001945 if (pdata && pdata->standalone_latency)
Pavankumar Kondeti4f5dc3b2012-09-07 15:33:09 +05301946 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301947
Vamsi Krishna34f01582011-12-14 19:54:42 -08001948 if (mehci->peripheral_status_irq)
1949 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001950
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001951 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001952 if (mehci->wakeup_irq_enabled)
1953 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001954 free_irq(mehci->wakeup_irq, mehci);
1955 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001956
Manu Gautam3fb60ca2013-02-13 18:33:33 +05301957 if (mehci->async_irq) {
1958 disable_irq_wake(mehci->async_irq);
1959 free_irq(mehci->async_irq, mehci);
1960 }
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001961 /*
1962 * If the update request is called after unregister, the request will
1963 * fail. Results are undefined if unregister is called in the middle of
1964 * update request.
1965 */
1966 mehci->bus_vote = false;
1967 cancel_work_sync(&mehci->bus_vote_w);
1968
Hemant Kumare6275972012-02-29 20:06:21 -08001969 if (mehci->bus_perf_client)
1970 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1971
1972 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301973 device_init_wakeup(&pdev->dev, 0);
Ido Shayevitze50d9142013-02-17 20:43:26 +02001974
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001975 destroy_workqueue(ehci_wq);
1976
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301977 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301978 msm_hsic_init_vddcx(mehci, 0);
Ofir Cohen4cc55372012-11-20 11:17:24 +02001979 msm_hsic_init_gdsc(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301980
1981 msm_hsic_init_clocks(mehci, 0);
Sudhir Sharma1673e302012-08-27 17:37:24 -07001982 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301983 iounmap(hcd->regs);
1984 usb_put_hcd(hcd);
1985
1986 return 0;
1987}
1988
1989#ifdef CONFIG_PM_SLEEP
1990static int msm_hsic_pm_suspend(struct device *dev)
1991{
Jack Phambe05fbb2012-05-16 10:56:26 -07001992 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301993 struct usb_hcd *hcd = dev_get_drvdata(dev);
1994 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1995
1996 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1997
Hemant Kumar45d211b2012-05-31 17:58:43 -07001998 dbg_log_event(NULL, "PM Suspend", 0);
1999
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302000 if (device_may_wakeup(dev))
2001 enable_irq_wake(hcd->irq);
2002
Jack Phambe05fbb2012-05-16 10:56:26 -07002003 ret = msm_hsic_suspend(mehci);
2004
2005 if (ret && device_may_wakeup(dev))
2006 disable_irq_wake(hcd->irq);
2007
2008 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07002009}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302010
Jack Pham16b06f82012-08-14 20:03:59 -07002011static int msm_hsic_pm_suspend_noirq(struct device *dev)
2012{
2013 struct usb_hcd *hcd = dev_get_drvdata(dev);
2014 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2015
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05302016 if (atomic_read(&mehci->async_int)) {
Jack Pham16b06f82012-08-14 20:03:59 -07002017 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
2018 return -EBUSY;
2019 }
2020
2021 return 0;
2022}
2023
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302024static int msm_hsic_pm_resume(struct device *dev)
2025{
2026 int ret;
2027 struct usb_hcd *hcd = dev_get_drvdata(dev);
2028 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2029
Jack Pham16b06f82012-08-14 20:03:59 -07002030 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002031 dbg_log_event(NULL, "PM Resume", 0);
2032
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302033 if (device_may_wakeup(dev))
2034 disable_irq_wake(hcd->irq);
2035
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05302036 /*
2037 * Keep HSIC in Low Power Mode if system is resumed
2038 * by any other wakeup source. HSIC is resumed later
2039 * when remote wakeup is received or interface driver
2040 * start I/O.
2041 */
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05302042 if (!atomic_read(&mehci->pm_usage_cnt) &&
Pavankumar Kondeti822fbe62013-01-28 17:04:39 +05302043 !atomic_read(&mehci->async_int) &&
Pavankumar Kondeti41d004c2012-11-09 10:54:00 +05302044 pm_runtime_suspended(dev))
Pavankumar Kondeti6f199aa2012-09-18 17:52:51 +05302045 return 0;
2046
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302047 ret = msm_hsic_resume(mehci);
2048 if (ret)
2049 return ret;
2050
2051 /* Bring the device to full powered state upon system resume */
2052 pm_runtime_disable(dev);
2053 pm_runtime_set_active(dev);
2054 pm_runtime_enable(dev);
2055
2056 return 0;
2057}
2058#endif
2059
2060#ifdef CONFIG_PM_RUNTIME
2061static int msm_hsic_runtime_idle(struct device *dev)
2062{
2063 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302064 return 0;
2065}
2066
2067static int msm_hsic_runtime_suspend(struct device *dev)
2068{
2069 struct usb_hcd *hcd = dev_get_drvdata(dev);
2070 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2071
2072 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002073
2074 dbg_log_event(NULL, "Run Time PM Suspend", 0);
2075
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302076 return msm_hsic_suspend(mehci);
2077}
2078
2079static int msm_hsic_runtime_resume(struct device *dev)
2080{
2081 struct usb_hcd *hcd = dev_get_drvdata(dev);
2082 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2083
2084 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002085
2086 dbg_log_event(NULL, "Run Time PM Resume", 0);
2087
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302088 return msm_hsic_resume(mehci);
2089}
2090#endif
2091
2092#ifdef CONFIG_PM
2093static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
2094 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07002095 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302096 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
2097 msm_hsic_runtime_idle)
2098};
2099#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02002100static const struct of_device_id hsic_host_dt_match[] = {
2101 { .compatible = "qcom,hsic-host",
2102 },
2103 {}
2104};
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302105static struct platform_driver ehci_msm_hsic_driver = {
2106 .probe = ehci_hsic_msm_probe,
2107 .remove = __devexit_p(ehci_hsic_msm_remove),
2108 .driver = {
2109 .name = "msm_hsic_host",
2110#ifdef CONFIG_PM
2111 .pm = &msm_hsic_dev_pm_ops,
2112#endif
Ofir Cohen4cc55372012-11-20 11:17:24 +02002113 .of_match_table = hsic_host_dt_match,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302114 },
2115};