blob: 14b96356cbf6d13022504edf2fa6508a64482dea [file] [log] [blame]
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301/* ehci-msm-hsic.c - HSUSB Host Controller Driver Implementation
2 *
Pavankumar Kondetibbd05822013-01-28 17:04:39 +05303 * Copyright (c) 2011-2013, Linux Foundation. All rights reserved.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05304 *
5 * Partly derived from ehci-fsl.c and ehci-hcd.c
6 * Copyright (c) 2000-2004 by David Brownell
7 * Copyright (c) 2005 MontaVista Software
8 *
9 * All source code in this file is licensed under the following license except
10 * where indicated.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published
14 * by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * See the GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, you can find it at http://www.fsf.org
23 */
24
25#include <linux/platform_device.h>
26#include <linux/clk.h>
27#include <linux/err.h>
Hemant Kumare6275972012-02-29 20:06:21 -080028#include <linux/debugfs.h>
29#include <linux/seq_file.h>
Ajay Dudaniab3bf192012-08-28 09:58:04 -070030#include <linux/wakelock.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053031#include <linux/pm_runtime.h>
32#include <linux/regulator/consumer.h>
33
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>
Ajay Dudani11ab1d52012-08-17 17:12:26 -070038#include <linux/kthread.h>
39#include <linux/wait.h>
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +053040#include <linux/pm_qos.h>
Hemant Kumar5e386632012-08-30 14:23:38 -070041#include <linux/irq.h>
Pavankumar Kondeti95933142013-10-10 22:39:15 +053042#include <linux/ktime.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030043
44#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053045#include <mach/clk.h>
46#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053047#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080048#include <linux/spinlock.h>
Hemant Kumar45d211b2012-05-31 17:58:43 -070049#include <linux/cpu.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030050#include <mach/rpm-regulator.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053051
52#define MSM_USB_BASE (hcd->regs)
Hemant Kumar105d07f2012-07-02 15:33:07 -070053#define USB_REG_START_OFFSET 0x90
54#define USB_REG_END_OFFSET 0x250
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053055
Pavankumar Kondeti95933142013-10-10 22:39:15 +053056#define RESUME_RETRY_LIMIT 3
57#define RESUME_SIGNAL_TIME_USEC (21 * 1000)
58#define RESUME_SIGNAL_TIME_SOF_USEC (23 * 1000)
59
Hemant Kumar2309eaa2012-08-14 16:46:42 -070060static struct workqueue_struct *ehci_wq;
Ajay Dudani11ab1d52012-08-17 17:12:26 -070061struct ehci_timer {
62#define GPT_LD(p) ((p) & 0x00FFFFFF)
63 u32 gptimer0_ld;
64#define GPT_RUN BIT(31)
65#define GPT_RESET BIT(30)
66#define GPT_MODE BIT(24)
67#define GPT_CNT(p) ((p) & 0x00FFFFFF)
68 u32 gptimer0_ctrl;
69
70 u32 gptimer1_ld;
71 u32 gptimer1_ctrl;
72};
Hemant Kumar2309eaa2012-08-14 16:46:42 -070073
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053074struct msm_hsic_hcd {
75 struct ehci_hcd ehci;
Hemant Kumar4cd49e12012-09-06 19:57:14 -070076 spinlock_t wakeup_lock;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053077 struct device *dev;
78 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080079 struct clk *core_clk;
80 struct clk *alt_core_clk;
81 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053082 struct clk *cal_clk;
83 struct regulator *hsic_vddcx;
Pavankumar Kondetibbd05822013-01-28 17:04:39 +053084 atomic_t async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053085 atomic_t in_lpm;
Ajay Dudaniab3bf192012-08-28 09:58:04 -070086 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080087 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080088 int wakeup_irq;
Hemant Kumar6fd65032012-05-23 13:02:24 -070089 int wakeup_gpio;
Jack Phamfe441ea2012-03-23 17:03:15 -070090 bool wakeup_irq_enabled;
Ajay Dudaniab3bf192012-08-28 09:58:04 -070091 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080092 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070093 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030094 enum usb_vdd_type vdd_type;
Hemant Kumar2309eaa2012-08-14 16:46:42 -070095
96 struct work_struct bus_vote_w;
97 bool bus_vote;
Ajay Dudani11ab1d52012-08-17 17:12:26 -070098
99 /* gp timer */
100 struct ehci_timer __iomem *timer;
101 struct completion gpt0_completion;
102 struct completion rt_completion;
103 int resume_status;
104 int resume_again;
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530105 int bus_reset;
106 int reset_again;
Pavankumar Kondeti95933142013-10-10 22:39:15 +0530107 ktime_t resume_start_t;
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +0530108
109 struct pm_qos_request pm_qos_req_dma;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530110};
111
Hemant Kumar105d07f2012-07-02 15:33:07 -0700112struct msm_hsic_hcd *__mehci;
113
Hemant Kumare6275972012-02-29 20:06:21 -0800114static bool debug_bus_voting_enabled = true;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700115
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700116static unsigned int enable_payload_log = 1;
117module_param(enable_payload_log, uint, S_IRUGO | S_IWUSR);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700118static unsigned int enable_dbg_log = 1;
119module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
120/*by default log ep0 and efs sync ep*/
121static unsigned int ep_addr_rxdbg_mask = 9;
122module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
123static unsigned int ep_addr_txdbg_mask = 9;
124module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
125
126/* Maximum debug message length */
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700127#define DBG_MSG_LEN 128UL
Hemant Kumar45d211b2012-05-31 17:58:43 -0700128
129/* Maximum number of messages */
130#define DBG_MAX_MSG 256UL
131
132#define TIME_BUF_LEN 20
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700133#define HEX_DUMP_LEN 72
Hemant Kumar45d211b2012-05-31 17:58:43 -0700134
135enum event_type {
136 EVENT_UNDEF = -1,
137 URB_SUBMIT,
138 URB_COMPLETE,
139 EVENT_NONE,
140};
141
142#define EVENT_STR_LEN 5
143
Hemant Kumar45d211b2012-05-31 17:58:43 -0700144static enum event_type str_to_event(const char *name)
145{
146 if (!strncasecmp("S", name, EVENT_STR_LEN))
147 return URB_SUBMIT;
148 if (!strncasecmp("C", name, EVENT_STR_LEN))
149 return URB_COMPLETE;
150 if (!strncasecmp("", name, EVENT_STR_LEN))
151 return EVENT_NONE;
152
153 return EVENT_UNDEF;
154}
155
156/*log ep0 activity*/
157static struct {
158 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
159 unsigned idx; /* index */
160 rwlock_t lck; /* lock */
161} dbg_hsic_ctrl = {
162 .idx = 0,
163 .lck = __RW_LOCK_UNLOCKED(lck)
164};
165
166static struct {
167 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
168 unsigned idx; /* index */
169 rwlock_t lck; /* lock */
170} dbg_hsic_data = {
171 .idx = 0,
172 .lck = __RW_LOCK_UNLOCKED(lck)
173};
174
175/**
176 * dbg_inc: increments debug event index
177 * @idx: buffer index
178 */
179static void dbg_inc(unsigned *idx)
180{
181 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
182}
183
184/*get_timestamp - returns time of day in us */
185static char *get_timestamp(char *tbuf)
186{
187 unsigned long long t;
188 unsigned long nanosec_rem;
189
190 t = cpu_clock(smp_processor_id());
191 nanosec_rem = do_div(t, 1000000000)/1000;
192 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
193 nanosec_rem);
194 return tbuf;
195}
196
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530197static int allow_dbg_log(struct urb *urb, int ep_addr)
Hemant Kumar45d211b2012-05-31 17:58:43 -0700198{
199 int dir, num;
200
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530201 dir = usb_urb_dir_in(urb) ? USB_DIR_IN : USB_DIR_OUT;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700202 num = ep_addr & ~USB_DIR_IN;
203 num = 1 << num;
204
205 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
206 return 1;
207 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
208 return 1;
209
210 return 0;
211}
212
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530213static char *
214get_hex_data(char *dbuf, struct urb *urb, int event, int status, size_t max_len)
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700215{
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700216 char *ubuf = urb->transfer_buffer;
217 size_t len = event ? \
218 urb->actual_length : urb->transfer_buffer_length;
219
220 if (status == -EINPROGRESS)
221 status = 0;
222
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530223 /*Only dump ep in successful completions and epout submissions*/
224 if (len && !status && ((usb_urb_dir_in(urb) && event) ||
225 (usb_urb_dir_out(urb) && !event))) {
226 if (len >= max_len)
227 len = max_len;
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700228 hex_dump_to_buffer(ubuf, len, 32, 4, dbuf, HEX_DUMP_LEN, 0);
229 } else {
230 dbuf = "";
231 }
232
233 return dbuf;
234}
235
Hemant Kumar45d211b2012-05-31 17:58:43 -0700236static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
237{
238 unsigned long flags;
239 int ep_addr;
240 char tbuf[TIME_BUF_LEN];
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700241 char dbuf[HEX_DUMP_LEN];
Hemant Kumar45d211b2012-05-31 17:58:43 -0700242
243 if (!enable_dbg_log)
244 return;
245
246 if (!urb) {
247 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
248 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700249 "%s: %s : %u", get_timestamp(tbuf), event, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700250 dbg_inc(&dbg_hsic_ctrl.idx);
251 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
252 return;
253 }
254
255 ep_addr = urb->ep->desc.bEndpointAddress;
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530256 if (!allow_dbg_log(urb, ep_addr))
Hemant Kumar45d211b2012-05-31 17:58:43 -0700257 return;
258
259 if ((ep_addr & 0x0f) == 0x0) {
260 /*submit event*/
261 if (!str_to_event(event)) {
262 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
263 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
264 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530265 "%02x %02x %04x %04x %04x %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700266 get_timestamp(tbuf), event, urb,
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530267 usb_urb_dir_in(urb) ? "in" : "out",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700268 urb->setup_packet[0], urb->setup_packet[1],
269 (urb->setup_packet[3] << 8) |
270 urb->setup_packet[2],
271 (urb->setup_packet[5] << 8) |
272 urb->setup_packet[4],
273 (urb->setup_packet[7] << 8) |
274 urb->setup_packet[6],
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530275 urb->transfer_buffer_length, extra,
276 enable_payload_log ? get_hex_data(dbuf, urb,
277 str_to_event(event), extra, 16) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700278
279 dbg_inc(&dbg_hsic_ctrl.idx);
280 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
281 } else {
282 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
283 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530284 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700285 get_timestamp(tbuf), event, urb,
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530286 usb_urb_dir_in(urb) ? "in" : "out",
287 urb->actual_length, extra,
288 enable_payload_log ? get_hex_data(dbuf, urb,
289 str_to_event(event), extra, 16) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700290
291 dbg_inc(&dbg_hsic_ctrl.idx);
292 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
293 }
294 } else {
295 write_lock_irqsave(&dbg_hsic_data.lck, flags);
296 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700297 "%s: [%s : %p]:ep%d[%s] %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700298 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530299 usb_urb_dir_in(urb) ? "in" : "out",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700300 str_to_event(event) ? urb->actual_length :
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700301 urb->transfer_buffer_length, extra,
302 enable_payload_log ? get_hex_data(dbuf, urb,
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530303 str_to_event(event), extra, 32) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700304
305 dbg_inc(&dbg_hsic_data.idx);
306 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
307 }
308}
309
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530310static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
311{
312 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
313}
314
315static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
316{
317 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
318}
319
Hemant Kumar105d07f2012-07-02 15:33:07 -0700320static void dump_hsic_regs(struct usb_hcd *hcd)
321{
322 int i;
323 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
324
325 if (atomic_read(&mehci->in_lpm))
326 return;
327
328 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
329 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
330 readl_relaxed(hcd->regs + i),
331 readl_relaxed(hcd->regs + i + 4),
332 readl_relaxed(hcd->regs + i + 8),
333 readl_relaxed(hcd->regs + i + 0xc));
334}
335
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530336#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
337
Amit Blayd6ea6102012-06-07 16:26:24 +0300338#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Hemant Kumar266d9d52012-10-17 13:48:10 -0700339#define USB_PHY_VDD_DIG_VOL_MIN 945000 /* uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700340#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530341
Lena Salman8c8ba382012-02-14 15:59:31 +0200342#define HSIC_DBG1_REG 0x38
343
Amit Blayd6ea6102012-06-07 16:26:24 +0300344static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
345 { /* VDD_CX CORNER Voting */
346 [VDD_NONE] = RPM_VREG_CORNER_NONE,
347 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
348 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
349 },
350 { /* VDD_CX Voltage Voting */
351 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
352 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
353 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
354 },
355};
356
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530357static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
358{
359 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300360 int none_vol, min_vol, max_vol;
361
362 if (!mehci->hsic_vddcx) {
363 mehci->vdd_type = VDDCX_CORNER;
364 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
365 "hsic_vdd_dig");
366 if (IS_ERR(mehci->hsic_vddcx)) {
367 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
368 "HSIC_VDDCX");
369 if (IS_ERR(mehci->hsic_vddcx)) {
370 dev_err(mehci->dev, "unable to get hsic vddcx\n");
371 return PTR_ERR(mehci->hsic_vddcx);
372 }
373 mehci->vdd_type = VDDCX;
374 }
375 }
376
377 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
378 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
379 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530380
381 if (!init)
382 goto disable_reg;
383
Amit Blayd6ea6102012-06-07 16:26:24 +0300384 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530385 if (ret) {
386 dev_err(mehci->dev, "unable to set the voltage"
387 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530388 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530389 }
390
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530391 ret = regulator_enable(mehci->hsic_vddcx);
392 if (ret) {
393 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
394 goto reg_enable_err;
395 }
396
397 return 0;
398
399disable_reg:
400 regulator_disable(mehci->hsic_vddcx);
401reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300402 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
403
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530404 return ret;
405
406}
407
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530408static int __maybe_unused ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700409{
410 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Devin Kim01e5a5b2012-08-30 02:52:45 -0700411 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700412
413 /* initiate read operation */
414 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
415 USB_ULPI_VIEWPORT);
416
417 /* wait for completion */
Devin Kim01e5a5b2012-08-30 02:52:45 -0700418 while (cnt < ULPI_IO_TIMEOUT_USEC) {
419 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
420 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700421 udelay(1);
Devin Kim01e5a5b2012-08-30 02:52:45 -0700422 cnt++;
423 }
424
425 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
426 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
427 readl_relaxed(USB_ULPI_VIEWPORT));
428 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
429 readl_relaxed(USB_PORTSC),
430 readl_relaxed(USB_USBCMD),
431 readl_relaxed(USB_FRINDEX));
432
433 /*frame counter increments afte 125us*/
434 udelay(130);
435 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
436 readl_relaxed(USB_FRINDEX));
437 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700438 }
439
440 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
441}
442
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530443static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
444{
445 struct usb_hcd *hcd = hsic_to_hcd(mehci);
446 int cnt = 0;
447
448 /* initiate write operation */
449 writel_relaxed(ULPI_RUN | ULPI_WRITE |
450 ULPI_ADDR(reg) | ULPI_DATA(val),
451 USB_ULPI_VIEWPORT);
452
453 /* wait for completion */
454 while (cnt < ULPI_IO_TIMEOUT_USEC) {
455 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
456 break;
457 udelay(1);
458 cnt++;
459 }
460
461 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Devin Kim01e5a5b2012-08-30 02:52:45 -0700462 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
463 readl_relaxed(USB_ULPI_VIEWPORT));
464 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
465 readl_relaxed(USB_PORTSC),
466 readl_relaxed(USB_USBCMD),
467 readl_relaxed(USB_FRINDEX));
468
469 /*frame counter increments afte 125us*/
470 udelay(130);
471 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
472 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530473 return -ETIMEDOUT;
474 }
475
476 return 0;
477}
478
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530479static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
480{
481 int rc = 0;
482 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800483 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530484
485 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800486
Lena Salman8c8ba382012-02-14 15:59:31 +0200487 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530488 return rc;
489
Vamsi Krishna34f01582011-12-14 19:54:42 -0800490 if (gpio_status == gpio_en)
491 return 0;
492
493 gpio_status = gpio_en;
494
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530495 if (!gpio_en)
496 goto free_gpio;
497
498 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
499 if (rc < 0) {
500 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
501 return rc;
502 }
503
504 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
505 if (rc < 0) {
506 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
507 goto free_strobe;
508 }
509
Hemant Kumar6fd65032012-05-23 13:02:24 -0700510 if (mehci->wakeup_gpio) {
511 rc = gpio_request(mehci->wakeup_gpio, "HSIC_WAKEUP_GPIO");
512 if (rc < 0) {
513 dev_err(mehci->dev, "gpio request failed for HSIC WAKEUP\n");
514 goto free_data;
515 }
516 }
517
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530518 return 0;
519
520free_gpio:
Hemant Kumar6fd65032012-05-23 13:02:24 -0700521 if (mehci->wakeup_gpio)
522 gpio_free(mehci->wakeup_gpio);
523free_data:
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530524 gpio_free(pdata->data);
525free_strobe:
526 gpio_free(pdata->strobe);
527
528 return rc;
529}
530
Vamsi Krishna64b48612012-06-14 16:08:11 -0700531static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530532{
533 int ret;
534
Manu Gautam5143b252012-01-05 19:25:23 -0800535 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530536 if (ret) {
Vamsi Krishna64b48612012-06-14 16:08:11 -0700537 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
538 return;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530539 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700540 clk_disable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530541
Manu Gautam5143b252012-01-05 19:25:23 -0800542 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530543 if (ret)
Vamsi Krishna64b48612012-06-14 16:08:11 -0700544 dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530545
Vamsi Krishna64b48612012-06-14 16:08:11 -0700546 usleep_range(10000, 12000);
547
548 clk_enable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530549}
550
Vamsi Krishna64b48612012-06-14 16:08:11 -0700551#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
552#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530553#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
554#define HSIC_LV_MODE 0x04
555#define HSIC_PAD_CALIBRATION 0xA8
556#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530557#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
558static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
559{
560 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530561 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200562 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
ChandanaKishori Chiluveru0a78e972013-12-06 12:35:46 +0530563 u32 temp;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530564
Vamsi Krishna64b48612012-06-14 16:08:11 -0700565 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530566
Vamsi Krishna64b48612012-06-14 16:08:11 -0700567 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530568 writel_relaxed(0x80000000, USB_PORTSC);
569
Vamsi Krishna64b48612012-06-14 16:08:11 -0700570 mb();
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530571
Lena Salman8c8ba382012-02-14 15:59:31 +0200572 /* HSIC init sequence when HSIC signals (Strobe/Data) are
573 routed via GPIOs */
574 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530575
Lena Salman8c8ba382012-02-14 15:59:31 +0200576 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
577 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530578
Vamsi Krishna64b48612012-06-14 16:08:11 -0700579 mb();
580
Lena Salman8c8ba382012-02-14 15:59:31 +0200581 /*set periodic calibration interval to ~2.048sec in
582 HSIC_IO_CAL_REG */
583 ulpi_write(mehci, 0xFF, 0x33);
584
585 /* Enable periodic IO calibration in HSIC_CFG register */
586 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
587
Vamsi Krishna64b48612012-06-14 16:08:11 -0700588 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200589 ret = msm_hsic_config_gpios(mehci, 1);
590 if (ret) {
591 dev_err(mehci->dev, " gpio configuarion failed\n");
592 return ret;
593 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700594 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO PAD_CTL register */
595 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_STROBE_GPIO_PAD_CTL);
596 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_DATA_GPIO_PAD_CTL);
597
598 mb();
599
Lena Salman8c8ba382012-02-14 15:59:31 +0200600 /* Enable HSIC mode in HSIC_CFG register */
601 ulpi_write(mehci, 0x01, 0x31);
602 } else {
603 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
604 via dedicated I/O */
605
606 /* programmable length of connect signaling (33.2ns) */
607 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
608 if (ret) {
609 pr_err("%s: Unable to program length of connect "
610 "signaling\n", __func__);
611 }
612
613 /*set periodic calibration interval to ~2.048sec in
614 HSIC_IO_CAL_REG */
615 ulpi_write(mehci, 0xFF, 0x33);
616
617 /* Enable HSIC mode in HSIC_CFG register */
618 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530619 }
620
ChandanaKishori Chiluveru0a78e972013-12-06 12:35:46 +0530621 temp = readl_relaxed(USB_GENCONFIG2);
622 temp &= ~GENCFG2_SYS_CLK_HOST_DEV_GATE_EN;
623 writel_relaxed(temp, USB_GENCONFIG2);
624
Hemant Kumar6fd65032012-05-23 13:02:24 -0700625 /*disable auto resume*/
626 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
627
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530628 return 0;
629}
630
631#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
632#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
633
634#ifdef CONFIG_PM_SLEEP
635static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
636{
637 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530638 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530639 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300640 int none_vol, max_vol;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530641
642 if (atomic_read(&mehci->in_lpm)) {
643 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
644 return 0;
645 }
646
647 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700648
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700649 /* make sure we don't race against a remote wakeup */
650 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700651 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700652 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700653 enable_irq(hcd->irq);
654 return -EBUSY;
655 }
656
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530657 /*
658 * PHY may take some time or even fail to enter into low power
659 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
660 * in failure case.
661 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700662 val = readl_relaxed(USB_PORTSC);
663 val &= ~PORT_RWC_BITS;
664 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530665 writel_relaxed(val, USB_PORTSC);
666 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
667 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
668 break;
669 udelay(1);
670 cnt++;
671 }
672
673 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
674 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530675 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530676 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530677 }
678
679 /*
680 * PHY has capability to generate interrupt asynchronously in low
681 * power mode (LPM). This interrupt is level triggered. So USB IRQ
682 * line must be disabled till async interrupt enable bit is cleared
683 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
Pavankumar Kondeti1c1d82b2013-01-28 21:37:59 +0530684 * block data communication from PHY. Enable asynchronous interrupt
685 * only when wakeup gpio IRQ is not present.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530686 */
Pavankumar Kondeti1c1d82b2013-01-28 21:37:59 +0530687 if (mehci->wakeup_irq)
688 writel_relaxed(readl_relaxed(USB_USBCMD) |
689 ULPI_STP_CTRL, USB_USBCMD);
690 else
691 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530692 ULPI_STP_CTRL, USB_USBCMD);
693
694 /*
695 * Ensure that hardware is put in low power mode before
696 * clocks are turned OFF and VDD is allowed to minimize.
697 */
698 mb();
699
Manu Gautam28b1bac2012-01-30 16:43:06 +0530700 clk_disable_unprepare(mehci->core_clk);
701 clk_disable_unprepare(mehci->phy_clk);
702 clk_disable_unprepare(mehci->cal_clk);
703 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530704
Amit Blayd6ea6102012-06-07 16:26:24 +0300705 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
706 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
707
708 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700709 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300710 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700711
Hemant Kumare6275972012-02-29 20:06:21 -0800712 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700713 mehci->bus_vote = false;
714 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800715 }
716
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530717 atomic_set(&mehci->in_lpm, 1);
718 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700719
720 mehci->wakeup_irq_enabled = 1;
721 enable_irq_wake(mehci->wakeup_irq);
722 enable_irq(mehci->wakeup_irq);
723
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700724 wake_unlock(&mehci->wlock);
725
Devin Kim476bbd72012-07-19 18:11:11 -0700726 dev_dbg(mehci->dev, "HSIC-USB in low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530727
728 return 0;
729}
730
731static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
732{
733 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530734 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530735 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300736 int min_vol, max_vol;
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700737 unsigned long flags;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530738
739 if (!atomic_read(&mehci->in_lpm)) {
740 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
741 return 0;
742 }
743
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530744 /* Handles race with Async interrupt */
745 disable_irq(hcd->irq);
746
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700747 spin_lock_irqsave(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700748 if (mehci->wakeup_irq_enabled) {
749 disable_irq_wake(mehci->wakeup_irq);
750 disable_irq_nosync(mehci->wakeup_irq);
751 mehci->wakeup_irq_enabled = 0;
752 }
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700753 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700754
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700755 wake_lock(&mehci->wlock);
756
Hemant Kumare6275972012-02-29 20:06:21 -0800757 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700758 mehci->bus_vote = true;
759 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800760 }
761
Amit Blayd6ea6102012-06-07 16:26:24 +0300762 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
763 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
764
765 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700766 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300767 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700768
Manu Gautam28b1bac2012-01-30 16:43:06 +0530769 clk_prepare_enable(mehci->core_clk);
770 clk_prepare_enable(mehci->phy_clk);
771 clk_prepare_enable(mehci->cal_clk);
772 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530773
774 temp = readl_relaxed(USB_USBCMD);
775 temp &= ~ASYNC_INTR_CTRL;
776 temp &= ~ULPI_STP_CTRL;
777 writel_relaxed(temp, USB_USBCMD);
778
779 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
780 goto skip_phy_resume;
781
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700782 temp = readl_relaxed(USB_PORTSC);
783 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530784 writel_relaxed(temp, USB_PORTSC);
785 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
786 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
787 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
788 break;
789 udelay(1);
790 cnt++;
791 }
792
793 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
794 /*
795 * This is a fatal error. Reset the link and
796 * PHY to make hsic working.
797 */
798 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530799 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530800 msm_hsic_reset(mehci);
801 }
802
803skip_phy_resume:
804
Hemant Kumar6fd65032012-05-23 13:02:24 -0700805 usb_hcd_resume_root_hub(hcd);
806
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530807 atomic_set(&mehci->in_lpm, 0);
808
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530809 if (atomic_read(&mehci->async_int)) {
810 atomic_set(&mehci->async_int, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530811 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700812 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700813 }
814
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700815 if (atomic_read(&mehci->pm_usage_cnt)) {
816 atomic_set(&mehci->pm_usage_cnt, 0);
817 pm_runtime_put_noidle(mehci->dev);
818 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700819
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530820 enable_irq(hcd->irq);
Devin Kim476bbd72012-07-19 18:11:11 -0700821 dev_dbg(mehci->dev, "HSIC-USB exited from low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530822
823 return 0;
824}
825#endif
826
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700827static void ehci_hsic_bus_vote_w(struct work_struct *w)
828{
829 struct msm_hsic_hcd *mehci =
830 container_of(w, struct msm_hsic_hcd, bus_vote_w);
831 int ret;
832
833 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
834 mehci->bus_vote);
835 if (ret)
836 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
837 __func__, ret);
838}
839
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530840static int msm_hsic_reset_done(struct usb_hcd *hcd)
841{
842 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
843 u32 __iomem *status_reg = &ehci->regs->port_status[0];
844 int ret;
845
846 ehci_writel(ehci, ehci_readl(ehci, status_reg) & ~(PORT_RWC_BITS |
847 PORT_RESET), status_reg);
848
849 ret = handshake(ehci, status_reg, PORT_RESET, 0, 1 * 1000);
850
851 if (ret)
852 pr_err("reset handshake failed in %s\n", __func__);
853 else
854 ehci_writel(ehci, ehci_readl(ehci, &ehci->regs->command) |
855 CMD_RUN, &ehci->regs->command);
856
857 return ret;
858}
859
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700860#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530861static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
862{
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700863 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530864 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700865 u32 status;
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530866 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530867
868 if (atomic_read(&mehci->in_lpm)) {
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700869 dev_dbg(mehci->dev, "phy async intr\n");
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530870 dbg_log_event(NULL, "Async IRQ", 0);
871 ret = pm_runtime_get(mehci->dev);
872 if ((ret == 1) || (ret == -EINPROGRESS)) {
873 pm_runtime_put_noidle(mehci->dev);
874 } else {
875 disable_irq_nosync(hcd->irq);
876 atomic_set(&mehci->async_int, 1);
877 }
878
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530879 return IRQ_HANDLED;
880 }
881
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700882 status = ehci_readl(ehci, &ehci->regs->status);
883
884 if (status & STS_GPTIMER0_INTERRUPT) {
885 int timeleft;
886
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530887 dbg_log_event(NULL, "FPR: gpt0_isr", mehci->bus_reset);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700888
889 timeleft = GPT_CNT(ehci_readl(ehci,
890 &mehci->timer->gptimer1_ctrl));
Pavankumar Kondeti95933142013-10-10 22:39:15 +0530891 if (!mehci->bus_reset) {
892 if (ktime_us_delta(ktime_get(), mehci->resume_start_t) >
893 RESUME_SIGNAL_TIME_SOF_USEC) {
894 dbg_log_event(NULL, "FPR: GPT prog invalid",
895 timeleft);
896 pr_err("HSIC GPT timer prog invalid\n");
897 timeleft = 0;
898 }
899 }
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700900 if (timeleft) {
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530901 if (mehci->bus_reset) {
902 ret = msm_hsic_reset_done(hcd);
903 if (ret) {
904 mehci->reset_again = 1;
905 dbg_log_event(NULL, "RESET: fail", 0);
906 }
907 } else {
Pavankumar Kondeti95933142013-10-10 22:39:15 +0530908 writel_relaxed(readl_relaxed(
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530909 &ehci->regs->command) | CMD_RUN,
910 &ehci->regs->command);
Pavankumar Kondeti95933142013-10-10 22:39:15 +0530911 if (ktime_us_delta(ktime_get(),
912 mehci->resume_start_t) >
913 RESUME_SIGNAL_TIME_SOF_USEC) {
914 dbg_log_event(NULL,
915 "FPR: resume prog invalid",
916 timeleft);
917 pr_err("HSIC resume fail. retrying\n");
918 mehci->resume_again = 1;
919 }
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530920 }
921 } else {
922 if (mehci->bus_reset)
923 mehci->reset_again = 1;
924 else
925 mehci->resume_again = 1;
926 }
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700927
928 dbg_log_event(NULL, "FPR: timeleft", timeleft);
929
930 complete(&mehci->gpt0_completion);
931 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
932 }
933
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530934 return ehci_irq(hcd);
935}
936
937static int ehci_hsic_reset(struct usb_hcd *hcd)
938{
939 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700940 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530941 int retval;
942
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700943 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530944 ehci->caps = USB_CAPLENGTH;
945 ehci->regs = USB_CAPLENGTH +
946 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
947 dbg_hcs_params(ehci, "reset");
948 dbg_hcc_params(ehci, "reset");
949
950 /* cache the data to minimize the chip reads*/
951 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
952
953 hcd->has_tt = 1;
954 ehci->sbrn = HCD_USB2;
955
956 retval = ehci_halt(ehci);
957 if (retval)
958 return retval;
959
960 /* data structure init */
961 retval = ehci_init(hcd);
962 if (retval)
963 return retval;
964
965 retval = ehci_reset(ehci);
966 if (retval)
967 return retval;
968
969 /* bursts of unspecified length. */
970 writel_relaxed(0, USB_AHBBURST);
971 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530972 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530973 /* Disable streaming mode and select host mode */
974 writel_relaxed(0x13, USB_USBMODE);
975
976 ehci_port_power(ehci, 1);
977 return 0;
978}
979
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530980#define RESET_RETRY_LIMIT 3
981#define RESET_SIGNAL_TIME_SOF_USEC (50 * 1000)
982#define RESET_SIGNAL_TIME_USEC (20 * 1000)
983static void ehci_hsic_reset_sof_bug_handler(struct usb_hcd *hcd, u32 val)
984{
985 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
986 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
987 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
988 u32 __iomem *status_reg = &ehci->regs->port_status[0];
Pavankumar Kondeti37493632013-03-05 09:43:22 +0530989 u32 cmd;
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530990 unsigned long flags;
991 int retries = 0, ret, cnt = RESET_SIGNAL_TIME_USEC;
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +0530992 s32 next_latency = 0;
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530993
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +0530994 if (pdata && pdata->swfi_latency) {
995 next_latency = pdata->swfi_latency + 1;
996 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
997 next_latency = PM_QOS_DEFAULT_VALUE;
998 }
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530999
1000 mehci->bus_reset = 1;
Pavankumar Kondeti37493632013-03-05 09:43:22 +05301001
1002 /* Halt the controller */
1003 cmd = ehci_readl(ehci, &ehci->regs->command);
1004 cmd &= ~CMD_RUN;
1005 ehci_writel(ehci, cmd, &ehci->regs->command);
1006 ret = handshake(ehci, &ehci->regs->status, STS_HALT,
1007 STS_HALT, 16 * 125);
1008 if (ret) {
1009 pr_err("halt handshake fatal error\n");
1010 dbg_log_event(NULL, "HALT: fatal", 0);
1011 goto fail;
1012 }
1013
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +05301014retry:
1015 retries++;
1016 dbg_log_event(NULL, "RESET: start", retries);
1017 pr_debug("reset begin %d\n", retries);
1018 mehci->reset_again = 0;
1019 spin_lock_irqsave(&ehci->lock, flags);
1020 ehci_writel(ehci, val, status_reg);
1021 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_USEC - 1),
1022 &mehci->timer->gptimer0_ld);
1023 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1024 &mehci->timer->gptimer0_ctrl);
1025 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1026 &ehci->regs->intr_enable);
1027
1028 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_SOF_USEC - 1),
1029 &mehci->timer->gptimer1_ld);
1030 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1031 &mehci->timer->gptimer1_ctrl);
1032
1033 spin_unlock_irqrestore(&ehci->lock, flags);
1034 wait_for_completion(&mehci->gpt0_completion);
1035
1036 if (!mehci->reset_again)
1037 goto done;
1038
1039 if (handshake(ehci, status_reg, PORT_RESET, 0, 10 * 1000)) {
1040 pr_err("reset handshake fatal error\n");
1041 dbg_log_event(NULL, "RESET: fatal", retries);
1042 goto fail;
1043 }
1044
1045 if (retries < RESET_RETRY_LIMIT)
1046 goto retry;
1047
1048 /* complete reset in tight loop */
1049 pr_info("RESET in tight loop\n");
1050 dbg_log_event(NULL, "RESET: tight", 0);
1051
1052 spin_lock_irqsave(&ehci->lock, flags);
1053 ehci_writel(ehci, val, status_reg);
1054 while (cnt--)
1055 udelay(1);
1056 ret = msm_hsic_reset_done(hcd);
1057 spin_unlock_irqrestore(&ehci->lock, flags);
1058 if (ret) {
1059 pr_err("RESET in tight loop failed\n");
1060 dbg_log_event(NULL, "RESET: tight failed", 0);
1061 goto fail;
1062 }
1063
1064done:
1065 dbg_log_event(NULL, "RESET: done", retries);
1066 pr_debug("reset completed\n");
1067fail:
1068 mehci->bus_reset = 0;
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301069 if (next_latency)
1070 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +05301071}
1072
Hemant Kumar45d211b2012-05-31 17:58:43 -07001073static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
1074{
Pavankumar Kondeti3c137392012-09-14 14:02:36 +05301075 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1076
1077 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
1078 dbg_log_event(NULL, "RH suspend attempt failed", 0);
1079 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
1080 __func__);
1081 return -EAGAIN;
1082 }
1083
Hemant Kumar45d211b2012-05-31 17:58:43 -07001084 dbg_log_event(NULL, "Suspend RH", 0);
1085 return ehci_bus_suspend(hcd);
1086}
1087
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001088static int msm_hsic_resume_thread(void *data)
1089{
1090 struct msm_hsic_hcd *mehci = data;
1091 struct usb_hcd *hcd = hsic_to_hcd(mehci);
1092 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1093 u32 temp;
1094 unsigned long resume_needed = 0;
1095 int retry_cnt = 0;
1096 int tight_resume = 0;
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301097 int tight_count = 0;
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301098 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301099 s32 next_latency = 0;
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001100
1101 dbg_log_event(NULL, "Resume RH", 0);
1102
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301103 if (pdata && pdata->swfi_latency) {
1104 next_latency = pdata->swfi_latency + 1;
1105 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
1106 next_latency = PM_QOS_DEFAULT_VALUE;
1107 }
1108
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001109 /* keep delay between bus states */
Pavankumar Kondetibed9ef72013-08-01 11:30:32 +05301110 if (time_before_eq(jiffies, ehci->next_statechange))
1111 usleep_range(10000, 10000);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001112
1113 spin_lock_irq(&ehci->lock);
1114 if (!HCD_HW_ACCESSIBLE(hcd)) {
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001115 mehci->resume_status = -ESHUTDOWN;
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301116 goto exit;
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001117 }
1118
1119 if (unlikely(ehci->debug)) {
1120 if (!dbgp_reset_prep())
1121 ehci->debug = NULL;
1122 else
1123 dbgp_external_startup();
1124 }
1125
1126 /* at least some APM implementations will try to deliver
1127 * IRQs right away, so delay them until we're ready.
1128 */
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301129 writel_relaxed(0, &ehci->regs->intr_enable);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001130
1131 /* re-init operational registers */
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301132 writel_relaxed(0, &ehci->regs->segment);
1133 writel_relaxed(ehci->periodic_dma, &ehci->regs->frame_list);
1134 writel_relaxed((u32) ehci->async->qh_dma, &ehci->regs->async_next);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001135
1136 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
1137 if (ehci->resume_sof_bug)
1138 ehci->command &= ~CMD_RUN;
1139
1140 /* restore CMD_RUN, framelist size, and irq threshold */
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301141 writel_relaxed(ehci->command, &ehci->regs->command);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001142
1143 /* manually resume the ports we suspended during bus_suspend() */
1144resume_again:
1145 if (retry_cnt >= RESUME_RETRY_LIMIT) {
1146 pr_info("retry count(%d) reached max, resume in tight loop\n",
1147 retry_cnt);
1148 tight_resume = 1;
1149 }
1150
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301151 temp = readl_relaxed(&ehci->regs->port_status[0]);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001152 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
1153 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
1154 temp |= PORT_RESUME;
1155 set_bit(0, &resume_needed);
1156 }
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301157 mehci->resume_start_t = ktime_get();
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001158 dbg_log_event(NULL, "FPR: Set", temp);
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301159 writel_relaxed(temp, &ehci->regs->port_status[0]);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001160
1161 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1162 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1163 * controller in MSM clears FPR bit after driving the resume signal for
1164 * 20ms. Workaround is to stop SOFs before driving resume and then start
1165 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1166 * completion otherwise peripheral may enter undefined state. As
1167 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1168 * to time the resume sequence. If driver exceeds allowable time SOFs,
1169 * repeat the resume process.
1170 */
1171 if (ehci->resume_sof_bug && resume_needed) {
1172 if (!tight_resume) {
1173 mehci->resume_again = 0;
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301174 writel_relaxed(GPT_LD(RESUME_SIGNAL_TIME_USEC - 1),
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001175 &mehci->timer->gptimer0_ld);
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301176 writel_relaxed(GPT_RESET | GPT_RUN,
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001177 &mehci->timer->gptimer0_ctrl);
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301178 writel_relaxed(INTR_MASK | STS_GPTIMER0_INTERRUPT,
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001179 &ehci->regs->intr_enable);
1180
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301181 writel_relaxed(GPT_LD(RESUME_SIGNAL_TIME_SOF_USEC - 1),
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001182 &mehci->timer->gptimer1_ld);
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301183 writel_relaxed(GPT_RESET | GPT_RUN,
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001184 &mehci->timer->gptimer1_ctrl);
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301185 dbg_log_event(NULL, "GPT timer prog done", 0);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001186
1187 spin_unlock_irq(&ehci->lock);
1188 wait_for_completion(&mehci->gpt0_completion);
1189 spin_lock_irq(&ehci->lock);
1190 } else {
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301191 dbg_log_event(NULL, "FPR: Tightloop", tight_count);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001192 /* do the resume in a tight loop */
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301193 mdelay(22);
1194 writel_relaxed(readl_relaxed(&ehci->regs->command) |
1195 CMD_RUN, &ehci->regs->command);
1196 if (ktime_us_delta(ktime_get(), mehci->resume_start_t) >
1197 RESUME_SIGNAL_TIME_SOF_USEC) {
1198 dbg_log_event(NULL, "FPR: Tightloop fail", 0);
1199 if (++tight_count > 3) {
1200 pr_err("HSIC resume failed\n");
1201 mehci->resume_status = -ENODEV;
1202 goto exit;
1203 }
1204 pr_err("FPR tight loop fail %d\n", tight_count);
1205 mehci->resume_again = 1;
1206 } else {
1207 dbg_log_event(NULL, "FPR: Tightloop done", 0);
1208 }
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001209 }
1210
1211 if (mehci->resume_again) {
1212 int temp;
1213
1214 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1215 pr_info("FPR: retry count: %d\n", retry_cnt);
1216 spin_unlock_irq(&ehci->lock);
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301217 temp = readl_relaxed(&ehci->regs->command);
1218 if (temp & CMD_RUN) {
1219 temp &= ~CMD_RUN;
1220 writel_relaxed(temp, &ehci->regs->command);
1221 dbg_log_event(NULL, "FPR: R/S cleared", 0);
1222 }
1223 temp = readl_relaxed(&ehci->regs->port_status[0]);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001224 temp &= ~PORT_RWC_BITS;
1225 temp |= PORT_SUSPEND;
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301226 writel_relaxed(temp, &ehci->regs->port_status[0]);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001227 /* Keep the bus idle for 5ms so that peripheral
1228 * can detect and initiate suspend
1229 */
1230 usleep_range(5000, 5000);
1231 dbg_log_event(NULL,
1232 "FPR: RResume",
1233 ehci_readl(ehci, &ehci->regs->port_status[0]));
1234 spin_lock_irq(&ehci->lock);
1235 mehci->resume_again = 0;
1236 retry_cnt++;
1237 goto resume_again;
1238 }
1239 }
1240
Pavankumar Kondeti95933142013-10-10 22:39:15 +05301241 ehci->command |= CMD_RUN;
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001242 dbg_log_event(NULL, "FPR: RT-Done", 0);
1243 mehci->resume_status = 1;
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301244exit:
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001245 spin_unlock_irq(&ehci->lock);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001246 complete(&mehci->rt_completion);
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301247 if (next_latency)
1248 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001249
1250 return 0;
1251}
1252
Hemant Kumar45d211b2012-05-31 17:58:43 -07001253static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1254{
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001255 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1256 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1257 u32 temp;
1258 struct task_struct *resume_thread = NULL;
1259
1260 mehci->resume_status = 0;
1261 resume_thread = kthread_run(msm_hsic_resume_thread,
1262 mehci, "hsic_resume_thread");
1263 if (IS_ERR(resume_thread)) {
1264 pr_err("Error creating resume thread:%lu\n",
1265 PTR_ERR(resume_thread));
1266 return PTR_ERR(resume_thread);
1267 }
1268
1269 wait_for_completion(&mehci->rt_completion);
1270
1271 if (mehci->resume_status < 0)
1272 return mehci->resume_status;
1273
1274 dbg_log_event(NULL, "FPR: Wokeup", 0);
1275 spin_lock_irq(&ehci->lock);
1276 (void) ehci_readl(ehci, &ehci->regs->command);
1277
1278 temp = 0;
1279 if (ehci->async->qh_next.qh)
1280 temp |= CMD_ASE;
1281 if (ehci->periodic_sched)
1282 temp |= CMD_PSE;
1283 if (temp) {
1284 ehci->command |= temp;
1285 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1286 }
1287
1288 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1289 hcd->state = HC_STATE_RUNNING;
1290 ehci->rh_state = EHCI_RH_RUNNING;
1291
1292 /* Now we can safely re-enable irqs */
1293 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1294
1295 spin_unlock_irq(&ehci->lock);
1296
1297 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001298}
1299
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301300static struct hc_driver msm_hsic_driver = {
1301 .description = hcd_name,
1302 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1303 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1304
1305 /*
1306 * generic hardware linkage
1307 */
1308 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001309 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301310
1311 .reset = ehci_hsic_reset,
1312 .start = ehci_run,
1313
1314 .stop = ehci_stop,
1315 .shutdown = ehci_shutdown,
1316
1317 /*
1318 * managing i/o requests and associated device resources
1319 */
Hemant Kumardf2d84d2012-08-15 09:06:35 -07001320 .urb_enqueue = ehci_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301321 .urb_dequeue = ehci_urb_dequeue,
1322 .endpoint_disable = ehci_endpoint_disable,
1323 .endpoint_reset = ehci_endpoint_reset,
1324 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1325
1326 /*
1327 * scheduling support
1328 */
1329 .get_frame_number = ehci_get_frame,
1330
1331 /*
1332 * root hub support
1333 */
1334 .hub_status_data = ehci_hub_status_data,
1335 .hub_control = ehci_hub_control,
1336 .relinquish_port = ehci_relinquish_port,
1337 .port_handed_over = ehci_port_handed_over,
1338
1339 /*
1340 * PM support
1341 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001342 .bus_suspend = ehci_hsic_bus_suspend,
1343 .bus_resume = ehci_hsic_bus_resume,
1344
Hemant Kumardf2d84d2012-08-15 09:06:35 -07001345 .log_urb = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001346 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001347
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +05301348 .reset_sof_bug_handler = ehci_hsic_reset_sof_bug_handler,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301349};
1350
1351static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1352{
1353 int ret = 0;
1354
1355 if (!init)
1356 goto put_clocks;
1357
Lena Salman8c8ba382012-02-14 15:59:31 +02001358 /*core_clk is required for LINK protocol engine
1359 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001360 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1361 if (IS_ERR(mehci->core_clk)) {
1362 dev_err(mehci->dev, "failed to get core_clk\n");
1363 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301364 return ret;
1365 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301366
Lena Salman8c8ba382012-02-14 15:59:31 +02001367 /* alt_core_clk is for LINK to be used during PHY RESET
1368 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001369 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
1370 if (IS_ERR(mehci->alt_core_clk)) {
1371 dev_err(mehci->dev, "failed to core_clk\n");
1372 ret = PTR_ERR(mehci->alt_core_clk);
1373 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301374 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301375
Lena Salman8c8ba382012-02-14 15:59:31 +02001376 /* phy_clk is required for HSIC PHY operation
1377 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001378 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1379 if (IS_ERR(mehci->phy_clk)) {
1380 dev_err(mehci->dev, "failed to get phy_clk\n");
1381 ret = PTR_ERR(mehci->phy_clk);
1382 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301383 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301384
1385 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001386 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301387 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001388 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301389 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001390 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301391 }
1392 clk_set_rate(mehci->cal_clk, 10000000);
1393
1394 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001395 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301396 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001397 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301398 ret = PTR_ERR(mehci->ahb_clk);
1399 goto put_cal_clk;
1400 }
1401
Manu Gautam28b1bac2012-01-30 16:43:06 +05301402 clk_prepare_enable(mehci->core_clk);
1403 clk_prepare_enable(mehci->phy_clk);
1404 clk_prepare_enable(mehci->cal_clk);
1405 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301406
1407 return 0;
1408
1409put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001410 if (!atomic_read(&mehci->in_lpm)) {
1411 clk_disable_unprepare(mehci->core_clk);
1412 clk_disable_unprepare(mehci->phy_clk);
1413 clk_disable_unprepare(mehci->cal_clk);
1414 clk_disable_unprepare(mehci->ahb_clk);
1415 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301416 clk_put(mehci->ahb_clk);
1417put_cal_clk:
1418 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001419put_phy_clk:
1420 clk_put(mehci->phy_clk);
1421put_alt_core_clk:
1422 clk_put(mehci->alt_core_clk);
1423put_core_clk:
1424 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301425
1426 return ret;
1427}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001428static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1429{
1430 struct msm_hsic_hcd *mehci = dev_id;
1431
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001432 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001433
1434 if (mehci)
1435 msm_hsic_config_gpios(mehci, 0);
1436
1437 return IRQ_HANDLED;
1438}
1439
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001440static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1441{
1442 struct msm_hsic_hcd *mehci = data;
Ajay Dudanid666daf2012-09-27 12:04:12 +05301443 int ret;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001444
Hemant Kumar6fd65032012-05-23 13:02:24 -07001445 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001446 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001447 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
1448 __func__, mehci->wakeup_int_cnt);
1449
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001450 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001451
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001452 spin_lock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001453 if (mehci->wakeup_irq_enabled) {
1454 mehci->wakeup_irq_enabled = 0;
1455 disable_irq_wake(irq);
1456 disable_irq_nosync(irq);
1457 }
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001458 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001459
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001460 if (!atomic_read(&mehci->pm_usage_cnt)) {
Ajay Dudanid666daf2012-09-27 12:04:12 +05301461 ret = pm_runtime_get(mehci->dev);
1462 /*
1463 * HSIC runtime resume can race with us.
1464 * if we are active (ret == 1) or resuming
1465 * (ret == -EINPROGRESS), decrement the
1466 * PM usage counter before returning.
1467 */
1468 if ((ret == 1) || (ret == -EINPROGRESS))
1469 pm_runtime_put_noidle(mehci->dev);
1470 else
1471 atomic_set(&mehci->pm_usage_cnt, 1);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001472 }
1473
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001474 return IRQ_HANDLED;
1475}
1476
Hemant Kumare6275972012-02-29 20:06:21 -08001477static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1478{
1479 if (debug_bus_voting_enabled)
1480 seq_printf(s, "enabled\n");
1481 else
1482 seq_printf(s, "disabled\n");
1483
1484 return 0;
1485}
1486
1487static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1488{
1489 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1490}
1491
1492static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1493 const char __user *ubuf, size_t count, loff_t *ppos)
1494{
1495 char buf[8];
1496 int ret;
1497 struct seq_file *s = file->private_data;
1498 struct msm_hsic_hcd *mehci = s->private;
1499
1500 memset(buf, 0x00, sizeof(buf));
1501
1502 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1503 return -EFAULT;
1504
1505 if (!strncmp(buf, "enable", 6)) {
1506 /* Do not vote here. Let hsic driver decide when to vote */
1507 debug_bus_voting_enabled = true;
1508 } else {
1509 debug_bus_voting_enabled = false;
1510 if (mehci->bus_perf_client) {
1511 ret = msm_bus_scale_client_update_request(
1512 mehci->bus_perf_client, 0);
1513 if (ret)
1514 dev_err(mehci->dev, "%s: Failed to devote "
1515 "for bus bw %d\n", __func__, ret);
1516 }
1517 }
1518
1519 return count;
1520}
1521
1522const struct file_operations ehci_hsic_msm_bus_fops = {
1523 .open = ehci_hsic_msm_bus_open,
1524 .read = seq_read,
1525 .write = ehci_hsic_msm_bus_write,
1526 .llseek = seq_lseek,
1527 .release = single_release,
1528};
1529
Hemant Kumar6fd65032012-05-23 13:02:24 -07001530static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1531{
1532 struct msm_hsic_hcd *mehci = s->private;
1533
1534 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1535
1536 return 0;
1537}
1538
1539static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1540{
1541 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1542}
1543
1544const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1545 .open = ehci_hsic_msm_wakeup_cnt_open,
1546 .read = seq_read,
1547 .llseek = seq_lseek,
1548 .release = single_release,
1549};
1550
Hemant Kumar45d211b2012-05-31 17:58:43 -07001551static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1552{
1553 unsigned long flags;
1554 unsigned i;
1555
1556 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1557
1558 i = dbg_hsic_data.idx;
1559 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1560 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1561 continue;
1562 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1563 }
1564
1565 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1566
1567 return 0;
1568}
1569
1570static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1571{
1572 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1573}
1574
1575const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1576 .open = ehci_hsic_msm_data_events_open,
1577 .read = seq_read,
1578 .llseek = seq_lseek,
1579 .release = single_release,
1580};
1581
1582static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1583{
1584 unsigned long flags;
1585 unsigned i;
1586
1587 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1588
1589 i = dbg_hsic_ctrl.idx;
1590 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1591 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1592 continue;
1593 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1594 }
1595
1596 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1597
1598 return 0;
1599}
1600
1601static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1602{
1603 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1604}
1605
1606const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1607 .open = ehci_hsic_msm_ctrl_events_open,
1608 .read = seq_read,
1609 .llseek = seq_lseek,
1610 .release = single_release,
1611};
1612
Hemant Kumare6275972012-02-29 20:06:21 -08001613static struct dentry *ehci_hsic_msm_dbg_root;
1614static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1615{
1616 struct dentry *ehci_hsic_msm_dentry;
1617
1618 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1619
1620 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1621 return -ENODEV;
1622
1623 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1624 S_IRUGO | S_IWUSR,
1625 ehci_hsic_msm_dbg_root, mehci,
1626 &ehci_hsic_msm_bus_fops);
1627
1628 if (!ehci_hsic_msm_dentry) {
1629 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1630 return -ENODEV;
1631 }
1632
Hemant Kumar6fd65032012-05-23 13:02:24 -07001633 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1634 S_IRUGO,
1635 ehci_hsic_msm_dbg_root, mehci,
1636 &ehci_hsic_msm_wakeup_cnt_fops);
1637
1638 if (!ehci_hsic_msm_dentry) {
1639 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1640 return -ENODEV;
1641 }
1642
Hemant Kumar45d211b2012-05-31 17:58:43 -07001643 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1644 S_IRUGO,
1645 ehci_hsic_msm_dbg_root, mehci,
1646 &ehci_hsic_msm_dbg_ctrl_fops);
1647
1648 if (!ehci_hsic_msm_dentry) {
1649 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1650 return -ENODEV;
1651 }
1652
1653 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1654 S_IRUGO,
1655 ehci_hsic_msm_dbg_root, mehci,
1656 &ehci_hsic_msm_dbg_data_fops);
1657
1658 if (!ehci_hsic_msm_dentry) {
1659 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1660 return -ENODEV;
1661 }
1662
Hemant Kumare6275972012-02-29 20:06:21 -08001663 return 0;
1664}
1665
1666static void ehci_hsic_msm_debugfs_cleanup(void)
1667{
1668 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1669}
1670
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301671static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1672{
1673 struct usb_hcd *hcd;
1674 struct resource *res;
1675 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301676 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301677 int ret;
1678
1679 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1680
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301681 /* After parent device's probe is executed, it will be put in suspend
1682 * mode. When child device's probe is called, driver core is not
1683 * resuming parent device due to which parent will be in suspend even
1684 * though child is active. Hence resume the parent device explicitly.
1685 */
1686 if (pdev->dev.parent)
1687 pm_runtime_get_sync(pdev->dev.parent);
1688
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301689 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1690 dev_name(&pdev->dev));
1691 if (!hcd) {
1692 dev_err(&pdev->dev, "Unable to create HCD\n");
1693 return -ENOMEM;
1694 }
1695
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301696 hcd_to_bus(hcd)->skip_resume = true;
1697
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301698 hcd->irq = platform_get_irq(pdev, 0);
1699 if (hcd->irq < 0) {
1700 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1701 ret = hcd->irq;
1702 goto put_hcd;
1703 }
1704
1705 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1706 if (!res) {
1707 dev_err(&pdev->dev, "Unable to get memory resource\n");
1708 ret = -ENODEV;
1709 goto put_hcd;
1710 }
1711
1712 hcd->rsrc_start = res->start;
1713 hcd->rsrc_len = resource_size(res);
1714 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1715 if (!hcd->regs) {
1716 dev_err(&pdev->dev, "ioremap failed\n");
1717 ret = -ENOMEM;
1718 goto put_hcd;
1719 }
1720
1721 mehci = hcd_to_hsic(hcd);
1722 mehci->dev = &pdev->dev;
Ajay Dudanic4e40db2012-08-20 14:44:40 -07001723 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301724
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001725 spin_lock_init(&mehci->wakeup_lock);
1726
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001727 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001728 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001729
Hemant Kumare4040492012-06-21 17:35:42 -07001730 mehci->ehci.resume_sof_bug = 1;
1731
Ajay Dudanic4e40db2012-08-20 14:44:40 -07001732 if (pdata)
1733 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Hemant Kumar933e0402012-05-22 11:11:40 -07001734
Vamsi Krishna34f01582011-12-14 19:54:42 -08001735 res = platform_get_resource_byname(pdev,
1736 IORESOURCE_IRQ,
1737 "peripheral_status_irq");
1738 if (res)
1739 mehci->peripheral_status_irq = res->start;
1740
Hemant Kumar6fd65032012-05-23 13:02:24 -07001741 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
1742 if (res) {
1743 mehci->wakeup_gpio = res->start;
1744 mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
1745 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1746 }
1747
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301748 ret = msm_hsic_init_clocks(mehci, 1);
1749 if (ret) {
1750 dev_err(&pdev->dev, "unable to initialize clocks\n");
1751 ret = -ENODEV;
1752 goto unmap;
1753 }
1754
1755 ret = msm_hsic_init_vddcx(mehci, 1);
1756 if (ret) {
1757 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1758 ret = -ENODEV;
1759 goto deinit_clocks;
1760 }
1761
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001762 init_completion(&mehci->rt_completion);
1763 init_completion(&mehci->gpt0_completion);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301764 ret = msm_hsic_reset(mehci);
1765 if (ret) {
1766 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301767 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301768 }
1769
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001770 ehci_wq = create_singlethread_workqueue("ehci_wq");
1771 if (!ehci_wq) {
1772 dev_err(&pdev->dev, "unable to create workqueue\n");
1773 ret = -ENOMEM;
1774 goto deinit_vddcx;
1775 }
1776
1777 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1778
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301779 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1780 if (ret) {
1781 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301782 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301783 }
1784
1785 device_init_wakeup(&pdev->dev, 1);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001786 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1787 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001788
1789 if (mehci->peripheral_status_irq) {
1790 ret = request_threaded_irq(mehci->peripheral_status_irq,
1791 NULL, hsic_peripheral_status_change,
1792 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1793 | IRQF_SHARED,
1794 "hsic_peripheral_status", mehci);
1795 if (ret)
1796 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1797 __func__, mehci->peripheral_status_irq, ret);
1798 }
1799
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001800 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001801 if (mehci->wakeup_irq) {
Hemant Kumar5e386632012-08-30 14:23:38 -07001802 /* In case if wakeup gpio is pulled high at this point
1803 * remote wakeup interrupt fires right after request_irq.
1804 * Remote wake up interrupt only needs to be enabled when
1805 * HSIC bus goes to suspend.
1806 */
1807 irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001808 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001809 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001810 "msm_hsic_wakeup", mehci);
Hemant Kumar5e386632012-08-30 14:23:38 -07001811 if (ret) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001812 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1813 mehci->wakeup_irq, ret);
1814 mehci->wakeup_irq = 0;
1815 }
1816 }
1817
Hemant Kumare6275972012-02-29 20:06:21 -08001818 ret = ehci_hsic_msm_debugfs_init(mehci);
1819 if (ret)
1820 dev_dbg(&pdev->dev, "mode debugfs file is"
1821 "not available\n");
1822
1823 if (pdata && pdata->bus_scale_table) {
1824 mehci->bus_perf_client =
1825 msm_bus_scale_register_client(pdata->bus_scale_table);
1826 /* Configure BUS performance parameters for MAX bandwidth */
1827 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001828 mehci->bus_vote = true;
1829 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001830 } else {
1831 dev_err(&pdev->dev, "%s: Failed to register BUS "
1832 "scaling client!!\n", __func__);
1833 }
1834 }
1835
Hemant Kumar105d07f2012-07-02 15:33:07 -07001836 __mehci = mehci;
1837
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301838 if (pdata && pdata->swfi_latency)
1839 pm_qos_add_request(&mehci->pm_qos_req_dma,
1840 PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
1841
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301842 /*
1843 * This pdev->dev is assigned parent of root-hub by USB core,
1844 * hence, runtime framework automatically calls this driver's
1845 * runtime APIs based on root-hub's state.
1846 */
1847 pm_runtime_set_active(&pdev->dev);
1848 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301849 /* Decrement the parent device's counter after probe.
1850 * As child is active, parent will not be put into
1851 * suspend mode.
1852 */
1853 if (pdev->dev.parent)
1854 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301855
1856 return 0;
1857
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301858unconfig_gpio:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001859 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301860 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301861deinit_vddcx:
1862 msm_hsic_init_vddcx(mehci, 0);
1863deinit_clocks:
1864 msm_hsic_init_clocks(mehci, 0);
1865unmap:
1866 iounmap(hcd->regs);
1867put_hcd:
1868 usb_put_hcd(hcd);
1869
1870 return ret;
1871}
1872
1873static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1874{
1875 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1876 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301877 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1878
Ido Shayevitzbd47c832013-02-20 18:55:59 +02001879 /* If the device was removed no need to call pm_runtime_disable */
1880 if (pdev->dev.power.power_state.event != PM_EVENT_INVALID)
1881 pm_runtime_disable(&pdev->dev);
1882
1883 pm_runtime_set_suspended(&pdev->dev);
1884
Pavankumar Kondetifff3f2e2013-02-12 21:43:56 +05301885 /* Remove the HCD prior to releasing our resources. */
1886 usb_remove_hcd(hcd);
1887
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301888 if (pdata && pdata->swfi_latency)
1889 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301890
Vamsi Krishna34f01582011-12-14 19:54:42 -08001891 if (mehci->peripheral_status_irq)
1892 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001893
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001894 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001895 if (mehci->wakeup_irq_enabled)
1896 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001897 free_irq(mehci->wakeup_irq, mehci);
1898 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001899
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001900 /*
1901 * If the update request is called after unregister, the request will
1902 * fail. Results are undefined if unregister is called in the middle of
1903 * update request.
1904 */
1905 mehci->bus_vote = false;
1906 cancel_work_sync(&mehci->bus_vote_w);
1907
Hemant Kumare6275972012-02-29 20:06:21 -08001908 if (mehci->bus_perf_client)
1909 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1910
1911 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301912 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301913
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001914 destroy_workqueue(ehci_wq);
1915
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301916 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301917 msm_hsic_init_vddcx(mehci, 0);
1918
1919 msm_hsic_init_clocks(mehci, 0);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001920 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301921 iounmap(hcd->regs);
1922 usb_put_hcd(hcd);
1923
1924 return 0;
1925}
1926
1927#ifdef CONFIG_PM_SLEEP
1928static int msm_hsic_pm_suspend(struct device *dev)
1929{
1930 struct usb_hcd *hcd = dev_get_drvdata(dev);
1931 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1932
1933 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1934
Hemant Kumar45d211b2012-05-31 17:58:43 -07001935 dbg_log_event(NULL, "PM Suspend", 0);
1936
Pavankumar Kondetife319632013-04-25 13:51:24 +05301937 if (!atomic_read(&mehci->in_lpm)) {
1938 dev_info(dev, "abort suspend\n");
1939 dbg_log_event(NULL, "PM Suspend abort", 0);
1940 return -EBUSY;
1941 }
1942
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301943 if (device_may_wakeup(dev))
1944 enable_irq_wake(hcd->irq);
1945
Pavankumar Kondetife319632013-04-25 13:51:24 +05301946 return 0;
Jack Phamfe441ea2012-03-23 17:03:15 -07001947}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301948
Jack Pham16b06f82012-08-14 20:03:59 -07001949static int msm_hsic_pm_suspend_noirq(struct device *dev)
1950{
1951 struct usb_hcd *hcd = dev_get_drvdata(dev);
1952 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1953
Pavankumar Kondetibbd05822013-01-28 17:04:39 +05301954 if (atomic_read(&mehci->async_int)) {
Jack Pham16b06f82012-08-14 20:03:59 -07001955 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
1956 return -EBUSY;
1957 }
1958
1959 return 0;
1960}
1961
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301962static int msm_hsic_pm_resume(struct device *dev)
1963{
1964 int ret;
1965 struct usb_hcd *hcd = dev_get_drvdata(dev);
1966 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1967
Jack Pham16b06f82012-08-14 20:03:59 -07001968 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001969 dbg_log_event(NULL, "PM Resume", 0);
1970
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301971 if (device_may_wakeup(dev))
1972 disable_irq_wake(hcd->irq);
1973
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301974 /*
1975 * Keep HSIC in Low Power Mode if system is resumed
1976 * by any other wakeup source. HSIC is resumed later
1977 * when remote wakeup is received or interface driver
1978 * start I/O.
1979 */
Pavankumar Kondeti98089c02012-11-09 10:54:00 +05301980 if (!atomic_read(&mehci->pm_usage_cnt) &&
Pavankumar Kondetibbd05822013-01-28 17:04:39 +05301981 !atomic_read(&mehci->async_int) &&
Pavankumar Kondeti98089c02012-11-09 10:54:00 +05301982 pm_runtime_suspended(dev))
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301983 return 0;
1984
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301985 ret = msm_hsic_resume(mehci);
1986 if (ret)
1987 return ret;
1988
1989 /* Bring the device to full powered state upon system resume */
1990 pm_runtime_disable(dev);
1991 pm_runtime_set_active(dev);
1992 pm_runtime_enable(dev);
1993
1994 return 0;
1995}
1996#endif
1997
1998#ifdef CONFIG_PM_RUNTIME
1999static int msm_hsic_runtime_idle(struct device *dev)
2000{
2001 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302002 return 0;
2003}
2004
2005static int msm_hsic_runtime_suspend(struct device *dev)
2006{
2007 struct usb_hcd *hcd = dev_get_drvdata(dev);
2008 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2009
2010 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002011
2012 dbg_log_event(NULL, "Run Time PM Suspend", 0);
2013
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302014 return msm_hsic_suspend(mehci);
2015}
2016
2017static int msm_hsic_runtime_resume(struct device *dev)
2018{
2019 struct usb_hcd *hcd = dev_get_drvdata(dev);
2020 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
2021
2022 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07002023
2024 dbg_log_event(NULL, "Run Time PM Resume", 0);
2025
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302026 return msm_hsic_resume(mehci);
2027}
2028#endif
2029
2030#ifdef CONFIG_PM
2031static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
2032 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07002033 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05302034 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
2035 msm_hsic_runtime_idle)
2036};
2037#endif
2038
2039static struct platform_driver ehci_msm_hsic_driver = {
2040 .probe = ehci_hsic_msm_probe,
2041 .remove = __devexit_p(ehci_hsic_msm_remove),
2042 .driver = {
2043 .name = "msm_hsic_host",
2044#ifdef CONFIG_PM
2045 .pm = &msm_hsic_dev_pm_ops,
2046#endif
2047 },
2048};