blob: 465e5128e4850dea0ece17b5d687e21106ca3ee6 [file] [log] [blame]
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301/* ehci-msm-hsic.c - HSUSB Host Controller Driver Implementation
2 *
Manu Gautam5143b252012-01-05 19:25:23 -08003 * Copyright (c) 2011-2012, Code Aurora Forum. 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>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053030#include <linux/pm_runtime.h>
31#include <linux/regulator/consumer.h>
32
33#include <linux/usb/msm_hsusb_hw.h>
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +053034#include <linux/usb/msm_hsusb.h>
35#include <linux/gpio.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030036#include <linux/spinlock.h>
37
38#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053039#include <mach/clk.h>
40#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053041#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080042#include <linux/spinlock.h>
Hemant Kumar45d211b2012-05-31 17:58:43 -070043#include <linux/cpu.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030044#include <mach/rpm-regulator.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053045
46#define MSM_USB_BASE (hcd->regs)
Hemant Kumar105d07f2012-07-02 15:33:07 -070047#define USB_REG_START_OFFSET 0x90
48#define USB_REG_END_OFFSET 0x250
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053049
Hemant Kumar2309eaa2012-08-14 16:46:42 -070050static struct workqueue_struct *ehci_wq;
51
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053052struct msm_hsic_hcd {
53 struct ehci_hcd ehci;
54 struct device *dev;
55 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080056 struct clk *core_clk;
57 struct clk *alt_core_clk;
58 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053059 struct clk *cal_clk;
60 struct regulator *hsic_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053061 atomic_t in_lpm;
Vamsi Krishna34f01582011-12-14 19:54:42 -080062 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080063 int wakeup_irq;
Hemant Kumar6fd65032012-05-23 13:02:24 -070064 int wakeup_gpio;
Jack Phamfe441ea2012-03-23 17:03:15 -070065 bool wakeup_irq_enabled;
Jack Phamdd5ad792012-07-26 10:31:03 -070066 bool irq_enabled;
67 bool async_int;
Hemant Kumare6275972012-02-29 20:06:21 -080068 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070069 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030070 enum usb_vdd_type vdd_type;
Hemant Kumar2309eaa2012-08-14 16:46:42 -070071
72 struct work_struct bus_vote_w;
73 bool bus_vote;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053074};
75
Hemant Kumar105d07f2012-07-02 15:33:07 -070076struct msm_hsic_hcd *__mehci;
77
Hemant Kumare6275972012-02-29 20:06:21 -080078static bool debug_bus_voting_enabled = true;
Hemant Kumar45d211b2012-05-31 17:58:43 -070079
80static unsigned int enable_dbg_log = 1;
81module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
82/*by default log ep0 and efs sync ep*/
83static unsigned int ep_addr_rxdbg_mask = 9;
84module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
85static unsigned int ep_addr_txdbg_mask = 9;
86module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
87
88/* Maximum debug message length */
89#define DBG_MSG_LEN 100UL
90
91/* Maximum number of messages */
92#define DBG_MAX_MSG 256UL
93
94#define TIME_BUF_LEN 20
95
96enum event_type {
97 EVENT_UNDEF = -1,
98 URB_SUBMIT,
99 URB_COMPLETE,
100 EVENT_NONE,
101};
102
103#define EVENT_STR_LEN 5
104
105static char *event_to_str(enum event_type e)
106{
107 switch (e) {
108 case URB_SUBMIT:
109 return "S";
110 case URB_COMPLETE:
111 return "C";
112 case EVENT_NONE:
113 return "NONE";
114 default:
115 return "UNDEF";
116 }
117}
118
119static enum event_type str_to_event(const char *name)
120{
121 if (!strncasecmp("S", name, EVENT_STR_LEN))
122 return URB_SUBMIT;
123 if (!strncasecmp("C", name, EVENT_STR_LEN))
124 return URB_COMPLETE;
125 if (!strncasecmp("", name, EVENT_STR_LEN))
126 return EVENT_NONE;
127
128 return EVENT_UNDEF;
129}
130
131/*log ep0 activity*/
132static struct {
133 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
134 unsigned idx; /* index */
135 rwlock_t lck; /* lock */
136} dbg_hsic_ctrl = {
137 .idx = 0,
138 .lck = __RW_LOCK_UNLOCKED(lck)
139};
140
141static struct {
142 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
143 unsigned idx; /* index */
144 rwlock_t lck; /* lock */
145} dbg_hsic_data = {
146 .idx = 0,
147 .lck = __RW_LOCK_UNLOCKED(lck)
148};
149
150/**
151 * dbg_inc: increments debug event index
152 * @idx: buffer index
153 */
154static void dbg_inc(unsigned *idx)
155{
156 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
157}
158
159/*get_timestamp - returns time of day in us */
160static char *get_timestamp(char *tbuf)
161{
162 unsigned long long t;
163 unsigned long nanosec_rem;
164
165 t = cpu_clock(smp_processor_id());
166 nanosec_rem = do_div(t, 1000000000)/1000;
167 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
168 nanosec_rem);
169 return tbuf;
170}
171
172static int allow_dbg_log(int ep_addr)
173{
174 int dir, num;
175
176 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
177 num = ep_addr & ~USB_DIR_IN;
178 num = 1 << num;
179
180 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
181 return 1;
182 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
183 return 1;
184
185 return 0;
186}
187
188static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
189{
190 unsigned long flags;
191 int ep_addr;
192 char tbuf[TIME_BUF_LEN];
193
194 if (!enable_dbg_log)
195 return;
196
197 if (!urb) {
198 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
199 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
200 "%s: %s : %u\n", get_timestamp(tbuf), event, extra);
201 dbg_inc(&dbg_hsic_ctrl.idx);
202 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
203 return;
204 }
205
206 ep_addr = urb->ep->desc.bEndpointAddress;
207 if (!allow_dbg_log(ep_addr))
208 return;
209
210 if ((ep_addr & 0x0f) == 0x0) {
211 /*submit event*/
212 if (!str_to_event(event)) {
213 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
214 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
215 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
216 "%02x %02x %04x %04x %04x %u %d\n",
217 get_timestamp(tbuf), event, urb,
218 (ep_addr & USB_DIR_IN) ? "in" : "out",
219 urb->setup_packet[0], urb->setup_packet[1],
220 (urb->setup_packet[3] << 8) |
221 urb->setup_packet[2],
222 (urb->setup_packet[5] << 8) |
223 urb->setup_packet[4],
224 (urb->setup_packet[7] << 8) |
225 urb->setup_packet[6],
226 urb->transfer_buffer_length, urb->status);
227
228 dbg_inc(&dbg_hsic_ctrl.idx);
229 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
230 } else {
231 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
232 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
233 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d\n",
234 get_timestamp(tbuf), event, urb,
235 (ep_addr & USB_DIR_IN) ? "in" : "out",
236 urb->actual_length, extra);
237
238 dbg_inc(&dbg_hsic_ctrl.idx);
239 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
240 }
241 } else {
242 write_lock_irqsave(&dbg_hsic_data.lck, flags);
243 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
244 "%s: [%s : %p]:ep%d[%s] %u %d\n",
245 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
246 (ep_addr & USB_DIR_IN) ? "in" : "out",
247 str_to_event(event) ? urb->actual_length :
248 urb->transfer_buffer_length,
249 str_to_event(event) ? extra : urb->status);
250
251 dbg_inc(&dbg_hsic_data.idx);
252 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
253 }
254}
255
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530256static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
257{
258 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
259}
260
261static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
262{
263 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
264}
265
Hemant Kumar105d07f2012-07-02 15:33:07 -0700266static void dump_hsic_regs(struct usb_hcd *hcd)
267{
268 int i;
269 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
270
271 if (atomic_read(&mehci->in_lpm))
272 return;
273
274 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
275 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
276 readl_relaxed(hcd->regs + i),
277 readl_relaxed(hcd->regs + i + 4),
278 readl_relaxed(hcd->regs + i + 8),
279 readl_relaxed(hcd->regs + i + 0xc));
280}
281
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530282#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
283
Amit Blayd6ea6102012-06-07 16:26:24 +0300284#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700285#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
286#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530287
Lena Salman8c8ba382012-02-14 15:59:31 +0200288#define HSIC_DBG1_REG 0x38
289
Amit Blayd6ea6102012-06-07 16:26:24 +0300290static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
291 { /* VDD_CX CORNER Voting */
292 [VDD_NONE] = RPM_VREG_CORNER_NONE,
293 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
294 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
295 },
296 { /* VDD_CX Voltage Voting */
297 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
298 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
299 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
300 },
301};
302
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530303static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
304{
305 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300306 int none_vol, min_vol, max_vol;
307
308 if (!mehci->hsic_vddcx) {
309 mehci->vdd_type = VDDCX_CORNER;
310 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
311 "hsic_vdd_dig");
312 if (IS_ERR(mehci->hsic_vddcx)) {
313 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
314 "HSIC_VDDCX");
315 if (IS_ERR(mehci->hsic_vddcx)) {
316 dev_err(mehci->dev, "unable to get hsic vddcx\n");
317 return PTR_ERR(mehci->hsic_vddcx);
318 }
319 mehci->vdd_type = VDDCX;
320 }
321 }
322
323 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
324 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
325 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530326
327 if (!init)
328 goto disable_reg;
329
Amit Blayd6ea6102012-06-07 16:26:24 +0300330 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530331 if (ret) {
332 dev_err(mehci->dev, "unable to set the voltage"
333 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530334 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530335 }
336
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530337 ret = regulator_enable(mehci->hsic_vddcx);
338 if (ret) {
339 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
340 goto reg_enable_err;
341 }
342
343 return 0;
344
345disable_reg:
346 regulator_disable(mehci->hsic_vddcx);
347reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300348 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
349
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530350 return ret;
351
352}
353
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700354static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
355{
356 struct usb_hcd *hcd = hsic_to_hcd(mehci);
357 unsigned long timeout;
358
359 /* initiate read operation */
360 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
361 USB_ULPI_VIEWPORT);
362
363 /* wait for completion */
364 timeout = jiffies + usecs_to_jiffies(ULPI_IO_TIMEOUT_USEC);
365 while (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN) {
366 if (time_after(jiffies, timeout)) {
367 dev_err(mehci->dev, "ulpi_read: timeout %08x\n",
368 readl_relaxed(USB_ULPI_VIEWPORT));
369 return -ETIMEDOUT;
370 }
371 udelay(1);
372 }
373
374 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
375}
376
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530377static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
378{
379 struct usb_hcd *hcd = hsic_to_hcd(mehci);
380 int cnt = 0;
381
382 /* initiate write operation */
383 writel_relaxed(ULPI_RUN | ULPI_WRITE |
384 ULPI_ADDR(reg) | ULPI_DATA(val),
385 USB_ULPI_VIEWPORT);
386
387 /* wait for completion */
388 while (cnt < ULPI_IO_TIMEOUT_USEC) {
389 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
390 break;
391 udelay(1);
392 cnt++;
393 }
394
395 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
396 dev_err(mehci->dev, "ulpi_write: timeout\n");
397 return -ETIMEDOUT;
398 }
399
400 return 0;
401}
402
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700403#define HSIC_DBG1 0X38
404#define ULPI_MANUAL_ENABLE BIT(4)
405#define ULPI_LINESTATE_DATA BIT(5)
406#define ULPI_LINESTATE_STROBE BIT(6)
407static void ehci_msm_enable_ulpi_control(struct usb_hcd *hcd, u32 linestate)
408{
409 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
410 int val;
411
412 switch (linestate) {
413 case PORT_RESET:
414 val = ulpi_read(mehci, HSIC_DBG1);
415 val |= ULPI_MANUAL_ENABLE;
416 val &= ~(ULPI_LINESTATE_DATA | ULPI_LINESTATE_STROBE);
417 ulpi_write(mehci, val, HSIC_DBG1);
418 break;
419 default:
420 pr_info("%s: Unknown linestate:%0x\n", __func__, linestate);
421 }
422}
423
424static void ehci_msm_disable_ulpi_control(struct usb_hcd *hcd)
425{
426 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
427 int val;
428
429 val = ulpi_read(mehci, HSIC_DBG1);
430 val &= ~ULPI_MANUAL_ENABLE;
431 ulpi_write(mehci, val, HSIC_DBG1);
432}
433
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530434static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
435{
436 int rc = 0;
437 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800438 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530439
440 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800441
Lena Salman8c8ba382012-02-14 15:59:31 +0200442 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530443 return rc;
444
Vamsi Krishna34f01582011-12-14 19:54:42 -0800445 if (gpio_status == gpio_en)
446 return 0;
447
448 gpio_status = gpio_en;
449
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530450 if (!gpio_en)
451 goto free_gpio;
452
453 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
454 if (rc < 0) {
455 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
456 return rc;
457 }
458
459 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
460 if (rc < 0) {
461 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
462 goto free_strobe;
463 }
464
Hemant Kumar6fd65032012-05-23 13:02:24 -0700465 if (mehci->wakeup_gpio) {
466 rc = gpio_request(mehci->wakeup_gpio, "HSIC_WAKEUP_GPIO");
467 if (rc < 0) {
468 dev_err(mehci->dev, "gpio request failed for HSIC WAKEUP\n");
469 goto free_data;
470 }
471 }
472
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530473 return 0;
474
475free_gpio:
Hemant Kumar6fd65032012-05-23 13:02:24 -0700476 if (mehci->wakeup_gpio)
477 gpio_free(mehci->wakeup_gpio);
478free_data:
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530479 gpio_free(pdata->data);
480free_strobe:
481 gpio_free(pdata->strobe);
482
483 return rc;
484}
485
Vamsi Krishna64b48612012-06-14 16:08:11 -0700486static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530487{
488 int ret;
489
Manu Gautam5143b252012-01-05 19:25:23 -0800490 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530491 if (ret) {
Vamsi Krishna64b48612012-06-14 16:08:11 -0700492 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
493 return;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530494 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700495 clk_disable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530496
Manu Gautam5143b252012-01-05 19:25:23 -0800497 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530498 if (ret)
Vamsi Krishna64b48612012-06-14 16:08:11 -0700499 dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530500
Vamsi Krishna64b48612012-06-14 16:08:11 -0700501 usleep_range(10000, 12000);
502
503 clk_enable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530504}
505
Vamsi Krishna64b48612012-06-14 16:08:11 -0700506#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
507#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530508#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
509#define HSIC_LV_MODE 0x04
510#define HSIC_PAD_CALIBRATION 0xA8
511#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530512#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
513static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
514{
515 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530516 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200517 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530518
Vamsi Krishna64b48612012-06-14 16:08:11 -0700519 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530520
Vamsi Krishna64b48612012-06-14 16:08:11 -0700521 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530522 writel_relaxed(0x80000000, USB_PORTSC);
523
Vamsi Krishna64b48612012-06-14 16:08:11 -0700524 mb();
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530525
Lena Salman8c8ba382012-02-14 15:59:31 +0200526 /* HSIC init sequence when HSIC signals (Strobe/Data) are
527 routed via GPIOs */
528 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530529
Lena Salman8c8ba382012-02-14 15:59:31 +0200530 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
531 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530532
Vamsi Krishna64b48612012-06-14 16:08:11 -0700533 mb();
534
Lena Salman8c8ba382012-02-14 15:59:31 +0200535 /*set periodic calibration interval to ~2.048sec in
536 HSIC_IO_CAL_REG */
537 ulpi_write(mehci, 0xFF, 0x33);
538
539 /* Enable periodic IO calibration in HSIC_CFG register */
540 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
541
Vamsi Krishna64b48612012-06-14 16:08:11 -0700542 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200543 ret = msm_hsic_config_gpios(mehci, 1);
544 if (ret) {
545 dev_err(mehci->dev, " gpio configuarion failed\n");
546 return ret;
547 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700548 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO PAD_CTL register */
549 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_STROBE_GPIO_PAD_CTL);
550 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_DATA_GPIO_PAD_CTL);
551
552 mb();
553
Lena Salman8c8ba382012-02-14 15:59:31 +0200554 /* Enable HSIC mode in HSIC_CFG register */
555 ulpi_write(mehci, 0x01, 0x31);
556 } else {
557 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
558 via dedicated I/O */
559
560 /* programmable length of connect signaling (33.2ns) */
561 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
562 if (ret) {
563 pr_err("%s: Unable to program length of connect "
564 "signaling\n", __func__);
565 }
566
567 /*set periodic calibration interval to ~2.048sec in
568 HSIC_IO_CAL_REG */
569 ulpi_write(mehci, 0xFF, 0x33);
570
571 /* Enable HSIC mode in HSIC_CFG register */
572 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530573 }
574
Hemant Kumar6fd65032012-05-23 13:02:24 -0700575 /*disable auto resume*/
576 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
577
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530578 return 0;
579}
580
581#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
582#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
583
584#ifdef CONFIG_PM_SLEEP
585static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
586{
587 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530588 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530589 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300590 int none_vol, max_vol;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530591
592 if (atomic_read(&mehci->in_lpm)) {
593 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
594 return 0;
595 }
596
Hemant Kumar7f374632012-05-31 20:10:32 -0700597 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
598 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
599 __func__);
600 return -EAGAIN;
601 }
602
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530603 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700604
Jack Phamdd5ad792012-07-26 10:31:03 -0700605 /* make sure we don't race against the root hub being resumed */
606 if (HCD_RH_RUNNING(hcd) || HCD_WAKEUP_PENDING(hcd) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700607 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Jack Phamdd5ad792012-07-26 10:31:03 -0700608 dev_warn(mehci->dev, "%s: Root hub is not suspended\n",
609 __func__);
Jack Phambe05fbb2012-05-16 10:56:26 -0700610 enable_irq(hcd->irq);
611 return -EBUSY;
612 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700613 mehci->irq_enabled = false;
Jack Phambe05fbb2012-05-16 10:56:26 -0700614
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530615 /*
616 * PHY may take some time or even fail to enter into low power
617 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
618 * in failure case.
619 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700620 val = readl_relaxed(USB_PORTSC);
621 val &= ~PORT_RWC_BITS;
622 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530623 writel_relaxed(val, USB_PORTSC);
624 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
625 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
626 break;
627 udelay(1);
628 cnt++;
629 }
630
631 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
632 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530633 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530634 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530635 }
636
637 /*
638 * PHY has capability to generate interrupt asynchronously in low
639 * power mode (LPM). This interrupt is level triggered. So USB IRQ
640 * line must be disabled till async interrupt enable bit is cleared
641 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
642 * block data communication from PHY.
643 */
644 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
645 ULPI_STP_CTRL, USB_USBCMD);
646
647 /*
648 * Ensure that hardware is put in low power mode before
649 * clocks are turned OFF and VDD is allowed to minimize.
650 */
651 mb();
652
Manu Gautam28b1bac2012-01-30 16:43:06 +0530653 clk_disable_unprepare(mehci->core_clk);
654 clk_disable_unprepare(mehci->phy_clk);
655 clk_disable_unprepare(mehci->cal_clk);
656 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530657
Amit Blayd6ea6102012-06-07 16:26:24 +0300658 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
659 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
660
661 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700662 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300663 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700664
Hemant Kumare6275972012-02-29 20:06:21 -0800665 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700666 mehci->bus_vote = false;
667 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800668 }
669
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530670 atomic_set(&mehci->in_lpm, 1);
Jack Phamdd5ad792012-07-26 10:31:03 -0700671 mehci->irq_enabled = true;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530672 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700673
674 mehci->wakeup_irq_enabled = 1;
675 enable_irq_wake(mehci->wakeup_irq);
676 enable_irq(mehci->wakeup_irq);
677
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530678 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
679
680 return 0;
681}
682
683static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
684{
685 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530686 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530687 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300688 int min_vol, max_vol;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530689
690 if (!atomic_read(&mehci->in_lpm)) {
691 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
692 return 0;
693 }
694
Hemant Kumar6fd65032012-05-23 13:02:24 -0700695 if (mehci->wakeup_irq_enabled) {
696 disable_irq_wake(mehci->wakeup_irq);
697 disable_irq_nosync(mehci->wakeup_irq);
698 mehci->wakeup_irq_enabled = 0;
699 }
700
Hemant Kumare6275972012-02-29 20:06:21 -0800701 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700702 mehci->bus_vote = true;
703 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800704 }
705
Amit Blayd6ea6102012-06-07 16:26:24 +0300706 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
707 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
708
709 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700710 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300711 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700712
Manu Gautam28b1bac2012-01-30 16:43:06 +0530713 clk_prepare_enable(mehci->core_clk);
714 clk_prepare_enable(mehci->phy_clk);
715 clk_prepare_enable(mehci->cal_clk);
716 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530717
718 temp = readl_relaxed(USB_USBCMD);
719 temp &= ~ASYNC_INTR_CTRL;
720 temp &= ~ULPI_STP_CTRL;
721 writel_relaxed(temp, USB_USBCMD);
722
723 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
724 goto skip_phy_resume;
725
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700726 temp = readl_relaxed(USB_PORTSC);
727 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530728 writel_relaxed(temp, USB_PORTSC);
729 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
730 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
731 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
732 break;
733 udelay(1);
734 cnt++;
735 }
736
737 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
738 /*
739 * This is a fatal error. Reset the link and
740 * PHY to make hsic working.
741 */
742 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530743 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530744 msm_hsic_reset(mehci);
745 }
746
747skip_phy_resume:
748
Hemant Kumar6fd65032012-05-23 13:02:24 -0700749 usb_hcd_resume_root_hub(hcd);
750
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530751 atomic_set(&mehci->in_lpm, 0);
752
753 if (mehci->async_int) {
754 mehci->async_int = false;
755 pm_runtime_put_noidle(mehci->dev);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530756 }
757
Jack Phamdd5ad792012-07-26 10:31:03 -0700758 if (!mehci->irq_enabled) {
759 enable_irq(hcd->irq);
760 mehci->irq_enabled = true;
Hemant Kumar6fd65032012-05-23 13:02:24 -0700761 }
762
Jack Phamdd5ad792012-07-26 10:31:03 -0700763 pm_relax(mehci->dev);
764
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530765 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
766
767 return 0;
768}
769#endif
770
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700771static void ehci_hsic_bus_vote_w(struct work_struct *w)
772{
773 struct msm_hsic_hcd *mehci =
774 container_of(w, struct msm_hsic_hcd, bus_vote_w);
775 int ret;
776
777 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
778 mehci->bus_vote);
779 if (ret)
780 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
781 __func__, ret);
782}
783
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530784static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
785{
786 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
787
788 if (atomic_read(&mehci->in_lpm)) {
789 disable_irq_nosync(hcd->irq);
Jack Phamdd5ad792012-07-26 10:31:03 -0700790 mehci->irq_enabled = false;
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700791 dev_dbg(mehci->dev, "phy async intr\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530792 mehci->async_int = true;
793 pm_runtime_get(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700794 pm_stay_awake(mehci->dev);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530795 return IRQ_HANDLED;
796 }
797
798 return ehci_irq(hcd);
799}
800
801static int ehci_hsic_reset(struct usb_hcd *hcd)
802{
803 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
804 int retval;
805
806 ehci->caps = USB_CAPLENGTH;
807 ehci->regs = USB_CAPLENGTH +
808 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
809 dbg_hcs_params(ehci, "reset");
810 dbg_hcc_params(ehci, "reset");
811
812 /* cache the data to minimize the chip reads*/
813 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
814
815 hcd->has_tt = 1;
816 ehci->sbrn = HCD_USB2;
817
818 retval = ehci_halt(ehci);
819 if (retval)
820 return retval;
821
822 /* data structure init */
823 retval = ehci_init(hcd);
824 if (retval)
825 return retval;
826
827 retval = ehci_reset(ehci);
828 if (retval)
829 return retval;
830
831 /* bursts of unspecified length. */
832 writel_relaxed(0, USB_AHBBURST);
833 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530834 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530835 /* Disable streaming mode and select host mode */
836 writel_relaxed(0x13, USB_USBMODE);
837
838 ehci_port_power(ehci, 1);
839 return 0;
840}
841
Hemant Kumar45d211b2012-05-31 17:58:43 -0700842static int ehci_hsic_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
843 gfp_t mem_flags)
844{
845 dbg_log_event(urb, event_to_str(URB_SUBMIT), 0);
846 return ehci_urb_enqueue(hcd, urb, mem_flags);
847}
848
849static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
850{
851 dbg_log_event(NULL, "Suspend RH", 0);
852 return ehci_bus_suspend(hcd);
853}
854
855static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
856{
857 dbg_log_event(NULL, "Resume RH", 0);
858 return ehci_bus_resume(hcd);
859}
860
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530861static struct hc_driver msm_hsic_driver = {
862 .description = hcd_name,
863 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
864 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
865
866 /*
867 * generic hardware linkage
868 */
869 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700870 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530871
872 .reset = ehci_hsic_reset,
873 .start = ehci_run,
874
875 .stop = ehci_stop,
876 .shutdown = ehci_shutdown,
877
878 /*
879 * managing i/o requests and associated device resources
880 */
Hemant Kumar45d211b2012-05-31 17:58:43 -0700881 .urb_enqueue = ehci_hsic_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530882 .urb_dequeue = ehci_urb_dequeue,
883 .endpoint_disable = ehci_endpoint_disable,
884 .endpoint_reset = ehci_endpoint_reset,
885 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
886
887 /*
888 * scheduling support
889 */
890 .get_frame_number = ehci_get_frame,
891
892 /*
893 * root hub support
894 */
895 .hub_status_data = ehci_hub_status_data,
896 .hub_control = ehci_hub_control,
897 .relinquish_port = ehci_relinquish_port,
898 .port_handed_over = ehci_port_handed_over,
899
900 /*
901 * PM support
902 */
Hemant Kumar45d211b2012-05-31 17:58:43 -0700903 .bus_suspend = ehci_hsic_bus_suspend,
904 .bus_resume = ehci_hsic_bus_resume,
905
906 .log_urb_complete = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -0700907 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700908
909 .enable_ulpi_control = ehci_msm_enable_ulpi_control,
910 .disable_ulpi_control = ehci_msm_disable_ulpi_control,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530911};
912
913static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
914{
915 int ret = 0;
916
917 if (!init)
918 goto put_clocks;
919
Lena Salman8c8ba382012-02-14 15:59:31 +0200920 /*core_clk is required for LINK protocol engine
921 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800922 mehci->core_clk = clk_get(mehci->dev, "core_clk");
923 if (IS_ERR(mehci->core_clk)) {
924 dev_err(mehci->dev, "failed to get core_clk\n");
925 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530926 return ret;
927 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530928
Lena Salman8c8ba382012-02-14 15:59:31 +0200929 /* alt_core_clk is for LINK to be used during PHY RESET
930 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800931 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
932 if (IS_ERR(mehci->alt_core_clk)) {
933 dev_err(mehci->dev, "failed to core_clk\n");
934 ret = PTR_ERR(mehci->alt_core_clk);
935 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530936 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530937
Lena Salman8c8ba382012-02-14 15:59:31 +0200938 /* phy_clk is required for HSIC PHY operation
939 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800940 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
941 if (IS_ERR(mehci->phy_clk)) {
942 dev_err(mehci->dev, "failed to get phy_clk\n");
943 ret = PTR_ERR(mehci->phy_clk);
944 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530945 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530946
947 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -0800948 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530949 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800950 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530951 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800952 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530953 }
954 clk_set_rate(mehci->cal_clk, 10000000);
955
956 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -0800957 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530958 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800959 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530960 ret = PTR_ERR(mehci->ahb_clk);
961 goto put_cal_clk;
962 }
963
Manu Gautam28b1bac2012-01-30 16:43:06 +0530964 clk_prepare_enable(mehci->core_clk);
965 clk_prepare_enable(mehci->phy_clk);
966 clk_prepare_enable(mehci->cal_clk);
967 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530968
969 return 0;
970
971put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -0800972 if (!atomic_read(&mehci->in_lpm)) {
973 clk_disable_unprepare(mehci->core_clk);
974 clk_disable_unprepare(mehci->phy_clk);
975 clk_disable_unprepare(mehci->cal_clk);
976 clk_disable_unprepare(mehci->ahb_clk);
977 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530978 clk_put(mehci->ahb_clk);
979put_cal_clk:
980 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800981put_phy_clk:
982 clk_put(mehci->phy_clk);
983put_alt_core_clk:
984 clk_put(mehci->alt_core_clk);
985put_core_clk:
986 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530987
988 return ret;
989}
Vamsi Krishna34f01582011-12-14 19:54:42 -0800990static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
991{
992 struct msm_hsic_hcd *mehci = dev_id;
993
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800994 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -0800995
996 if (mehci)
997 msm_hsic_config_gpios(mehci, 0);
998
999 return IRQ_HANDLED;
1000}
1001
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001002static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1003{
1004 struct msm_hsic_hcd *mehci = data;
1005
Hemant Kumar6fd65032012-05-23 13:02:24 -07001006 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001007 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001008 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
1009 __func__, mehci->wakeup_int_cnt);
1010
Jack Phamdd5ad792012-07-26 10:31:03 -07001011 mehci->async_int = true;
1012 pm_runtime_get(mehci->dev);
1013 pm_stay_awake(mehci->dev);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001014
Jack Phamfe441ea2012-03-23 17:03:15 -07001015 if (mehci->wakeup_irq_enabled) {
1016 mehci->wakeup_irq_enabled = 0;
1017 disable_irq_wake(irq);
1018 disable_irq_nosync(irq);
1019 }
1020
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001021 return IRQ_HANDLED;
1022}
1023
Hemant Kumare6275972012-02-29 20:06:21 -08001024static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1025{
1026 if (debug_bus_voting_enabled)
1027 seq_printf(s, "enabled\n");
1028 else
1029 seq_printf(s, "disabled\n");
1030
1031 return 0;
1032}
1033
1034static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1035{
1036 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1037}
1038
1039static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1040 const char __user *ubuf, size_t count, loff_t *ppos)
1041{
1042 char buf[8];
1043 int ret;
1044 struct seq_file *s = file->private_data;
1045 struct msm_hsic_hcd *mehci = s->private;
1046
1047 memset(buf, 0x00, sizeof(buf));
1048
1049 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1050 return -EFAULT;
1051
1052 if (!strncmp(buf, "enable", 6)) {
1053 /* Do not vote here. Let hsic driver decide when to vote */
1054 debug_bus_voting_enabled = true;
1055 } else {
1056 debug_bus_voting_enabled = false;
1057 if (mehci->bus_perf_client) {
1058 ret = msm_bus_scale_client_update_request(
1059 mehci->bus_perf_client, 0);
1060 if (ret)
1061 dev_err(mehci->dev, "%s: Failed to devote "
1062 "for bus bw %d\n", __func__, ret);
1063 }
1064 }
1065
1066 return count;
1067}
1068
1069const struct file_operations ehci_hsic_msm_bus_fops = {
1070 .open = ehci_hsic_msm_bus_open,
1071 .read = seq_read,
1072 .write = ehci_hsic_msm_bus_write,
1073 .llseek = seq_lseek,
1074 .release = single_release,
1075};
1076
Hemant Kumar6fd65032012-05-23 13:02:24 -07001077static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1078{
1079 struct msm_hsic_hcd *mehci = s->private;
1080
1081 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1082
1083 return 0;
1084}
1085
1086static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1087{
1088 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1089}
1090
1091const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1092 .open = ehci_hsic_msm_wakeup_cnt_open,
1093 .read = seq_read,
1094 .llseek = seq_lseek,
1095 .release = single_release,
1096};
1097
Hemant Kumar45d211b2012-05-31 17:58:43 -07001098static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1099{
1100 unsigned long flags;
1101 unsigned i;
1102
1103 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1104
1105 i = dbg_hsic_data.idx;
1106 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1107 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1108 continue;
1109 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1110 }
1111
1112 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1113
1114 return 0;
1115}
1116
1117static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1118{
1119 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1120}
1121
1122const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1123 .open = ehci_hsic_msm_data_events_open,
1124 .read = seq_read,
1125 .llseek = seq_lseek,
1126 .release = single_release,
1127};
1128
1129static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1130{
1131 unsigned long flags;
1132 unsigned i;
1133
1134 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1135
1136 i = dbg_hsic_ctrl.idx;
1137 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1138 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1139 continue;
1140 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1141 }
1142
1143 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1144
1145 return 0;
1146}
1147
1148static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1149{
1150 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1151}
1152
1153const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1154 .open = ehci_hsic_msm_ctrl_events_open,
1155 .read = seq_read,
1156 .llseek = seq_lseek,
1157 .release = single_release,
1158};
1159
Hemant Kumare6275972012-02-29 20:06:21 -08001160static struct dentry *ehci_hsic_msm_dbg_root;
1161static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1162{
1163 struct dentry *ehci_hsic_msm_dentry;
1164
1165 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1166
1167 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1168 return -ENODEV;
1169
1170 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1171 S_IRUGO | S_IWUSR,
1172 ehci_hsic_msm_dbg_root, mehci,
1173 &ehci_hsic_msm_bus_fops);
1174
1175 if (!ehci_hsic_msm_dentry) {
1176 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1177 return -ENODEV;
1178 }
1179
Hemant Kumar6fd65032012-05-23 13:02:24 -07001180 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1181 S_IRUGO,
1182 ehci_hsic_msm_dbg_root, mehci,
1183 &ehci_hsic_msm_wakeup_cnt_fops);
1184
1185 if (!ehci_hsic_msm_dentry) {
1186 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1187 return -ENODEV;
1188 }
1189
Hemant Kumar45d211b2012-05-31 17:58:43 -07001190 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1191 S_IRUGO,
1192 ehci_hsic_msm_dbg_root, mehci,
1193 &ehci_hsic_msm_dbg_ctrl_fops);
1194
1195 if (!ehci_hsic_msm_dentry) {
1196 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1197 return -ENODEV;
1198 }
1199
1200 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1201 S_IRUGO,
1202 ehci_hsic_msm_dbg_root, mehci,
1203 &ehci_hsic_msm_dbg_data_fops);
1204
1205 if (!ehci_hsic_msm_dentry) {
1206 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1207 return -ENODEV;
1208 }
1209
Hemant Kumare6275972012-02-29 20:06:21 -08001210 return 0;
1211}
1212
1213static void ehci_hsic_msm_debugfs_cleanup(void)
1214{
1215 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1216}
1217
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301218static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1219{
1220 struct usb_hcd *hcd;
1221 struct resource *res;
1222 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301223 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301224 int ret;
1225
1226 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1227
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301228 /* After parent device's probe is executed, it will be put in suspend
1229 * mode. When child device's probe is called, driver core is not
1230 * resuming parent device due to which parent will be in suspend even
1231 * though child is active. Hence resume the parent device explicitly.
1232 */
1233 if (pdev->dev.parent)
1234 pm_runtime_get_sync(pdev->dev.parent);
1235
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301236 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1237 dev_name(&pdev->dev));
1238 if (!hcd) {
1239 dev_err(&pdev->dev, "Unable to create HCD\n");
1240 return -ENOMEM;
1241 }
1242
1243 hcd->irq = platform_get_irq(pdev, 0);
1244 if (hcd->irq < 0) {
1245 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1246 ret = hcd->irq;
1247 goto put_hcd;
1248 }
1249
1250 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1251 if (!res) {
1252 dev_err(&pdev->dev, "Unable to get memory resource\n");
1253 ret = -ENODEV;
1254 goto put_hcd;
1255 }
1256
1257 hcd->rsrc_start = res->start;
1258 hcd->rsrc_len = resource_size(res);
1259 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1260 if (!hcd->regs) {
1261 dev_err(&pdev->dev, "ioremap failed\n");
1262 ret = -ENOMEM;
1263 goto put_hcd;
1264 }
1265
1266 mehci = hcd_to_hsic(hcd);
1267 mehci->dev = &pdev->dev;
1268
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001269 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001270 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001271
Hemant Kumare4040492012-06-21 17:35:42 -07001272 mehci->ehci.resume_sof_bug = 1;
1273
Hemant Kumar933e0402012-05-22 11:11:40 -07001274 mehci->ehci.max_log2_irq_thresh = 6;
1275
Vamsi Krishna34f01582011-12-14 19:54:42 -08001276 res = platform_get_resource_byname(pdev,
1277 IORESOURCE_IRQ,
1278 "peripheral_status_irq");
1279 if (res)
1280 mehci->peripheral_status_irq = res->start;
1281
Hemant Kumar6fd65032012-05-23 13:02:24 -07001282 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
1283 if (res) {
1284 mehci->wakeup_gpio = res->start;
1285 mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
1286 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1287 }
1288
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301289 ret = msm_hsic_init_clocks(mehci, 1);
1290 if (ret) {
1291 dev_err(&pdev->dev, "unable to initialize clocks\n");
1292 ret = -ENODEV;
1293 goto unmap;
1294 }
1295
1296 ret = msm_hsic_init_vddcx(mehci, 1);
1297 if (ret) {
1298 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1299 ret = -ENODEV;
1300 goto deinit_clocks;
1301 }
1302
1303 ret = msm_hsic_reset(mehci);
1304 if (ret) {
1305 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301306 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301307 }
1308
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001309 ehci_wq = create_singlethread_workqueue("ehci_wq");
1310 if (!ehci_wq) {
1311 dev_err(&pdev->dev, "unable to create workqueue\n");
1312 ret = -ENOMEM;
1313 goto deinit_vddcx;
1314 }
1315
1316 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1317
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301318 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1319 if (ret) {
1320 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301321 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301322 }
1323
Jack Phamdd5ad792012-07-26 10:31:03 -07001324 mehci->irq_enabled = true;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301325 device_init_wakeup(&pdev->dev, 1);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001326
1327 if (mehci->peripheral_status_irq) {
1328 ret = request_threaded_irq(mehci->peripheral_status_irq,
1329 NULL, hsic_peripheral_status_change,
1330 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1331 | IRQF_SHARED,
1332 "hsic_peripheral_status", mehci);
1333 if (ret)
1334 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1335 __func__, mehci->peripheral_status_irq, ret);
1336 }
1337
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001338 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001339 if (mehci->wakeup_irq) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001340 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001341 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001342 "msm_hsic_wakeup", mehci);
1343 if (!ret) {
1344 disable_irq_nosync(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001345 } else {
1346 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1347 mehci->wakeup_irq, ret);
1348 mehci->wakeup_irq = 0;
1349 }
1350 }
1351
Hemant Kumare6275972012-02-29 20:06:21 -08001352 ret = ehci_hsic_msm_debugfs_init(mehci);
1353 if (ret)
1354 dev_dbg(&pdev->dev, "mode debugfs file is"
1355 "not available\n");
1356
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301357 pdata = mehci->dev->platform_data;
Hemant Kumare6275972012-02-29 20:06:21 -08001358 if (pdata && pdata->bus_scale_table) {
1359 mehci->bus_perf_client =
1360 msm_bus_scale_register_client(pdata->bus_scale_table);
1361 /* Configure BUS performance parameters for MAX bandwidth */
1362 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001363 mehci->bus_vote = true;
1364 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001365 } else {
1366 dev_err(&pdev->dev, "%s: Failed to register BUS "
1367 "scaling client!!\n", __func__);
1368 }
1369 }
1370
Hemant Kumar105d07f2012-07-02 15:33:07 -07001371 __mehci = mehci;
1372
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301373 /*
1374 * This pdev->dev is assigned parent of root-hub by USB core,
1375 * hence, runtime framework automatically calls this driver's
1376 * runtime APIs based on root-hub's state.
1377 */
1378 pm_runtime_set_active(&pdev->dev);
1379 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301380 /* Decrement the parent device's counter after probe.
1381 * As child is active, parent will not be put into
1382 * suspend mode.
1383 */
1384 if (pdev->dev.parent)
1385 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301386
1387 return 0;
1388
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301389unconfig_gpio:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001390 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301391 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301392deinit_vddcx:
1393 msm_hsic_init_vddcx(mehci, 0);
1394deinit_clocks:
1395 msm_hsic_init_clocks(mehci, 0);
1396unmap:
1397 iounmap(hcd->regs);
1398put_hcd:
1399 usb_put_hcd(hcd);
1400
1401 return ret;
1402}
1403
1404static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1405{
1406 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1407 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1408
Vamsi Krishna34f01582011-12-14 19:54:42 -08001409 if (mehci->peripheral_status_irq)
1410 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001411
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001412 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001413 if (mehci->wakeup_irq_enabled)
1414 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001415 free_irq(mehci->wakeup_irq, mehci);
1416 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001417
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001418 /*
1419 * If the update request is called after unregister, the request will
1420 * fail. Results are undefined if unregister is called in the middle of
1421 * update request.
1422 */
1423 mehci->bus_vote = false;
1424 cancel_work_sync(&mehci->bus_vote_w);
1425
Hemant Kumare6275972012-02-29 20:06:21 -08001426 if (mehci->bus_perf_client)
1427 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1428
1429 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301430 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301431 pm_runtime_set_suspended(&pdev->dev);
1432
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001433 destroy_workqueue(ehci_wq);
1434
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301435 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301436 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301437 msm_hsic_init_vddcx(mehci, 0);
1438
1439 msm_hsic_init_clocks(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301440 iounmap(hcd->regs);
1441 usb_put_hcd(hcd);
1442
1443 return 0;
1444}
1445
1446#ifdef CONFIG_PM_SLEEP
1447static int msm_hsic_pm_suspend(struct device *dev)
1448{
Jack Phambe05fbb2012-05-16 10:56:26 -07001449 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301450 struct usb_hcd *hcd = dev_get_drvdata(dev);
1451 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1452
1453 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1454
Hemant Kumar45d211b2012-05-31 17:58:43 -07001455 dbg_log_event(NULL, "PM Suspend", 0);
1456
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301457 if (device_may_wakeup(dev))
1458 enable_irq_wake(hcd->irq);
1459
Jack Phambe05fbb2012-05-16 10:56:26 -07001460 ret = msm_hsic_suspend(mehci);
1461
1462 if (ret && device_may_wakeup(dev))
1463 disable_irq_wake(hcd->irq);
1464
1465 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001466}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301467
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301468static int msm_hsic_pm_resume(struct device *dev)
1469{
1470 int ret;
1471 struct usb_hcd *hcd = dev_get_drvdata(dev);
1472 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1473
Hemant Kumar45d211b2012-05-31 17:58:43 -07001474 dbg_log_event(NULL, "PM Resume", 0);
1475
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301476 if (device_may_wakeup(dev))
1477 disable_irq_wake(hcd->irq);
1478
1479 ret = msm_hsic_resume(mehci);
1480 if (ret)
1481 return ret;
1482
1483 /* Bring the device to full powered state upon system resume */
1484 pm_runtime_disable(dev);
1485 pm_runtime_set_active(dev);
1486 pm_runtime_enable(dev);
1487
1488 return 0;
1489}
1490#endif
1491
1492#ifdef CONFIG_PM_RUNTIME
1493static int msm_hsic_runtime_idle(struct device *dev)
1494{
1495 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301496 return 0;
1497}
1498
1499static int msm_hsic_runtime_suspend(struct device *dev)
1500{
1501 struct usb_hcd *hcd = dev_get_drvdata(dev);
1502 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1503
1504 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001505
1506 dbg_log_event(NULL, "Run Time PM Suspend", 0);
1507
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301508 return msm_hsic_suspend(mehci);
1509}
1510
1511static int msm_hsic_runtime_resume(struct device *dev)
1512{
1513 struct usb_hcd *hcd = dev_get_drvdata(dev);
1514 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1515
1516 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001517
1518 dbg_log_event(NULL, "Run Time PM Resume", 0);
1519
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301520 return msm_hsic_resume(mehci);
1521}
1522#endif
1523
1524#ifdef CONFIG_PM
1525static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1526 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301527 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1528 msm_hsic_runtime_idle)
1529};
1530#endif
1531
1532static struct platform_driver ehci_msm_hsic_driver = {
1533 .probe = ehci_hsic_msm_probe,
1534 .remove = __devexit_p(ehci_hsic_msm_remove),
1535 .driver = {
1536 .name = "msm_hsic_host",
1537#ifdef CONFIG_PM
1538 .pm = &msm_hsic_dev_pm_ops,
1539#endif
1540 },
1541};