blob: a6b7dee1331901eb568cd299ddd60a9154e900fa [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/wakelock.h>
31#include <linux/pm_runtime.h>
32#include <linux/regulator/consumer.h>
33
34#include <linux/usb/msm_hsusb_hw.h>
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +053035#include <linux/usb/msm_hsusb.h>
36#include <linux/gpio.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030037#include <linux/spinlock.h>
38
39#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053040#include <mach/clk.h>
41#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053042#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080043#include <linux/spinlock.h>
Hemant Kumar45d211b2012-05-31 17:58:43 -070044#include <linux/cpu.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030045#include <mach/rpm-regulator.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053046
47#define MSM_USB_BASE (hcd->regs)
48
49struct msm_hsic_hcd {
50 struct ehci_hcd ehci;
51 struct device *dev;
52 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080053 struct clk *core_clk;
54 struct clk *alt_core_clk;
55 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053056 struct clk *cal_clk;
57 struct regulator *hsic_vddcx;
58 bool async_int;
59 atomic_t in_lpm;
60 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080061 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080062 int wakeup_irq;
Hemant Kumar6fd65032012-05-23 13:02:24 -070063 int wakeup_gpio;
Jack Phamfe441ea2012-03-23 17:03:15 -070064 bool wakeup_irq_enabled;
Hemant Kumar6fd65032012-05-23 13:02:24 -070065 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080066 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070067 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030068 enum usb_vdd_type vdd_type;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053069};
70
Hemant Kumare6275972012-02-29 20:06:21 -080071static bool debug_bus_voting_enabled = true;
Hemant Kumar45d211b2012-05-31 17:58:43 -070072
73static unsigned int enable_dbg_log = 1;
74module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
75/*by default log ep0 and efs sync ep*/
76static unsigned int ep_addr_rxdbg_mask = 9;
77module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
78static unsigned int ep_addr_txdbg_mask = 9;
79module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
80
81/* Maximum debug message length */
82#define DBG_MSG_LEN 100UL
83
84/* Maximum number of messages */
85#define DBG_MAX_MSG 256UL
86
87#define TIME_BUF_LEN 20
88
89enum event_type {
90 EVENT_UNDEF = -1,
91 URB_SUBMIT,
92 URB_COMPLETE,
93 EVENT_NONE,
94};
95
96#define EVENT_STR_LEN 5
97
98static char *event_to_str(enum event_type e)
99{
100 switch (e) {
101 case URB_SUBMIT:
102 return "S";
103 case URB_COMPLETE:
104 return "C";
105 case EVENT_NONE:
106 return "NONE";
107 default:
108 return "UNDEF";
109 }
110}
111
112static enum event_type str_to_event(const char *name)
113{
114 if (!strncasecmp("S", name, EVENT_STR_LEN))
115 return URB_SUBMIT;
116 if (!strncasecmp("C", name, EVENT_STR_LEN))
117 return URB_COMPLETE;
118 if (!strncasecmp("", name, EVENT_STR_LEN))
119 return EVENT_NONE;
120
121 return EVENT_UNDEF;
122}
123
124/*log ep0 activity*/
125static struct {
126 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
127 unsigned idx; /* index */
128 rwlock_t lck; /* lock */
129} dbg_hsic_ctrl = {
130 .idx = 0,
131 .lck = __RW_LOCK_UNLOCKED(lck)
132};
133
134static struct {
135 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
136 unsigned idx; /* index */
137 rwlock_t lck; /* lock */
138} dbg_hsic_data = {
139 .idx = 0,
140 .lck = __RW_LOCK_UNLOCKED(lck)
141};
142
143/**
144 * dbg_inc: increments debug event index
145 * @idx: buffer index
146 */
147static void dbg_inc(unsigned *idx)
148{
149 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
150}
151
152/*get_timestamp - returns time of day in us */
153static char *get_timestamp(char *tbuf)
154{
155 unsigned long long t;
156 unsigned long nanosec_rem;
157
158 t = cpu_clock(smp_processor_id());
159 nanosec_rem = do_div(t, 1000000000)/1000;
160 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
161 nanosec_rem);
162 return tbuf;
163}
164
165static int allow_dbg_log(int ep_addr)
166{
167 int dir, num;
168
169 dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
170 num = ep_addr & ~USB_DIR_IN;
171 num = 1 << num;
172
173 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
174 return 1;
175 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
176 return 1;
177
178 return 0;
179}
180
181static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
182{
183 unsigned long flags;
184 int ep_addr;
185 char tbuf[TIME_BUF_LEN];
186
187 if (!enable_dbg_log)
188 return;
189
190 if (!urb) {
191 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
192 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
193 "%s: %s : %u\n", get_timestamp(tbuf), event, extra);
194 dbg_inc(&dbg_hsic_ctrl.idx);
195 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
196 return;
197 }
198
199 ep_addr = urb->ep->desc.bEndpointAddress;
200 if (!allow_dbg_log(ep_addr))
201 return;
202
203 if ((ep_addr & 0x0f) == 0x0) {
204 /*submit event*/
205 if (!str_to_event(event)) {
206 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
207 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
208 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
209 "%02x %02x %04x %04x %04x %u %d\n",
210 get_timestamp(tbuf), event, urb,
211 (ep_addr & USB_DIR_IN) ? "in" : "out",
212 urb->setup_packet[0], urb->setup_packet[1],
213 (urb->setup_packet[3] << 8) |
214 urb->setup_packet[2],
215 (urb->setup_packet[5] << 8) |
216 urb->setup_packet[4],
217 (urb->setup_packet[7] << 8) |
218 urb->setup_packet[6],
219 urb->transfer_buffer_length, urb->status);
220
221 dbg_inc(&dbg_hsic_ctrl.idx);
222 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
223 } else {
224 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
225 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
226 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d\n",
227 get_timestamp(tbuf), event, urb,
228 (ep_addr & USB_DIR_IN) ? "in" : "out",
229 urb->actual_length, extra);
230
231 dbg_inc(&dbg_hsic_ctrl.idx);
232 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
233 }
234 } else {
235 write_lock_irqsave(&dbg_hsic_data.lck, flags);
236 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
237 "%s: [%s : %p]:ep%d[%s] %u %d\n",
238 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
239 (ep_addr & USB_DIR_IN) ? "in" : "out",
240 str_to_event(event) ? urb->actual_length :
241 urb->transfer_buffer_length,
242 str_to_event(event) ? extra : urb->status);
243
244 dbg_inc(&dbg_hsic_data.idx);
245 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
246 }
247}
248
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530249static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
250{
251 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
252}
253
254static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
255{
256 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
257}
258
259#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
260
Amit Blayd6ea6102012-06-07 16:26:24 +0300261#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700262#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
263#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530264
Lena Salman8c8ba382012-02-14 15:59:31 +0200265#define HSIC_DBG1_REG 0x38
266
Amit Blayd6ea6102012-06-07 16:26:24 +0300267static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
268 { /* VDD_CX CORNER Voting */
269 [VDD_NONE] = RPM_VREG_CORNER_NONE,
270 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
271 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
272 },
273 { /* VDD_CX Voltage Voting */
274 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
275 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
276 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
277 },
278};
279
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530280static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
281{
282 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300283 int none_vol, min_vol, max_vol;
284
285 if (!mehci->hsic_vddcx) {
286 mehci->vdd_type = VDDCX_CORNER;
287 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
288 "hsic_vdd_dig");
289 if (IS_ERR(mehci->hsic_vddcx)) {
290 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
291 "HSIC_VDDCX");
292 if (IS_ERR(mehci->hsic_vddcx)) {
293 dev_err(mehci->dev, "unable to get hsic vddcx\n");
294 return PTR_ERR(mehci->hsic_vddcx);
295 }
296 mehci->vdd_type = VDDCX;
297 }
298 }
299
300 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
301 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
302 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530303
304 if (!init)
305 goto disable_reg;
306
Amit Blayd6ea6102012-06-07 16:26:24 +0300307 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530308 if (ret) {
309 dev_err(mehci->dev, "unable to set the voltage"
310 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530311 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530312 }
313
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530314 ret = regulator_enable(mehci->hsic_vddcx);
315 if (ret) {
316 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
317 goto reg_enable_err;
318 }
319
320 return 0;
321
322disable_reg:
323 regulator_disable(mehci->hsic_vddcx);
324reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300325 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
326
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530327 return ret;
328
329}
330
331static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
332{
333 struct usb_hcd *hcd = hsic_to_hcd(mehci);
334 int cnt = 0;
335
336 /* initiate write operation */
337 writel_relaxed(ULPI_RUN | ULPI_WRITE |
338 ULPI_ADDR(reg) | ULPI_DATA(val),
339 USB_ULPI_VIEWPORT);
340
341 /* wait for completion */
342 while (cnt < ULPI_IO_TIMEOUT_USEC) {
343 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
344 break;
345 udelay(1);
346 cnt++;
347 }
348
349 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
350 dev_err(mehci->dev, "ulpi_write: timeout\n");
351 return -ETIMEDOUT;
352 }
353
354 return 0;
355}
356
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530357static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
358{
359 int rc = 0;
360 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800361 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530362
363 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800364
Lena Salman8c8ba382012-02-14 15:59:31 +0200365 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530366 return rc;
367
Vamsi Krishna34f01582011-12-14 19:54:42 -0800368 if (gpio_status == gpio_en)
369 return 0;
370
371 gpio_status = gpio_en;
372
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530373 if (!gpio_en)
374 goto free_gpio;
375
376 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
377 if (rc < 0) {
378 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
379 return rc;
380 }
381
382 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
383 if (rc < 0) {
384 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
385 goto free_strobe;
386 }
387
Hemant Kumar6fd65032012-05-23 13:02:24 -0700388 if (mehci->wakeup_gpio) {
389 rc = gpio_request(mehci->wakeup_gpio, "HSIC_WAKEUP_GPIO");
390 if (rc < 0) {
391 dev_err(mehci->dev, "gpio request failed for HSIC WAKEUP\n");
392 goto free_data;
393 }
394 }
395
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530396 return 0;
397
398free_gpio:
Hemant Kumar6fd65032012-05-23 13:02:24 -0700399 if (mehci->wakeup_gpio)
400 gpio_free(mehci->wakeup_gpio);
401free_data:
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530402 gpio_free(pdata->data);
403free_strobe:
404 gpio_free(pdata->strobe);
405
406 return rc;
407}
408
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530409static int msm_hsic_phy_clk_reset(struct msm_hsic_hcd *mehci)
410{
411 int ret;
412
Manu Gautam28b1bac2012-01-30 16:43:06 +0530413 clk_prepare_enable(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530414
Manu Gautam5143b252012-01-05 19:25:23 -0800415 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530416 if (ret) {
Manu Gautam28b1bac2012-01-30 16:43:06 +0530417 clk_disable_unprepare(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530418 dev_err(mehci->dev, "usb phy clk assert failed\n");
419 return ret;
420 }
421 usleep_range(10000, 12000);
Manu Gautam28b1bac2012-01-30 16:43:06 +0530422 clk_disable_unprepare(mehci->alt_core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530423
Manu Gautam5143b252012-01-05 19:25:23 -0800424 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530425 if (ret)
426 dev_err(mehci->dev, "usb phy clk deassert failed\n");
427
428 return ret;
429}
430
431static int msm_hsic_phy_reset(struct msm_hsic_hcd *mehci)
432{
433 struct usb_hcd *hcd = hsic_to_hcd(mehci);
434 u32 val;
435 int ret;
436
437 ret = msm_hsic_phy_clk_reset(mehci);
438 if (ret)
439 return ret;
440
441 val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
442 writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);
443
444 /* Ensure that RESET operation is completed before turning off clock */
445 mb();
446 dev_dbg(mehci->dev, "phy_reset: success\n");
447
448 return 0;
449}
450
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530451#define HSIC_GPIO150_PAD_CTL (MSM_TLMM_BASE+0x20C0)
452#define HSIC_GPIO151_PAD_CTL (MSM_TLMM_BASE+0x20C4)
453#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
454#define HSIC_LV_MODE 0x04
455#define HSIC_PAD_CALIBRATION 0xA8
456#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530457#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
458static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
459{
460 struct usb_hcd *hcd = hsic_to_hcd(mehci);
461 int cnt = 0;
462 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200463 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530464
465 ret = msm_hsic_phy_reset(mehci);
466 if (ret) {
467 dev_err(mehci->dev, "phy_reset failed\n");
468 return ret;
469 }
470
471 writel_relaxed(USBCMD_RESET, USB_USBCMD);
472 while (cnt < LINK_RESET_TIMEOUT_USEC) {
473 if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
474 break;
475 udelay(1);
476 cnt++;
477 }
478 if (cnt >= LINK_RESET_TIMEOUT_USEC)
479 return -ETIMEDOUT;
480
Lena Salman8c8ba382012-02-14 15:59:31 +0200481 /* Reset PORTSC and select ULPI phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530482 writel_relaxed(0x80000000, USB_PORTSC);
483
484 /* TODO: Need to confirm if HSIC PHY also requires delay after RESET */
485 msleep(100);
486
487 /* HSIC PHY Initialization */
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530488
Lena Salman8c8ba382012-02-14 15:59:31 +0200489 /* HSIC init sequence when HSIC signals (Strobe/Data) are
490 routed via GPIOs */
491 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530492
Lena Salman8c8ba382012-02-14 15:59:31 +0200493 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
494 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530495
Lena Salman8c8ba382012-02-14 15:59:31 +0200496 /*set periodic calibration interval to ~2.048sec in
497 HSIC_IO_CAL_REG */
498 ulpi_write(mehci, 0xFF, 0x33);
499
500 /* Enable periodic IO calibration in HSIC_CFG register */
501 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
502
503 /* Configure GPIO 150/151 pins for HSIC functionality mode */
504 ret = msm_hsic_config_gpios(mehci, 1);
505 if (ret) {
506 dev_err(mehci->dev, " gpio configuarion failed\n");
507 return ret;
508 }
509 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL
510 register */
511 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
512 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
513 /* Enable HSIC mode in HSIC_CFG register */
514 ulpi_write(mehci, 0x01, 0x31);
515 } else {
516 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
517 via dedicated I/O */
518
519 /* programmable length of connect signaling (33.2ns) */
520 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
521 if (ret) {
522 pr_err("%s: Unable to program length of connect "
523 "signaling\n", __func__);
524 }
525
526 /*set periodic calibration interval to ~2.048sec in
527 HSIC_IO_CAL_REG */
528 ulpi_write(mehci, 0xFF, 0x33);
529
530 /* Enable HSIC mode in HSIC_CFG register */
531 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530532 }
533
Hemant Kumar6fd65032012-05-23 13:02:24 -0700534 /*disable auto resume*/
535 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
536
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530537 return 0;
538}
539
540#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
541#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
542
543#ifdef CONFIG_PM_SLEEP
544static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
545{
546 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530547 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530548 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300549 int none_vol, max_vol;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530550
551 if (atomic_read(&mehci->in_lpm)) {
552 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
553 return 0;
554 }
555
Hemant Kumar7f374632012-05-31 20:10:32 -0700556 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
557 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
558 __func__);
559 return -EAGAIN;
560 }
561
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530562 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700563
564 /* make sure we don't race against a remote wakeup */
565 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
566 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
567 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
568 enable_irq(hcd->irq);
569 return -EBUSY;
570 }
571
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530572 /*
573 * PHY may take some time or even fail to enter into low power
574 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
575 * in failure case.
576 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700577 val = readl_relaxed(USB_PORTSC);
578 val &= ~PORT_RWC_BITS;
579 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530580 writel_relaxed(val, USB_PORTSC);
581 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
582 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
583 break;
584 udelay(1);
585 cnt++;
586 }
587
588 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
589 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530590 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530591 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530592 }
593
594 /*
595 * PHY has capability to generate interrupt asynchronously in low
596 * power mode (LPM). This interrupt is level triggered. So USB IRQ
597 * line must be disabled till async interrupt enable bit is cleared
598 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
599 * block data communication from PHY.
600 */
601 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
602 ULPI_STP_CTRL, USB_USBCMD);
603
604 /*
605 * Ensure that hardware is put in low power mode before
606 * clocks are turned OFF and VDD is allowed to minimize.
607 */
608 mb();
609
Manu Gautam28b1bac2012-01-30 16:43:06 +0530610 clk_disable_unprepare(mehci->core_clk);
611 clk_disable_unprepare(mehci->phy_clk);
612 clk_disable_unprepare(mehci->cal_clk);
613 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530614
Amit Blayd6ea6102012-06-07 16:26:24 +0300615 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
616 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
617
618 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700619 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300620 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700621
Hemant Kumare6275972012-02-29 20:06:21 -0800622 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
623 ret = msm_bus_scale_client_update_request(
624 mehci->bus_perf_client, 0);
625 if (ret)
626 dev_err(mehci->dev, "%s: Failed to dvote for "
627 "bus bandwidth %d\n", __func__, ret);
628 }
629
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530630 atomic_set(&mehci->in_lpm, 1);
631 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700632
633 mehci->wakeup_irq_enabled = 1;
634 enable_irq_wake(mehci->wakeup_irq);
635 enable_irq(mehci->wakeup_irq);
636
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530637 wake_unlock(&mehci->wlock);
638
639 dev_info(mehci->dev, "HSIC-USB in low power mode\n");
640
641 return 0;
642}
643
644static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
645{
646 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530647 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530648 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300649 int min_vol, max_vol;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530650
651 if (!atomic_read(&mehci->in_lpm)) {
652 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
653 return 0;
654 }
655
Hemant Kumar6fd65032012-05-23 13:02:24 -0700656 if (mehci->wakeup_irq_enabled) {
657 disable_irq_wake(mehci->wakeup_irq);
658 disable_irq_nosync(mehci->wakeup_irq);
659 mehci->wakeup_irq_enabled = 0;
660 }
661
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530662 wake_lock(&mehci->wlock);
663
Hemant Kumare6275972012-02-29 20:06:21 -0800664 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
665 ret = msm_bus_scale_client_update_request(
666 mehci->bus_perf_client, 1);
667 if (ret)
668 dev_err(mehci->dev, "%s: Failed to vote for "
669 "bus bandwidth %d\n", __func__, ret);
670 }
671
Amit Blayd6ea6102012-06-07 16:26:24 +0300672 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
673 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
674
675 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700676 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300677 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700678
Manu Gautam28b1bac2012-01-30 16:43:06 +0530679 clk_prepare_enable(mehci->core_clk);
680 clk_prepare_enable(mehci->phy_clk);
681 clk_prepare_enable(mehci->cal_clk);
682 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530683
684 temp = readl_relaxed(USB_USBCMD);
685 temp &= ~ASYNC_INTR_CTRL;
686 temp &= ~ULPI_STP_CTRL;
687 writel_relaxed(temp, USB_USBCMD);
688
689 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
690 goto skip_phy_resume;
691
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700692 temp = readl_relaxed(USB_PORTSC);
693 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530694 writel_relaxed(temp, USB_PORTSC);
695 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
696 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
697 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
698 break;
699 udelay(1);
700 cnt++;
701 }
702
703 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
704 /*
705 * This is a fatal error. Reset the link and
706 * PHY to make hsic working.
707 */
708 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530709 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530710 msm_hsic_reset(mehci);
711 }
712
713skip_phy_resume:
714
Hemant Kumard4ee29f2012-06-06 11:47:50 -0700715 if (!(readl_relaxed(USB_USBCMD) & CMD_RUN) &&
716 (readl_relaxed(USB_PORTSC) & PORT_SUSPEND)) {
717 writel_relaxed(readl_relaxed(USB_USBCMD) | CMD_RUN ,
718 USB_USBCMD);
719 dbg_log_event(NULL, "Set RS", readl_relaxed(USB_USBCMD));
720 }
721
Hemant Kumar6fd65032012-05-23 13:02:24 -0700722 usb_hcd_resume_root_hub(hcd);
723
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530724 atomic_set(&mehci->in_lpm, 0);
725
726 if (mehci->async_int) {
727 mehci->async_int = false;
728 pm_runtime_put_noidle(mehci->dev);
729 enable_irq(hcd->irq);
730 }
731
Hemant Kumar6fd65032012-05-23 13:02:24 -0700732 if (atomic_read(&mehci->pm_usage_cnt)) {
733 atomic_set(&mehci->pm_usage_cnt, 0);
734 pm_runtime_put_noidle(mehci->dev);
735 }
736
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530737 dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
738
739 return 0;
740}
741#endif
742
743static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
744{
745 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
746
747 if (atomic_read(&mehci->in_lpm)) {
748 disable_irq_nosync(hcd->irq);
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700749 dev_dbg(mehci->dev, "phy async intr\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530750 mehci->async_int = true;
751 pm_runtime_get(mehci->dev);
752 return IRQ_HANDLED;
753 }
754
755 return ehci_irq(hcd);
756}
757
758static int ehci_hsic_reset(struct usb_hcd *hcd)
759{
760 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
761 int retval;
762
763 ehci->caps = USB_CAPLENGTH;
764 ehci->regs = USB_CAPLENGTH +
765 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
766 dbg_hcs_params(ehci, "reset");
767 dbg_hcc_params(ehci, "reset");
768
769 /* cache the data to minimize the chip reads*/
770 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
771
772 hcd->has_tt = 1;
773 ehci->sbrn = HCD_USB2;
774
775 retval = ehci_halt(ehci);
776 if (retval)
777 return retval;
778
779 /* data structure init */
780 retval = ehci_init(hcd);
781 if (retval)
782 return retval;
783
784 retval = ehci_reset(ehci);
785 if (retval)
786 return retval;
787
788 /* bursts of unspecified length. */
789 writel_relaxed(0, USB_AHBBURST);
790 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530791 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530792 /* Disable streaming mode and select host mode */
793 writel_relaxed(0x13, USB_USBMODE);
794
795 ehci_port_power(ehci, 1);
796 return 0;
797}
798
Hemant Kumar45d211b2012-05-31 17:58:43 -0700799static int ehci_hsic_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
800 gfp_t mem_flags)
801{
802 dbg_log_event(urb, event_to_str(URB_SUBMIT), 0);
803 return ehci_urb_enqueue(hcd, urb, mem_flags);
804}
805
806static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
807{
808 dbg_log_event(NULL, "Suspend RH", 0);
809 return ehci_bus_suspend(hcd);
810}
811
812static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
813{
814 dbg_log_event(NULL, "Resume RH", 0);
815 return ehci_bus_resume(hcd);
816}
817
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530818static struct hc_driver msm_hsic_driver = {
819 .description = hcd_name,
820 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
821 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
822
823 /*
824 * generic hardware linkage
825 */
826 .irq = msm_hsic_irq,
827 .flags = HCD_USB2 | HCD_MEMORY,
828
829 .reset = ehci_hsic_reset,
830 .start = ehci_run,
831
832 .stop = ehci_stop,
833 .shutdown = ehci_shutdown,
834
835 /*
836 * managing i/o requests and associated device resources
837 */
Hemant Kumar45d211b2012-05-31 17:58:43 -0700838 .urb_enqueue = ehci_hsic_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530839 .urb_dequeue = ehci_urb_dequeue,
840 .endpoint_disable = ehci_endpoint_disable,
841 .endpoint_reset = ehci_endpoint_reset,
842 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
843
844 /*
845 * scheduling support
846 */
847 .get_frame_number = ehci_get_frame,
848
849 /*
850 * root hub support
851 */
852 .hub_status_data = ehci_hub_status_data,
853 .hub_control = ehci_hub_control,
854 .relinquish_port = ehci_relinquish_port,
855 .port_handed_over = ehci_port_handed_over,
856
857 /*
858 * PM support
859 */
Hemant Kumar45d211b2012-05-31 17:58:43 -0700860 .bus_suspend = ehci_hsic_bus_suspend,
861 .bus_resume = ehci_hsic_bus_resume,
862
863 .log_urb_complete = dbg_log_event,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530864};
865
866static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
867{
868 int ret = 0;
869
870 if (!init)
871 goto put_clocks;
872
Lena Salman8c8ba382012-02-14 15:59:31 +0200873 /*core_clk is required for LINK protocol engine
874 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800875 mehci->core_clk = clk_get(mehci->dev, "core_clk");
876 if (IS_ERR(mehci->core_clk)) {
877 dev_err(mehci->dev, "failed to get core_clk\n");
878 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530879 return ret;
880 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530881
Lena Salman8c8ba382012-02-14 15:59:31 +0200882 /* alt_core_clk is for LINK to be used during PHY RESET
883 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800884 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
885 if (IS_ERR(mehci->alt_core_clk)) {
886 dev_err(mehci->dev, "failed to core_clk\n");
887 ret = PTR_ERR(mehci->alt_core_clk);
888 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530889 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530890
Lena Salman8c8ba382012-02-14 15:59:31 +0200891 /* phy_clk is required for HSIC PHY operation
892 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -0800893 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
894 if (IS_ERR(mehci->phy_clk)) {
895 dev_err(mehci->dev, "failed to get phy_clk\n");
896 ret = PTR_ERR(mehci->phy_clk);
897 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530898 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530899
900 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -0800901 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530902 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800903 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530904 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800905 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530906 }
907 clk_set_rate(mehci->cal_clk, 10000000);
908
909 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -0800910 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530911 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -0800912 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530913 ret = PTR_ERR(mehci->ahb_clk);
914 goto put_cal_clk;
915 }
916
Manu Gautam28b1bac2012-01-30 16:43:06 +0530917 clk_prepare_enable(mehci->core_clk);
918 clk_prepare_enable(mehci->phy_clk);
919 clk_prepare_enable(mehci->cal_clk);
920 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530921
922 return 0;
923
924put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -0800925 if (!atomic_read(&mehci->in_lpm)) {
926 clk_disable_unprepare(mehci->core_clk);
927 clk_disable_unprepare(mehci->phy_clk);
928 clk_disable_unprepare(mehci->cal_clk);
929 clk_disable_unprepare(mehci->ahb_clk);
930 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530931 clk_put(mehci->ahb_clk);
932put_cal_clk:
933 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -0800934put_phy_clk:
935 clk_put(mehci->phy_clk);
936put_alt_core_clk:
937 clk_put(mehci->alt_core_clk);
938put_core_clk:
939 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530940
941 return ret;
942}
Vamsi Krishna34f01582011-12-14 19:54:42 -0800943static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
944{
945 struct msm_hsic_hcd *mehci = dev_id;
946
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800947 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -0800948
949 if (mehci)
950 msm_hsic_config_gpios(mehci, 0);
951
952 return IRQ_HANDLED;
953}
954
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800955static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
956{
957 struct msm_hsic_hcd *mehci = data;
958
Hemant Kumar6fd65032012-05-23 13:02:24 -0700959 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700960 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700961 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
962 __func__, mehci->wakeup_int_cnt);
963
964 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800965
Jack Phamfe441ea2012-03-23 17:03:15 -0700966 if (mehci->wakeup_irq_enabled) {
967 mehci->wakeup_irq_enabled = 0;
968 disable_irq_wake(irq);
969 disable_irq_nosync(irq);
970 }
971
Hemant Kumar6fd65032012-05-23 13:02:24 -0700972 if (!atomic_read(&mehci->pm_usage_cnt)) {
973 atomic_set(&mehci->pm_usage_cnt, 1);
974 pm_runtime_get(mehci->dev);
975 }
976
Vamsi Krishna6921cbe2012-02-21 18:34:43 -0800977 return IRQ_HANDLED;
978}
979
Hemant Kumare6275972012-02-29 20:06:21 -0800980static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
981{
982 if (debug_bus_voting_enabled)
983 seq_printf(s, "enabled\n");
984 else
985 seq_printf(s, "disabled\n");
986
987 return 0;
988}
989
990static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
991{
992 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
993}
994
995static ssize_t ehci_hsic_msm_bus_write(struct file *file,
996 const char __user *ubuf, size_t count, loff_t *ppos)
997{
998 char buf[8];
999 int ret;
1000 struct seq_file *s = file->private_data;
1001 struct msm_hsic_hcd *mehci = s->private;
1002
1003 memset(buf, 0x00, sizeof(buf));
1004
1005 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1006 return -EFAULT;
1007
1008 if (!strncmp(buf, "enable", 6)) {
1009 /* Do not vote here. Let hsic driver decide when to vote */
1010 debug_bus_voting_enabled = true;
1011 } else {
1012 debug_bus_voting_enabled = false;
1013 if (mehci->bus_perf_client) {
1014 ret = msm_bus_scale_client_update_request(
1015 mehci->bus_perf_client, 0);
1016 if (ret)
1017 dev_err(mehci->dev, "%s: Failed to devote "
1018 "for bus bw %d\n", __func__, ret);
1019 }
1020 }
1021
1022 return count;
1023}
1024
1025const struct file_operations ehci_hsic_msm_bus_fops = {
1026 .open = ehci_hsic_msm_bus_open,
1027 .read = seq_read,
1028 .write = ehci_hsic_msm_bus_write,
1029 .llseek = seq_lseek,
1030 .release = single_release,
1031};
1032
Hemant Kumar6fd65032012-05-23 13:02:24 -07001033static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1034{
1035 struct msm_hsic_hcd *mehci = s->private;
1036
1037 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1038
1039 return 0;
1040}
1041
1042static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1043{
1044 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1045}
1046
1047const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1048 .open = ehci_hsic_msm_wakeup_cnt_open,
1049 .read = seq_read,
1050 .llseek = seq_lseek,
1051 .release = single_release,
1052};
1053
Hemant Kumar45d211b2012-05-31 17:58:43 -07001054static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1055{
1056 unsigned long flags;
1057 unsigned i;
1058
1059 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1060
1061 i = dbg_hsic_data.idx;
1062 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1063 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1064 continue;
1065 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1066 }
1067
1068 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1069
1070 return 0;
1071}
1072
1073static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1074{
1075 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1076}
1077
1078const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1079 .open = ehci_hsic_msm_data_events_open,
1080 .read = seq_read,
1081 .llseek = seq_lseek,
1082 .release = single_release,
1083};
1084
1085static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1086{
1087 unsigned long flags;
1088 unsigned i;
1089
1090 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1091
1092 i = dbg_hsic_ctrl.idx;
1093 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1094 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1095 continue;
1096 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1097 }
1098
1099 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1100
1101 return 0;
1102}
1103
1104static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1105{
1106 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1107}
1108
1109const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1110 .open = ehci_hsic_msm_ctrl_events_open,
1111 .read = seq_read,
1112 .llseek = seq_lseek,
1113 .release = single_release,
1114};
1115
Hemant Kumare6275972012-02-29 20:06:21 -08001116static struct dentry *ehci_hsic_msm_dbg_root;
1117static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1118{
1119 struct dentry *ehci_hsic_msm_dentry;
1120
1121 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1122
1123 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1124 return -ENODEV;
1125
1126 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1127 S_IRUGO | S_IWUSR,
1128 ehci_hsic_msm_dbg_root, mehci,
1129 &ehci_hsic_msm_bus_fops);
1130
1131 if (!ehci_hsic_msm_dentry) {
1132 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1133 return -ENODEV;
1134 }
1135
Hemant Kumar6fd65032012-05-23 13:02:24 -07001136 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1137 S_IRUGO,
1138 ehci_hsic_msm_dbg_root, mehci,
1139 &ehci_hsic_msm_wakeup_cnt_fops);
1140
1141 if (!ehci_hsic_msm_dentry) {
1142 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1143 return -ENODEV;
1144 }
1145
Hemant Kumar45d211b2012-05-31 17:58:43 -07001146 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1147 S_IRUGO,
1148 ehci_hsic_msm_dbg_root, mehci,
1149 &ehci_hsic_msm_dbg_ctrl_fops);
1150
1151 if (!ehci_hsic_msm_dentry) {
1152 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1153 return -ENODEV;
1154 }
1155
1156 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1157 S_IRUGO,
1158 ehci_hsic_msm_dbg_root, mehci,
1159 &ehci_hsic_msm_dbg_data_fops);
1160
1161 if (!ehci_hsic_msm_dentry) {
1162 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1163 return -ENODEV;
1164 }
1165
Hemant Kumare6275972012-02-29 20:06:21 -08001166 return 0;
1167}
1168
1169static void ehci_hsic_msm_debugfs_cleanup(void)
1170{
1171 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1172}
1173
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301174static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1175{
1176 struct usb_hcd *hcd;
1177 struct resource *res;
1178 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301179 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301180 int ret;
1181
1182 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1183
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301184 /* After parent device's probe is executed, it will be put in suspend
1185 * mode. When child device's probe is called, driver core is not
1186 * resuming parent device due to which parent will be in suspend even
1187 * though child is active. Hence resume the parent device explicitly.
1188 */
1189 if (pdev->dev.parent)
1190 pm_runtime_get_sync(pdev->dev.parent);
1191
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301192 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1193 dev_name(&pdev->dev));
1194 if (!hcd) {
1195 dev_err(&pdev->dev, "Unable to create HCD\n");
1196 return -ENOMEM;
1197 }
1198
1199 hcd->irq = platform_get_irq(pdev, 0);
1200 if (hcd->irq < 0) {
1201 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1202 ret = hcd->irq;
1203 goto put_hcd;
1204 }
1205
1206 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1207 if (!res) {
1208 dev_err(&pdev->dev, "Unable to get memory resource\n");
1209 ret = -ENODEV;
1210 goto put_hcd;
1211 }
1212
1213 hcd->rsrc_start = res->start;
1214 hcd->rsrc_len = resource_size(res);
1215 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1216 if (!hcd->regs) {
1217 dev_err(&pdev->dev, "ioremap failed\n");
1218 ret = -ENOMEM;
1219 goto put_hcd;
1220 }
1221
1222 mehci = hcd_to_hsic(hcd);
1223 mehci->dev = &pdev->dev;
1224
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001225 mehci->ehci.susp_sof_bug = 1;
1226
Hemant Kumar933e0402012-05-22 11:11:40 -07001227 mehci->ehci.max_log2_irq_thresh = 6;
1228
Vamsi Krishna34f01582011-12-14 19:54:42 -08001229 res = platform_get_resource_byname(pdev,
1230 IORESOURCE_IRQ,
1231 "peripheral_status_irq");
1232 if (res)
1233 mehci->peripheral_status_irq = res->start;
1234
Hemant Kumar6fd65032012-05-23 13:02:24 -07001235 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
1236 if (res) {
1237 mehci->wakeup_gpio = res->start;
1238 mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
1239 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1240 }
1241
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301242 ret = msm_hsic_init_clocks(mehci, 1);
1243 if (ret) {
1244 dev_err(&pdev->dev, "unable to initialize clocks\n");
1245 ret = -ENODEV;
1246 goto unmap;
1247 }
1248
1249 ret = msm_hsic_init_vddcx(mehci, 1);
1250 if (ret) {
1251 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1252 ret = -ENODEV;
1253 goto deinit_clocks;
1254 }
1255
1256 ret = msm_hsic_reset(mehci);
1257 if (ret) {
1258 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301259 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301260 }
1261
1262 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1263 if (ret) {
1264 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301265 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301266 }
1267
1268 device_init_wakeup(&pdev->dev, 1);
1269 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1270 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001271
1272 if (mehci->peripheral_status_irq) {
1273 ret = request_threaded_irq(mehci->peripheral_status_irq,
1274 NULL, hsic_peripheral_status_change,
1275 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1276 | IRQF_SHARED,
1277 "hsic_peripheral_status", mehci);
1278 if (ret)
1279 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1280 __func__, mehci->peripheral_status_irq, ret);
1281 }
1282
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001283 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001284 if (mehci->wakeup_irq) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001285 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001286 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001287 "msm_hsic_wakeup", mehci);
1288 if (!ret) {
1289 disable_irq_nosync(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001290 } else {
1291 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1292 mehci->wakeup_irq, ret);
1293 mehci->wakeup_irq = 0;
1294 }
1295 }
1296
Hemant Kumare6275972012-02-29 20:06:21 -08001297 ret = ehci_hsic_msm_debugfs_init(mehci);
1298 if (ret)
1299 dev_dbg(&pdev->dev, "mode debugfs file is"
1300 "not available\n");
1301
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301302 pdata = mehci->dev->platform_data;
Hemant Kumare6275972012-02-29 20:06:21 -08001303 if (pdata && pdata->bus_scale_table) {
1304 mehci->bus_perf_client =
1305 msm_bus_scale_register_client(pdata->bus_scale_table);
1306 /* Configure BUS performance parameters for MAX bandwidth */
1307 if (mehci->bus_perf_client) {
1308 ret = msm_bus_scale_client_update_request(
1309 mehci->bus_perf_client, 1);
1310 if (ret)
1311 dev_err(&pdev->dev, "%s: Failed to vote for "
1312 "bus bandwidth %d\n", __func__, ret);
1313 } else {
1314 dev_err(&pdev->dev, "%s: Failed to register BUS "
1315 "scaling client!!\n", __func__);
1316 }
1317 }
1318
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301319 /*
1320 * This pdev->dev is assigned parent of root-hub by USB core,
1321 * hence, runtime framework automatically calls this driver's
1322 * runtime APIs based on root-hub's state.
1323 */
1324 pm_runtime_set_active(&pdev->dev);
1325 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301326 /* Decrement the parent device's counter after probe.
1327 * As child is active, parent will not be put into
1328 * suspend mode.
1329 */
1330 if (pdev->dev.parent)
1331 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301332
1333 return 0;
1334
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301335unconfig_gpio:
1336 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301337deinit_vddcx:
1338 msm_hsic_init_vddcx(mehci, 0);
1339deinit_clocks:
1340 msm_hsic_init_clocks(mehci, 0);
1341unmap:
1342 iounmap(hcd->regs);
1343put_hcd:
1344 usb_put_hcd(hcd);
1345
1346 return ret;
1347}
1348
1349static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1350{
1351 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1352 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1353
Vamsi Krishna34f01582011-12-14 19:54:42 -08001354 if (mehci->peripheral_status_irq)
1355 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001356
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001357 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001358 if (mehci->wakeup_irq_enabled)
1359 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001360 free_irq(mehci->wakeup_irq, mehci);
1361 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001362
Hemant Kumare6275972012-02-29 20:06:21 -08001363 if (mehci->bus_perf_client)
1364 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1365
1366 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301367 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301368 pm_runtime_set_suspended(&pdev->dev);
1369
1370 usb_remove_hcd(hcd);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301371 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301372 msm_hsic_init_vddcx(mehci, 0);
1373
1374 msm_hsic_init_clocks(mehci, 0);
1375 wake_lock_destroy(&mehci->wlock);
1376 iounmap(hcd->regs);
1377 usb_put_hcd(hcd);
1378
1379 return 0;
1380}
1381
1382#ifdef CONFIG_PM_SLEEP
1383static int msm_hsic_pm_suspend(struct device *dev)
1384{
Jack Phambe05fbb2012-05-16 10:56:26 -07001385 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301386 struct usb_hcd *hcd = dev_get_drvdata(dev);
1387 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1388
1389 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1390
Hemant Kumar45d211b2012-05-31 17:58:43 -07001391 dbg_log_event(NULL, "PM Suspend", 0);
1392
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301393 if (device_may_wakeup(dev))
1394 enable_irq_wake(hcd->irq);
1395
Jack Phambe05fbb2012-05-16 10:56:26 -07001396 ret = msm_hsic_suspend(mehci);
1397
1398 if (ret && device_may_wakeup(dev))
1399 disable_irq_wake(hcd->irq);
1400
1401 return ret;
Jack Phamfe441ea2012-03-23 17:03:15 -07001402}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301403
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301404static int msm_hsic_pm_resume(struct device *dev)
1405{
1406 int ret;
1407 struct usb_hcd *hcd = dev_get_drvdata(dev);
1408 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1409
Hemant Kumar45d211b2012-05-31 17:58:43 -07001410 dbg_log_event(NULL, "PM Resume", 0);
1411
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301412 if (device_may_wakeup(dev))
1413 disable_irq_wake(hcd->irq);
1414
1415 ret = msm_hsic_resume(mehci);
1416 if (ret)
1417 return ret;
1418
1419 /* Bring the device to full powered state upon system resume */
1420 pm_runtime_disable(dev);
1421 pm_runtime_set_active(dev);
1422 pm_runtime_enable(dev);
1423
1424 return 0;
1425}
1426#endif
1427
1428#ifdef CONFIG_PM_RUNTIME
1429static int msm_hsic_runtime_idle(struct device *dev)
1430{
1431 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301432 return 0;
1433}
1434
1435static int msm_hsic_runtime_suspend(struct device *dev)
1436{
1437 struct usb_hcd *hcd = dev_get_drvdata(dev);
1438 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1439
1440 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001441
1442 dbg_log_event(NULL, "Run Time PM Suspend", 0);
1443
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301444 return msm_hsic_suspend(mehci);
1445}
1446
1447static int msm_hsic_runtime_resume(struct device *dev)
1448{
1449 struct usb_hcd *hcd = dev_get_drvdata(dev);
1450 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1451
1452 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001453
1454 dbg_log_event(NULL, "Run Time PM Resume", 0);
1455
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301456 return msm_hsic_resume(mehci);
1457}
1458#endif
1459
1460#ifdef CONFIG_PM
1461static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1462 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301463 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1464 msm_hsic_runtime_idle)
1465};
1466#endif
1467
1468static struct platform_driver ehci_msm_hsic_driver = {
1469 .probe = ehci_hsic_msm_probe,
1470 .remove = __devexit_p(ehci_hsic_msm_remove),
1471 .driver = {
1472 .name = "msm_hsic_host",
1473#ifdef CONFIG_PM
1474 .pm = &msm_hsic_dev_pm_ops,
1475#endif
1476 },
1477};