blob: 7f2e0a8421872ce1b8e3442342cf17dea83dfcb2 [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>
Amit Blayd6ea6102012-06-07 16:26:24 +030042
43#include <mach/msm_bus.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053044#include <mach/clk.h>
45#include <mach/msm_iomap.h>
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +053046#include <mach/msm_xo.h>
Vamsi Krishna34f01582011-12-14 19:54:42 -080047#include <linux/spinlock.h>
Hemant Kumar45d211b2012-05-31 17:58:43 -070048#include <linux/cpu.h>
Amit Blayd6ea6102012-06-07 16:26:24 +030049#include <mach/rpm-regulator.h>
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053050
51#define MSM_USB_BASE (hcd->regs)
Hemant Kumar105d07f2012-07-02 15:33:07 -070052#define USB_REG_START_OFFSET 0x90
53#define USB_REG_END_OFFSET 0x250
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053054
Hemant Kumar2309eaa2012-08-14 16:46:42 -070055static struct workqueue_struct *ehci_wq;
Ajay Dudani11ab1d52012-08-17 17:12:26 -070056struct ehci_timer {
57#define GPT_LD(p) ((p) & 0x00FFFFFF)
58 u32 gptimer0_ld;
59#define GPT_RUN BIT(31)
60#define GPT_RESET BIT(30)
61#define GPT_MODE BIT(24)
62#define GPT_CNT(p) ((p) & 0x00FFFFFF)
63 u32 gptimer0_ctrl;
64
65 u32 gptimer1_ld;
66 u32 gptimer1_ctrl;
67};
Hemant Kumar2309eaa2012-08-14 16:46:42 -070068
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053069struct msm_hsic_hcd {
70 struct ehci_hcd ehci;
Hemant Kumar4cd49e12012-09-06 19:57:14 -070071 spinlock_t wakeup_lock;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053072 struct device *dev;
73 struct clk *ahb_clk;
Manu Gautam5143b252012-01-05 19:25:23 -080074 struct clk *core_clk;
75 struct clk *alt_core_clk;
76 struct clk *phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053077 struct clk *cal_clk;
78 struct regulator *hsic_vddcx;
Pavankumar Kondetibbd05822013-01-28 17:04:39 +053079 atomic_t async_int;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +053080 atomic_t in_lpm;
Ajay Dudaniab3bf192012-08-28 09:58:04 -070081 struct wake_lock wlock;
Vamsi Krishna34f01582011-12-14 19:54:42 -080082 int peripheral_status_irq;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -080083 int wakeup_irq;
Hemant Kumar6fd65032012-05-23 13:02:24 -070084 int wakeup_gpio;
Jack Phamfe441ea2012-03-23 17:03:15 -070085 bool wakeup_irq_enabled;
Ajay Dudaniab3bf192012-08-28 09:58:04 -070086 atomic_t pm_usage_cnt;
Hemant Kumare6275972012-02-29 20:06:21 -080087 uint32_t bus_perf_client;
Hemant Kumar6fd65032012-05-23 13:02:24 -070088 uint32_t wakeup_int_cnt;
Amit Blayd6ea6102012-06-07 16:26:24 +030089 enum usb_vdd_type vdd_type;
Hemant Kumar2309eaa2012-08-14 16:46:42 -070090
91 struct work_struct bus_vote_w;
92 bool bus_vote;
Ajay Dudani11ab1d52012-08-17 17:12:26 -070093
94 /* gp timer */
95 struct ehci_timer __iomem *timer;
96 struct completion gpt0_completion;
97 struct completion rt_completion;
98 int resume_status;
99 int resume_again;
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530100 int bus_reset;
101 int reset_again;
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +0530102
103 struct pm_qos_request pm_qos_req_dma;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530104};
105
Hemant Kumar105d07f2012-07-02 15:33:07 -0700106struct msm_hsic_hcd *__mehci;
107
Hemant Kumare6275972012-02-29 20:06:21 -0800108static bool debug_bus_voting_enabled = true;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700109
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700110static unsigned int enable_payload_log = 1;
111module_param(enable_payload_log, uint, S_IRUGO | S_IWUSR);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700112static unsigned int enable_dbg_log = 1;
113module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
114/*by default log ep0 and efs sync ep*/
115static unsigned int ep_addr_rxdbg_mask = 9;
116module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
117static unsigned int ep_addr_txdbg_mask = 9;
118module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
119
120/* Maximum debug message length */
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700121#define DBG_MSG_LEN 128UL
Hemant Kumar45d211b2012-05-31 17:58:43 -0700122
123/* Maximum number of messages */
124#define DBG_MAX_MSG 256UL
125
126#define TIME_BUF_LEN 20
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700127#define HEX_DUMP_LEN 72
Hemant Kumar45d211b2012-05-31 17:58:43 -0700128
129enum event_type {
130 EVENT_UNDEF = -1,
131 URB_SUBMIT,
132 URB_COMPLETE,
133 EVENT_NONE,
134};
135
136#define EVENT_STR_LEN 5
137
Hemant Kumar45d211b2012-05-31 17:58:43 -0700138static enum event_type str_to_event(const char *name)
139{
140 if (!strncasecmp("S", name, EVENT_STR_LEN))
141 return URB_SUBMIT;
142 if (!strncasecmp("C", name, EVENT_STR_LEN))
143 return URB_COMPLETE;
144 if (!strncasecmp("", name, EVENT_STR_LEN))
145 return EVENT_NONE;
146
147 return EVENT_UNDEF;
148}
149
150/*log ep0 activity*/
151static struct {
152 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
153 unsigned idx; /* index */
154 rwlock_t lck; /* lock */
155} dbg_hsic_ctrl = {
156 .idx = 0,
157 .lck = __RW_LOCK_UNLOCKED(lck)
158};
159
160static struct {
161 char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
162 unsigned idx; /* index */
163 rwlock_t lck; /* lock */
164} dbg_hsic_data = {
165 .idx = 0,
166 .lck = __RW_LOCK_UNLOCKED(lck)
167};
168
169/**
170 * dbg_inc: increments debug event index
171 * @idx: buffer index
172 */
173static void dbg_inc(unsigned *idx)
174{
175 *idx = (*idx + 1) & (DBG_MAX_MSG-1);
176}
177
178/*get_timestamp - returns time of day in us */
179static char *get_timestamp(char *tbuf)
180{
181 unsigned long long t;
182 unsigned long nanosec_rem;
183
184 t = cpu_clock(smp_processor_id());
185 nanosec_rem = do_div(t, 1000000000)/1000;
186 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
187 nanosec_rem);
188 return tbuf;
189}
190
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530191static int allow_dbg_log(struct urb *urb, int ep_addr)
Hemant Kumar45d211b2012-05-31 17:58:43 -0700192{
193 int dir, num;
194
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530195 dir = usb_urb_dir_in(urb) ? USB_DIR_IN : USB_DIR_OUT;
Hemant Kumar45d211b2012-05-31 17:58:43 -0700196 num = ep_addr & ~USB_DIR_IN;
197 num = 1 << num;
198
199 if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
200 return 1;
201 if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
202 return 1;
203
204 return 0;
205}
206
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530207static char *
208get_hex_data(char *dbuf, struct urb *urb, int event, int status, size_t max_len)
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700209{
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700210 char *ubuf = urb->transfer_buffer;
211 size_t len = event ? \
212 urb->actual_length : urb->transfer_buffer_length;
213
214 if (status == -EINPROGRESS)
215 status = 0;
216
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530217 /*Only dump ep in successful completions and epout submissions*/
218 if (len && !status && ((usb_urb_dir_in(urb) && event) ||
219 (usb_urb_dir_out(urb) && !event))) {
220 if (len >= max_len)
221 len = max_len;
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700222 hex_dump_to_buffer(ubuf, len, 32, 4, dbuf, HEX_DUMP_LEN, 0);
223 } else {
224 dbuf = "";
225 }
226
227 return dbuf;
228}
229
Hemant Kumar45d211b2012-05-31 17:58:43 -0700230static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
231{
232 unsigned long flags;
233 int ep_addr;
234 char tbuf[TIME_BUF_LEN];
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700235 char dbuf[HEX_DUMP_LEN];
Hemant Kumar45d211b2012-05-31 17:58:43 -0700236
237 if (!enable_dbg_log)
238 return;
239
240 if (!urb) {
241 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
242 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700243 "%s: %s : %u", get_timestamp(tbuf), event, extra);
Hemant Kumar45d211b2012-05-31 17:58:43 -0700244 dbg_inc(&dbg_hsic_ctrl.idx);
245 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
246 return;
247 }
248
249 ep_addr = urb->ep->desc.bEndpointAddress;
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530250 if (!allow_dbg_log(urb, ep_addr))
Hemant Kumar45d211b2012-05-31 17:58:43 -0700251 return;
252
253 if ((ep_addr & 0x0f) == 0x0) {
254 /*submit event*/
255 if (!str_to_event(event)) {
256 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
257 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
258 DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530259 "%02x %02x %04x %04x %04x %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700260 get_timestamp(tbuf), event, urb,
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530261 usb_urb_dir_in(urb) ? "in" : "out",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700262 urb->setup_packet[0], urb->setup_packet[1],
263 (urb->setup_packet[3] << 8) |
264 urb->setup_packet[2],
265 (urb->setup_packet[5] << 8) |
266 urb->setup_packet[4],
267 (urb->setup_packet[7] << 8) |
268 urb->setup_packet[6],
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530269 urb->transfer_buffer_length, extra,
270 enable_payload_log ? get_hex_data(dbuf, urb,
271 str_to_event(event), extra, 16) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700272
273 dbg_inc(&dbg_hsic_ctrl.idx);
274 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
275 } else {
276 write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
277 scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530278 DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700279 get_timestamp(tbuf), event, urb,
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530280 usb_urb_dir_in(urb) ? "in" : "out",
281 urb->actual_length, extra,
282 enable_payload_log ? get_hex_data(dbuf, urb,
283 str_to_event(event), extra, 16) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700284
285 dbg_inc(&dbg_hsic_ctrl.idx);
286 write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
287 }
288 } else {
289 write_lock_irqsave(&dbg_hsic_data.lck, flags);
290 scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700291 "%s: [%s : %p]:ep%d[%s] %u %d %s",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700292 get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530293 usb_urb_dir_in(urb) ? "in" : "out",
Hemant Kumar45d211b2012-05-31 17:58:43 -0700294 str_to_event(event) ? urb->actual_length :
Hemant Kumardf2d84d2012-08-15 09:06:35 -0700295 urb->transfer_buffer_length, extra,
296 enable_payload_log ? get_hex_data(dbuf, urb,
Pavankumar Kondetia2953ed2013-03-22 15:26:50 +0530297 str_to_event(event), extra, 32) : "");
Hemant Kumar45d211b2012-05-31 17:58:43 -0700298
299 dbg_inc(&dbg_hsic_data.idx);
300 write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
301 }
302}
303
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530304static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
305{
306 return (struct msm_hsic_hcd *) (hcd->hcd_priv);
307}
308
309static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
310{
311 return container_of((void *) mehci, struct usb_hcd, hcd_priv);
312}
313
Hemant Kumar105d07f2012-07-02 15:33:07 -0700314static void dump_hsic_regs(struct usb_hcd *hcd)
315{
316 int i;
317 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
318
319 if (atomic_read(&mehci->in_lpm))
320 return;
321
322 for (i = USB_REG_START_OFFSET; i <= USB_REG_END_OFFSET; i += 0x10)
323 pr_info("%p: %08x\t%08x\t%08x\t%08x\n", hcd->regs + i,
324 readl_relaxed(hcd->regs + i),
325 readl_relaxed(hcd->regs + i + 4),
326 readl_relaxed(hcd->regs + i + 8),
327 readl_relaxed(hcd->regs + i + 0xc));
328}
329
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530330#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
331
Amit Blayd6ea6102012-06-07 16:26:24 +0300332#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Hemant Kumar266d9d52012-10-17 13:48:10 -0700333#define USB_PHY_VDD_DIG_VOL_MIN 945000 /* uV */
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700334#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530335
Lena Salman8c8ba382012-02-14 15:59:31 +0200336#define HSIC_DBG1_REG 0x38
337
Amit Blayd6ea6102012-06-07 16:26:24 +0300338static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
339 { /* VDD_CX CORNER Voting */
340 [VDD_NONE] = RPM_VREG_CORNER_NONE,
341 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
342 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
343 },
344 { /* VDD_CX Voltage Voting */
345 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
346 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
347 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
348 },
349};
350
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530351static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
352{
353 int ret = 0;
Amit Blayd6ea6102012-06-07 16:26:24 +0300354 int none_vol, min_vol, max_vol;
355
356 if (!mehci->hsic_vddcx) {
357 mehci->vdd_type = VDDCX_CORNER;
358 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
359 "hsic_vdd_dig");
360 if (IS_ERR(mehci->hsic_vddcx)) {
361 mehci->hsic_vddcx = devm_regulator_get(mehci->dev,
362 "HSIC_VDDCX");
363 if (IS_ERR(mehci->hsic_vddcx)) {
364 dev_err(mehci->dev, "unable to get hsic vddcx\n");
365 return PTR_ERR(mehci->hsic_vddcx);
366 }
367 mehci->vdd_type = VDDCX;
368 }
369 }
370
371 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
372 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
373 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530374
375 if (!init)
376 goto disable_reg;
377
Amit Blayd6ea6102012-06-07 16:26:24 +0300378 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530379 if (ret) {
380 dev_err(mehci->dev, "unable to set the voltage"
381 "for hsic vddcx\n");
Mayank Rana189ac052012-03-24 04:35:02 +0530382 return ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530383 }
384
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530385 ret = regulator_enable(mehci->hsic_vddcx);
386 if (ret) {
387 dev_err(mehci->dev, "unable to enable hsic vddcx\n");
388 goto reg_enable_err;
389 }
390
391 return 0;
392
393disable_reg:
394 regulator_disable(mehci->hsic_vddcx);
395reg_enable_err:
Amit Blayd6ea6102012-06-07 16:26:24 +0300396 regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
397
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530398 return ret;
399
400}
401
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530402static int __maybe_unused ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700403{
404 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Devin Kim01e5a5b2012-08-30 02:52:45 -0700405 int cnt = 0;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700406
407 /* initiate read operation */
408 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
409 USB_ULPI_VIEWPORT);
410
411 /* wait for completion */
Devin Kim01e5a5b2012-08-30 02:52:45 -0700412 while (cnt < ULPI_IO_TIMEOUT_USEC) {
413 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
414 break;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700415 udelay(1);
Devin Kim01e5a5b2012-08-30 02:52:45 -0700416 cnt++;
417 }
418
419 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
420 dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
421 readl_relaxed(USB_ULPI_VIEWPORT));
422 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
423 readl_relaxed(USB_PORTSC),
424 readl_relaxed(USB_USBCMD),
425 readl_relaxed(USB_FRINDEX));
426
427 /*frame counter increments afte 125us*/
428 udelay(130);
429 dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
430 readl_relaxed(USB_FRINDEX));
431 return -ETIMEDOUT;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -0700432 }
433
434 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
435}
436
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530437static int ulpi_write(struct msm_hsic_hcd *mehci, u32 val, u32 reg)
438{
439 struct usb_hcd *hcd = hsic_to_hcd(mehci);
440 int cnt = 0;
441
442 /* initiate write operation */
443 writel_relaxed(ULPI_RUN | ULPI_WRITE |
444 ULPI_ADDR(reg) | ULPI_DATA(val),
445 USB_ULPI_VIEWPORT);
446
447 /* wait for completion */
448 while (cnt < ULPI_IO_TIMEOUT_USEC) {
449 if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
450 break;
451 udelay(1);
452 cnt++;
453 }
454
455 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
Devin Kim01e5a5b2012-08-30 02:52:45 -0700456 dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
457 readl_relaxed(USB_ULPI_VIEWPORT));
458 dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
459 readl_relaxed(USB_PORTSC),
460 readl_relaxed(USB_USBCMD),
461 readl_relaxed(USB_FRINDEX));
462
463 /*frame counter increments afte 125us*/
464 udelay(130);
465 dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
466 readl_relaxed(USB_FRINDEX));
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530467 return -ETIMEDOUT;
468 }
469
470 return 0;
471}
472
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530473static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
474{
475 int rc = 0;
476 struct msm_hsic_host_platform_data *pdata;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800477 static int gpio_status;
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530478
479 pdata = mehci->dev->platform_data;
Vamsi Krishna34f01582011-12-14 19:54:42 -0800480
Lena Salman8c8ba382012-02-14 15:59:31 +0200481 if (!pdata || !pdata->strobe || !pdata->data)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530482 return rc;
483
Vamsi Krishna34f01582011-12-14 19:54:42 -0800484 if (gpio_status == gpio_en)
485 return 0;
486
487 gpio_status = gpio_en;
488
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530489 if (!gpio_en)
490 goto free_gpio;
491
492 rc = gpio_request(pdata->strobe, "HSIC_STROBE_GPIO");
493 if (rc < 0) {
494 dev_err(mehci->dev, "gpio request failed for HSIC STROBE\n");
495 return rc;
496 }
497
498 rc = gpio_request(pdata->data, "HSIC_DATA_GPIO");
499 if (rc < 0) {
500 dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
501 goto free_strobe;
502 }
503
Hemant Kumar6fd65032012-05-23 13:02:24 -0700504 if (mehci->wakeup_gpio) {
505 rc = gpio_request(mehci->wakeup_gpio, "HSIC_WAKEUP_GPIO");
506 if (rc < 0) {
507 dev_err(mehci->dev, "gpio request failed for HSIC WAKEUP\n");
508 goto free_data;
509 }
510 }
511
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530512 return 0;
513
514free_gpio:
Hemant Kumar6fd65032012-05-23 13:02:24 -0700515 if (mehci->wakeup_gpio)
516 gpio_free(mehci->wakeup_gpio);
517free_data:
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530518 gpio_free(pdata->data);
519free_strobe:
520 gpio_free(pdata->strobe);
521
522 return rc;
523}
524
Vamsi Krishna64b48612012-06-14 16:08:11 -0700525static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530526{
527 int ret;
528
Manu Gautam5143b252012-01-05 19:25:23 -0800529 ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530530 if (ret) {
Vamsi Krishna64b48612012-06-14 16:08:11 -0700531 dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
532 return;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530533 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700534 clk_disable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530535
Manu Gautam5143b252012-01-05 19:25:23 -0800536 ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530537 if (ret)
Vamsi Krishna64b48612012-06-14 16:08:11 -0700538 dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530539
Vamsi Krishna64b48612012-06-14 16:08:11 -0700540 usleep_range(10000, 12000);
541
542 clk_enable(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530543}
544
Vamsi Krishna64b48612012-06-14 16:08:11 -0700545#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
546#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4)
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530547#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8)
548#define HSIC_LV_MODE 0x04
549#define HSIC_PAD_CALIBRATION 0xA8
550#define HSIC_GPIO_PAD_VAL 0x0A0AAA10
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530551#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
552static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
553{
554 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530555 int ret;
Lena Salman8c8ba382012-02-14 15:59:31 +0200556 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530557
Vamsi Krishna64b48612012-06-14 16:08:11 -0700558 msm_hsic_clk_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530559
Vamsi Krishna64b48612012-06-14 16:08:11 -0700560 /* select ulpi phy */
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530561 writel_relaxed(0x80000000, USB_PORTSC);
562
Vamsi Krishna64b48612012-06-14 16:08:11 -0700563 mb();
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530564
Lena Salman8c8ba382012-02-14 15:59:31 +0200565 /* HSIC init sequence when HSIC signals (Strobe/Data) are
566 routed via GPIOs */
567 if (pdata && pdata->strobe && pdata->data) {
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530568
Lena Salman8c8ba382012-02-14 15:59:31 +0200569 /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
570 writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530571
Vamsi Krishna64b48612012-06-14 16:08:11 -0700572 mb();
573
Lena Salman8c8ba382012-02-14 15:59:31 +0200574 /*set periodic calibration interval to ~2.048sec in
575 HSIC_IO_CAL_REG */
576 ulpi_write(mehci, 0xFF, 0x33);
577
578 /* Enable periodic IO calibration in HSIC_CFG register */
579 ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
580
Vamsi Krishna64b48612012-06-14 16:08:11 -0700581 /* Configure GPIO pins for HSIC functionality mode */
Lena Salman8c8ba382012-02-14 15:59:31 +0200582 ret = msm_hsic_config_gpios(mehci, 1);
583 if (ret) {
584 dev_err(mehci->dev, " gpio configuarion failed\n");
585 return ret;
586 }
Vamsi Krishna64b48612012-06-14 16:08:11 -0700587 /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO PAD_CTL register */
588 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_STROBE_GPIO_PAD_CTL);
589 writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_DATA_GPIO_PAD_CTL);
590
591 mb();
592
Lena Salman8c8ba382012-02-14 15:59:31 +0200593 /* Enable HSIC mode in HSIC_CFG register */
594 ulpi_write(mehci, 0x01, 0x31);
595 } else {
596 /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
597 via dedicated I/O */
598
599 /* programmable length of connect signaling (33.2ns) */
600 ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
601 if (ret) {
602 pr_err("%s: Unable to program length of connect "
603 "signaling\n", __func__);
604 }
605
606 /*set periodic calibration interval to ~2.048sec in
607 HSIC_IO_CAL_REG */
608 ulpi_write(mehci, 0xFF, 0x33);
609
610 /* Enable HSIC mode in HSIC_CFG register */
611 ulpi_write(mehci, 0xA9, 0x30);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530612 }
613
Hemant Kumar6fd65032012-05-23 13:02:24 -0700614 /*disable auto resume*/
615 ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
616
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530617 return 0;
618}
619
620#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
621#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
622
623#ifdef CONFIG_PM_SLEEP
624static int msm_hsic_suspend(struct msm_hsic_hcd *mehci)
625{
626 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530627 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530628 u32 val;
Amit Blayd6ea6102012-06-07 16:26:24 +0300629 int none_vol, max_vol;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530630
631 if (atomic_read(&mehci->in_lpm)) {
632 dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
633 return 0;
634 }
635
636 disable_irq(hcd->irq);
Jack Phambe05fbb2012-05-16 10:56:26 -0700637
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700638 /* make sure we don't race against a remote wakeup */
639 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
Jack Phambe05fbb2012-05-16 10:56:26 -0700640 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700641 dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
Jack Phambe05fbb2012-05-16 10:56:26 -0700642 enable_irq(hcd->irq);
643 return -EBUSY;
644 }
645
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530646 /*
647 * PHY may take some time or even fail to enter into low power
648 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
649 * in failure case.
650 */
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700651 val = readl_relaxed(USB_PORTSC);
652 val &= ~PORT_RWC_BITS;
653 val |= PORTSC_PHCD;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530654 writel_relaxed(val, USB_PORTSC);
655 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
656 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
657 break;
658 udelay(1);
659 cnt++;
660 }
661
662 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
663 dev_err(mehci->dev, "Unable to suspend PHY\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530664 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530665 msm_hsic_reset(mehci);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530666 }
667
668 /*
669 * PHY has capability to generate interrupt asynchronously in low
670 * power mode (LPM). This interrupt is level triggered. So USB IRQ
671 * line must be disabled till async interrupt enable bit is cleared
672 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
Pavankumar Kondeti1c1d82b2013-01-28 21:37:59 +0530673 * block data communication from PHY. Enable asynchronous interrupt
674 * only when wakeup gpio IRQ is not present.
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530675 */
Pavankumar Kondeti1c1d82b2013-01-28 21:37:59 +0530676 if (mehci->wakeup_irq)
677 writel_relaxed(readl_relaxed(USB_USBCMD) |
678 ULPI_STP_CTRL, USB_USBCMD);
679 else
680 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530681 ULPI_STP_CTRL, USB_USBCMD);
682
683 /*
684 * Ensure that hardware is put in low power mode before
685 * clocks are turned OFF and VDD is allowed to minimize.
686 */
687 mb();
688
Manu Gautam28b1bac2012-01-30 16:43:06 +0530689 clk_disable_unprepare(mehci->core_clk);
690 clk_disable_unprepare(mehci->phy_clk);
691 clk_disable_unprepare(mehci->cal_clk);
692 clk_disable_unprepare(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530693
Amit Blayd6ea6102012-06-07 16:26:24 +0300694 none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
695 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
696
697 ret = regulator_set_voltage(mehci->hsic_vddcx, none_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700698 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300699 dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700700
Hemant Kumare6275972012-02-29 20:06:21 -0800701 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700702 mehci->bus_vote = false;
703 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800704 }
705
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530706 atomic_set(&mehci->in_lpm, 1);
707 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700708
709 mehci->wakeup_irq_enabled = 1;
710 enable_irq_wake(mehci->wakeup_irq);
711 enable_irq(mehci->wakeup_irq);
712
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700713 wake_unlock(&mehci->wlock);
714
Devin Kim476bbd72012-07-19 18:11:11 -0700715 dev_dbg(mehci->dev, "HSIC-USB in low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530716
717 return 0;
718}
719
720static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
721{
722 struct usb_hcd *hcd = hsic_to_hcd(mehci);
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +0530723 int cnt = 0, ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530724 unsigned temp;
Amit Blayd6ea6102012-06-07 16:26:24 +0300725 int min_vol, max_vol;
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700726 unsigned long flags;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530727
728 if (!atomic_read(&mehci->in_lpm)) {
729 dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
730 return 0;
731 }
732
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530733 /* Handles race with Async interrupt */
734 disable_irq(hcd->irq);
735
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700736 spin_lock_irqsave(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700737 if (mehci->wakeup_irq_enabled) {
738 disable_irq_wake(mehci->wakeup_irq);
739 disable_irq_nosync(mehci->wakeup_irq);
740 mehci->wakeup_irq_enabled = 0;
741 }
Hemant Kumar4cd49e12012-09-06 19:57:14 -0700742 spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700743
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700744 wake_lock(&mehci->wlock);
745
Hemant Kumare6275972012-02-29 20:06:21 -0800746 if (mehci->bus_perf_client && debug_bus_voting_enabled) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700747 mehci->bus_vote = true;
748 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -0800749 }
750
Amit Blayd6ea6102012-06-07 16:26:24 +0300751 min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
752 max_vol = vdd_val[mehci->vdd_type][VDD_MAX];
753
754 ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700755 if (ret < 0)
Amit Blayd6ea6102012-06-07 16:26:24 +0300756 dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");
Vamsi Krishna45d88fa2011-11-02 13:28:42 -0700757
Manu Gautam28b1bac2012-01-30 16:43:06 +0530758 clk_prepare_enable(mehci->core_clk);
759 clk_prepare_enable(mehci->phy_clk);
760 clk_prepare_enable(mehci->cal_clk);
761 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530762
763 temp = readl_relaxed(USB_USBCMD);
764 temp &= ~ASYNC_INTR_CTRL;
765 temp &= ~ULPI_STP_CTRL;
766 writel_relaxed(temp, USB_USBCMD);
767
768 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
769 goto skip_phy_resume;
770
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700771 temp = readl_relaxed(USB_PORTSC);
772 temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530773 writel_relaxed(temp, USB_PORTSC);
774 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
775 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
776 (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
777 break;
778 udelay(1);
779 cnt++;
780 }
781
782 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
783 /*
784 * This is a fatal error. Reset the link and
785 * PHY to make hsic working.
786 */
787 dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +0530788 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530789 msm_hsic_reset(mehci);
790 }
791
792skip_phy_resume:
793
Hemant Kumar6fd65032012-05-23 13:02:24 -0700794 usb_hcd_resume_root_hub(hcd);
795
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530796 atomic_set(&mehci->in_lpm, 0);
797
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530798 if (atomic_read(&mehci->async_int)) {
799 atomic_set(&mehci->async_int, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530800 pm_runtime_put_noidle(mehci->dev);
Jack Phamdd5ad792012-07-26 10:31:03 -0700801 enable_irq(hcd->irq);
Hemant Kumar6fd65032012-05-23 13:02:24 -0700802 }
803
Ajay Dudaniab3bf192012-08-28 09:58:04 -0700804 if (atomic_read(&mehci->pm_usage_cnt)) {
805 atomic_set(&mehci->pm_usage_cnt, 0);
806 pm_runtime_put_noidle(mehci->dev);
807 }
Jack Phamdd5ad792012-07-26 10:31:03 -0700808
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530809 enable_irq(hcd->irq);
Devin Kim476bbd72012-07-19 18:11:11 -0700810 dev_dbg(mehci->dev, "HSIC-USB exited from low power mode\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530811
812 return 0;
813}
814#endif
815
Hemant Kumar2309eaa2012-08-14 16:46:42 -0700816static void ehci_hsic_bus_vote_w(struct work_struct *w)
817{
818 struct msm_hsic_hcd *mehci =
819 container_of(w, struct msm_hsic_hcd, bus_vote_w);
820 int ret;
821
822 ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
823 mehci->bus_vote);
824 if (ret)
825 dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
826 __func__, ret);
827}
828
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530829static int msm_hsic_reset_done(struct usb_hcd *hcd)
830{
831 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
832 u32 __iomem *status_reg = &ehci->regs->port_status[0];
833 int ret;
834
835 ehci_writel(ehci, ehci_readl(ehci, status_reg) & ~(PORT_RWC_BITS |
836 PORT_RESET), status_reg);
837
838 ret = handshake(ehci, status_reg, PORT_RESET, 0, 1 * 1000);
839
840 if (ret)
841 pr_err("reset handshake failed in %s\n", __func__);
842 else
843 ehci_writel(ehci, ehci_readl(ehci, &ehci->regs->command) |
844 CMD_RUN, &ehci->regs->command);
845
846 return ret;
847}
848
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700849#define STS_GPTIMER0_INTERRUPT BIT(24)
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530850static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
851{
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700852 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530853 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700854 u32 status;
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530855 int ret;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530856
857 if (atomic_read(&mehci->in_lpm)) {
Hemant Kumar3dbc5b32012-05-09 15:36:11 -0700858 dev_dbg(mehci->dev, "phy async intr\n");
Pavankumar Kondetibbd05822013-01-28 17:04:39 +0530859 dbg_log_event(NULL, "Async IRQ", 0);
860 ret = pm_runtime_get(mehci->dev);
861 if ((ret == 1) || (ret == -EINPROGRESS)) {
862 pm_runtime_put_noidle(mehci->dev);
863 } else {
864 disable_irq_nosync(hcd->irq);
865 atomic_set(&mehci->async_int, 1);
866 }
867
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530868 return IRQ_HANDLED;
869 }
870
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700871 status = ehci_readl(ehci, &ehci->regs->status);
872
873 if (status & STS_GPTIMER0_INTERRUPT) {
874 int timeleft;
875
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530876 dbg_log_event(NULL, "FPR: gpt0_isr", mehci->bus_reset);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700877
878 timeleft = GPT_CNT(ehci_readl(ehci,
879 &mehci->timer->gptimer1_ctrl));
880 if (timeleft) {
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530881 if (mehci->bus_reset) {
882 ret = msm_hsic_reset_done(hcd);
883 if (ret) {
884 mehci->reset_again = 1;
885 dbg_log_event(NULL, "RESET: fail", 0);
886 }
887 } else {
888 ehci_writel(ehci, ehci_readl(ehci,
889 &ehci->regs->command) | CMD_RUN,
890 &ehci->regs->command);
891 }
892 } else {
893 if (mehci->bus_reset)
894 mehci->reset_again = 1;
895 else
896 mehci->resume_again = 1;
897 }
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700898
899 dbg_log_event(NULL, "FPR: timeleft", timeleft);
900
901 complete(&mehci->gpt0_completion);
902 ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
903 }
904
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530905 return ehci_irq(hcd);
906}
907
908static int ehci_hsic_reset(struct usb_hcd *hcd)
909{
910 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700911 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530912 int retval;
913
Ajay Dudani11ab1d52012-08-17 17:12:26 -0700914 mehci->timer = USB_HS_GPTIMER_BASE;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530915 ehci->caps = USB_CAPLENGTH;
916 ehci->regs = USB_CAPLENGTH +
917 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
918 dbg_hcs_params(ehci, "reset");
919 dbg_hcc_params(ehci, "reset");
920
921 /* cache the data to minimize the chip reads*/
922 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
923
924 hcd->has_tt = 1;
925 ehci->sbrn = HCD_USB2;
926
927 retval = ehci_halt(ehci);
928 if (retval)
929 return retval;
930
931 /* data structure init */
932 retval = ehci_init(hcd);
933 if (retval)
934 return retval;
935
936 retval = ehci_reset(ehci);
937 if (retval)
938 return retval;
939
940 /* bursts of unspecified length. */
941 writel_relaxed(0, USB_AHBBURST);
942 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530943 writel_relaxed(0x08, USB_AHBMODE);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +0530944 /* Disable streaming mode and select host mode */
945 writel_relaxed(0x13, USB_USBMODE);
946
947 ehci_port_power(ehci, 1);
948 return 0;
949}
950
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530951#define RESET_RETRY_LIMIT 3
952#define RESET_SIGNAL_TIME_SOF_USEC (50 * 1000)
953#define RESET_SIGNAL_TIME_USEC (20 * 1000)
954static void ehci_hsic_reset_sof_bug_handler(struct usb_hcd *hcd, u32 val)
955{
956 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
957 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
958 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
959 u32 __iomem *status_reg = &ehci->regs->port_status[0];
Pavankumar Kondeti37493632013-03-05 09:43:22 +0530960 u32 cmd;
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530961 unsigned long flags;
962 int retries = 0, ret, cnt = RESET_SIGNAL_TIME_USEC;
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +0530963 s32 next_latency = 0;
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530964
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +0530965 if (pdata && pdata->swfi_latency) {
966 next_latency = pdata->swfi_latency + 1;
967 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
968 next_latency = PM_QOS_DEFAULT_VALUE;
969 }
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530970
971 mehci->bus_reset = 1;
Pavankumar Kondeti37493632013-03-05 09:43:22 +0530972
973 /* Halt the controller */
974 cmd = ehci_readl(ehci, &ehci->regs->command);
975 cmd &= ~CMD_RUN;
976 ehci_writel(ehci, cmd, &ehci->regs->command);
977 ret = handshake(ehci, &ehci->regs->status, STS_HALT,
978 STS_HALT, 16 * 125);
979 if (ret) {
980 pr_err("halt handshake fatal error\n");
981 dbg_log_event(NULL, "HALT: fatal", 0);
982 goto fail;
983 }
984
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +0530985retry:
986 retries++;
987 dbg_log_event(NULL, "RESET: start", retries);
988 pr_debug("reset begin %d\n", retries);
989 mehci->reset_again = 0;
990 spin_lock_irqsave(&ehci->lock, flags);
991 ehci_writel(ehci, val, status_reg);
992 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_USEC - 1),
993 &mehci->timer->gptimer0_ld);
994 ehci_writel(ehci, GPT_RESET | GPT_RUN,
995 &mehci->timer->gptimer0_ctrl);
996 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
997 &ehci->regs->intr_enable);
998
999 ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_SOF_USEC - 1),
1000 &mehci->timer->gptimer1_ld);
1001 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1002 &mehci->timer->gptimer1_ctrl);
1003
1004 spin_unlock_irqrestore(&ehci->lock, flags);
1005 wait_for_completion(&mehci->gpt0_completion);
1006
1007 if (!mehci->reset_again)
1008 goto done;
1009
1010 if (handshake(ehci, status_reg, PORT_RESET, 0, 10 * 1000)) {
1011 pr_err("reset handshake fatal error\n");
1012 dbg_log_event(NULL, "RESET: fatal", retries);
1013 goto fail;
1014 }
1015
1016 if (retries < RESET_RETRY_LIMIT)
1017 goto retry;
1018
1019 /* complete reset in tight loop */
1020 pr_info("RESET in tight loop\n");
1021 dbg_log_event(NULL, "RESET: tight", 0);
1022
1023 spin_lock_irqsave(&ehci->lock, flags);
1024 ehci_writel(ehci, val, status_reg);
1025 while (cnt--)
1026 udelay(1);
1027 ret = msm_hsic_reset_done(hcd);
1028 spin_unlock_irqrestore(&ehci->lock, flags);
1029 if (ret) {
1030 pr_err("RESET in tight loop failed\n");
1031 dbg_log_event(NULL, "RESET: tight failed", 0);
1032 goto fail;
1033 }
1034
1035done:
1036 dbg_log_event(NULL, "RESET: done", retries);
1037 pr_debug("reset completed\n");
1038fail:
1039 mehci->bus_reset = 0;
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301040 if (next_latency)
1041 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +05301042}
1043
Hemant Kumar45d211b2012-05-31 17:58:43 -07001044static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
1045{
Pavankumar Kondeti3c137392012-09-14 14:02:36 +05301046 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1047
1048 if (!(readl_relaxed(USB_PORTSC) & PORT_PE)) {
1049 dbg_log_event(NULL, "RH suspend attempt failed", 0);
1050 dev_dbg(mehci->dev, "%s:port is not enabled skip suspend\n",
1051 __func__);
1052 return -EAGAIN;
1053 }
1054
Hemant Kumar45d211b2012-05-31 17:58:43 -07001055 dbg_log_event(NULL, "Suspend RH", 0);
1056 return ehci_bus_suspend(hcd);
1057}
1058
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001059#define RESUME_RETRY_LIMIT 3
Pavankumar Kondetic91a92a2013-01-29 19:08:12 +05301060#define RESUME_SIGNAL_TIME_USEC (21 * 1000)
1061#define RESUME_SIGNAL_TIME_SOF_USEC (23 * 1000)
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001062static int msm_hsic_resume_thread(void *data)
1063{
1064 struct msm_hsic_hcd *mehci = data;
1065 struct usb_hcd *hcd = hsic_to_hcd(mehci);
1066 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1067 u32 temp;
1068 unsigned long resume_needed = 0;
1069 int retry_cnt = 0;
1070 int tight_resume = 0;
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301071 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301072 s32 next_latency = 0;
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001073
1074 dbg_log_event(NULL, "Resume RH", 0);
1075
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301076 if (pdata && pdata->swfi_latency) {
1077 next_latency = pdata->swfi_latency + 1;
1078 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
1079 next_latency = PM_QOS_DEFAULT_VALUE;
1080 }
1081
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001082 /* keep delay between bus states */
1083 if (time_before(jiffies, ehci->next_statechange))
1084 usleep_range(5000, 5000);
1085
1086 spin_lock_irq(&ehci->lock);
1087 if (!HCD_HW_ACCESSIBLE(hcd)) {
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001088 mehci->resume_status = -ESHUTDOWN;
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301089 goto exit;
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001090 }
1091
1092 if (unlikely(ehci->debug)) {
1093 if (!dbgp_reset_prep())
1094 ehci->debug = NULL;
1095 else
1096 dbgp_external_startup();
1097 }
1098
1099 /* at least some APM implementations will try to deliver
1100 * IRQs right away, so delay them until we're ready.
1101 */
1102 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
1103
1104 /* re-init operational registers */
1105 ehci_writel(ehci, 0, &ehci->regs->segment);
1106 ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
1107 ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
1108
1109 /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
1110 if (ehci->resume_sof_bug)
1111 ehci->command &= ~CMD_RUN;
1112
1113 /* restore CMD_RUN, framelist size, and irq threshold */
1114 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1115
1116 /* manually resume the ports we suspended during bus_suspend() */
1117resume_again:
1118 if (retry_cnt >= RESUME_RETRY_LIMIT) {
1119 pr_info("retry count(%d) reached max, resume in tight loop\n",
1120 retry_cnt);
1121 tight_resume = 1;
1122 }
1123
1124
1125 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1126 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
1127 if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
1128 temp |= PORT_RESUME;
1129 set_bit(0, &resume_needed);
1130 }
1131 dbg_log_event(NULL, "FPR: Set", temp);
1132 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1133
1134 /* HSIC controller has a h/w bug due to which it can try to send SOFs
1135 * (start of frames) during port resume resulting in phy lockup. HSIC hw
1136 * controller in MSM clears FPR bit after driving the resume signal for
1137 * 20ms. Workaround is to stop SOFs before driving resume and then start
1138 * sending SOFs immediately. Need to send SOFs within 3ms of resume
1139 * completion otherwise peripheral may enter undefined state. As
1140 * usleep_range does not gurantee exact sleep time, GPTimer is used to
1141 * to time the resume sequence. If driver exceeds allowable time SOFs,
1142 * repeat the resume process.
1143 */
1144 if (ehci->resume_sof_bug && resume_needed) {
1145 if (!tight_resume) {
1146 mehci->resume_again = 0;
Pavankumar Kondetic91a92a2013-01-29 19:08:12 +05301147 ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_USEC - 1),
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001148 &mehci->timer->gptimer0_ld);
1149 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1150 &mehci->timer->gptimer0_ctrl);
1151 ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
1152 &ehci->regs->intr_enable);
1153
Pavankumar Kondetic91a92a2013-01-29 19:08:12 +05301154 ehci_writel(ehci, GPT_LD(
1155 RESUME_SIGNAL_TIME_SOF_USEC - 1),
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001156 &mehci->timer->gptimer1_ld);
1157 ehci_writel(ehci, GPT_RESET | GPT_RUN,
1158 &mehci->timer->gptimer1_ctrl);
1159
1160 spin_unlock_irq(&ehci->lock);
1161 wait_for_completion(&mehci->gpt0_completion);
1162 spin_lock_irq(&ehci->lock);
1163 } else {
1164 dbg_log_event(NULL, "FPR: Tightloop", 0);
1165 /* do the resume in a tight loop */
1166 handshake(ehci, &ehci->regs->port_status[0],
1167 PORT_RESUME, 0, 22 * 1000);
1168 ehci_writel(ehci, ehci_readl(ehci,
1169 &ehci->regs->command) | CMD_RUN,
1170 &ehci->regs->command);
1171 }
1172
1173 if (mehci->resume_again) {
1174 int temp;
1175
1176 dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
1177 pr_info("FPR: retry count: %d\n", retry_cnt);
1178 spin_unlock_irq(&ehci->lock);
1179 temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
1180 temp &= ~PORT_RWC_BITS;
1181 temp |= PORT_SUSPEND;
1182 ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
1183 /* Keep the bus idle for 5ms so that peripheral
1184 * can detect and initiate suspend
1185 */
1186 usleep_range(5000, 5000);
1187 dbg_log_event(NULL,
1188 "FPR: RResume",
1189 ehci_readl(ehci, &ehci->regs->port_status[0]));
1190 spin_lock_irq(&ehci->lock);
1191 mehci->resume_again = 0;
1192 retry_cnt++;
1193 goto resume_again;
1194 }
1195 }
1196
1197 dbg_log_event(NULL, "FPR: RT-Done", 0);
1198 mehci->resume_status = 1;
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301199exit:
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001200 spin_unlock_irq(&ehci->lock);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001201 complete(&mehci->rt_completion);
Pavankumar Kondeti8ea50d52013-07-22 15:32:17 +05301202 if (next_latency)
1203 pm_qos_update_request(&mehci->pm_qos_req_dma, next_latency);
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001204
1205 return 0;
1206}
1207
Hemant Kumar45d211b2012-05-31 17:58:43 -07001208static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
1209{
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001210 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1211 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1212 u32 temp;
1213 struct task_struct *resume_thread = NULL;
1214
1215 mehci->resume_status = 0;
1216 resume_thread = kthread_run(msm_hsic_resume_thread,
1217 mehci, "hsic_resume_thread");
1218 if (IS_ERR(resume_thread)) {
1219 pr_err("Error creating resume thread:%lu\n",
1220 PTR_ERR(resume_thread));
1221 return PTR_ERR(resume_thread);
1222 }
1223
1224 wait_for_completion(&mehci->rt_completion);
1225
1226 if (mehci->resume_status < 0)
1227 return mehci->resume_status;
1228
1229 dbg_log_event(NULL, "FPR: Wokeup", 0);
1230 spin_lock_irq(&ehci->lock);
1231 (void) ehci_readl(ehci, &ehci->regs->command);
1232
1233 temp = 0;
1234 if (ehci->async->qh_next.qh)
1235 temp |= CMD_ASE;
1236 if (ehci->periodic_sched)
1237 temp |= CMD_PSE;
1238 if (temp) {
1239 ehci->command |= temp;
1240 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1241 }
1242
1243 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
1244 hcd->state = HC_STATE_RUNNING;
1245 ehci->rh_state = EHCI_RH_RUNNING;
1246
1247 /* Now we can safely re-enable irqs */
1248 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
1249
1250 spin_unlock_irq(&ehci->lock);
1251
1252 return 0;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001253}
1254
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301255static struct hc_driver msm_hsic_driver = {
1256 .description = hcd_name,
1257 .product_desc = "Qualcomm EHCI Host Controller using HSIC",
1258 .hcd_priv_size = sizeof(struct msm_hsic_hcd),
1259
1260 /*
1261 * generic hardware linkage
1262 */
1263 .irq = msm_hsic_irq,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001264 .flags = HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301265
1266 .reset = ehci_hsic_reset,
1267 .start = ehci_run,
1268
1269 .stop = ehci_stop,
1270 .shutdown = ehci_shutdown,
1271
1272 /*
1273 * managing i/o requests and associated device resources
1274 */
Hemant Kumardf2d84d2012-08-15 09:06:35 -07001275 .urb_enqueue = ehci_urb_enqueue,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301276 .urb_dequeue = ehci_urb_dequeue,
1277 .endpoint_disable = ehci_endpoint_disable,
1278 .endpoint_reset = ehci_endpoint_reset,
1279 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1280
1281 /*
1282 * scheduling support
1283 */
1284 .get_frame_number = ehci_get_frame,
1285
1286 /*
1287 * root hub support
1288 */
1289 .hub_status_data = ehci_hub_status_data,
1290 .hub_control = ehci_hub_control,
1291 .relinquish_port = ehci_relinquish_port,
1292 .port_handed_over = ehci_port_handed_over,
1293
1294 /*
1295 * PM support
1296 */
Hemant Kumar45d211b2012-05-31 17:58:43 -07001297 .bus_suspend = ehci_hsic_bus_suspend,
1298 .bus_resume = ehci_hsic_bus_resume,
1299
Hemant Kumardf2d84d2012-08-15 09:06:35 -07001300 .log_urb = dbg_log_event,
Hemant Kumar105d07f2012-07-02 15:33:07 -07001301 .dump_regs = dump_hsic_regs,
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001302
Pavankumar Kondeti9ecc39c2013-01-29 14:41:58 +05301303 .reset_sof_bug_handler = ehci_hsic_reset_sof_bug_handler,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301304};
1305
1306static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
1307{
1308 int ret = 0;
1309
1310 if (!init)
1311 goto put_clocks;
1312
Lena Salman8c8ba382012-02-14 15:59:31 +02001313 /*core_clk is required for LINK protocol engine
1314 *clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001315 mehci->core_clk = clk_get(mehci->dev, "core_clk");
1316 if (IS_ERR(mehci->core_clk)) {
1317 dev_err(mehci->dev, "failed to get core_clk\n");
1318 ret = PTR_ERR(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301319 return ret;
1320 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301321
Lena Salman8c8ba382012-02-14 15:59:31 +02001322 /* alt_core_clk is for LINK to be used during PHY RESET
1323 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001324 mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
1325 if (IS_ERR(mehci->alt_core_clk)) {
1326 dev_err(mehci->dev, "failed to core_clk\n");
1327 ret = PTR_ERR(mehci->alt_core_clk);
1328 goto put_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301329 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301330
Lena Salman8c8ba382012-02-14 15:59:31 +02001331 /* phy_clk is required for HSIC PHY operation
1332 * clock rate appropriately set by target specific clock driver */
Manu Gautam5143b252012-01-05 19:25:23 -08001333 mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
1334 if (IS_ERR(mehci->phy_clk)) {
1335 dev_err(mehci->dev, "failed to get phy_clk\n");
1336 ret = PTR_ERR(mehci->phy_clk);
1337 goto put_alt_core_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301338 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301339
1340 /* 10MHz cal_clk is required for calibration of I/O pads */
Manu Gautam5143b252012-01-05 19:25:23 -08001341 mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301342 if (IS_ERR(mehci->cal_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001343 dev_err(mehci->dev, "failed to get cal_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301344 ret = PTR_ERR(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001345 goto put_phy_clk;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301346 }
1347 clk_set_rate(mehci->cal_clk, 10000000);
1348
1349 /* ahb_clk is required for data transfers */
Manu Gautam5143b252012-01-05 19:25:23 -08001350 mehci->ahb_clk = clk_get(mehci->dev, "iface_clk");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301351 if (IS_ERR(mehci->ahb_clk)) {
Manu Gautam5143b252012-01-05 19:25:23 -08001352 dev_err(mehci->dev, "failed to get iface_clk\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301353 ret = PTR_ERR(mehci->ahb_clk);
1354 goto put_cal_clk;
1355 }
1356
Manu Gautam28b1bac2012-01-30 16:43:06 +05301357 clk_prepare_enable(mehci->core_clk);
1358 clk_prepare_enable(mehci->phy_clk);
1359 clk_prepare_enable(mehci->cal_clk);
1360 clk_prepare_enable(mehci->ahb_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301361
1362 return 0;
1363
1364put_clocks:
Jack Phamfd193eb2012-02-22 15:38:08 -08001365 if (!atomic_read(&mehci->in_lpm)) {
1366 clk_disable_unprepare(mehci->core_clk);
1367 clk_disable_unprepare(mehci->phy_clk);
1368 clk_disable_unprepare(mehci->cal_clk);
1369 clk_disable_unprepare(mehci->ahb_clk);
1370 }
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301371 clk_put(mehci->ahb_clk);
1372put_cal_clk:
1373 clk_put(mehci->cal_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08001374put_phy_clk:
1375 clk_put(mehci->phy_clk);
1376put_alt_core_clk:
1377 clk_put(mehci->alt_core_clk);
1378put_core_clk:
1379 clk_put(mehci->core_clk);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301380
1381 return ret;
1382}
Vamsi Krishna34f01582011-12-14 19:54:42 -08001383static irqreturn_t hsic_peripheral_status_change(int irq, void *dev_id)
1384{
1385 struct msm_hsic_hcd *mehci = dev_id;
1386
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001387 pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001388
1389 if (mehci)
1390 msm_hsic_config_gpios(mehci, 0);
1391
1392 return IRQ_HANDLED;
1393}
1394
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001395static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
1396{
1397 struct msm_hsic_hcd *mehci = data;
Ajay Dudanid666daf2012-09-27 12:04:12 +05301398 int ret;
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001399
Hemant Kumar6fd65032012-05-23 13:02:24 -07001400 mehci->wakeup_int_cnt++;
Hemant Kumar45d211b2012-05-31 17:58:43 -07001401 dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
Hemant Kumar6fd65032012-05-23 13:02:24 -07001402 dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
1403 __func__, mehci->wakeup_int_cnt);
1404
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001405 wake_lock(&mehci->wlock);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001406
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001407 spin_lock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001408 if (mehci->wakeup_irq_enabled) {
1409 mehci->wakeup_irq_enabled = 0;
1410 disable_irq_wake(irq);
1411 disable_irq_nosync(irq);
1412 }
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001413 spin_unlock(&mehci->wakeup_lock);
Jack Phamfe441ea2012-03-23 17:03:15 -07001414
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001415 if (!atomic_read(&mehci->pm_usage_cnt)) {
Ajay Dudanid666daf2012-09-27 12:04:12 +05301416 ret = pm_runtime_get(mehci->dev);
1417 /*
1418 * HSIC runtime resume can race with us.
1419 * if we are active (ret == 1) or resuming
1420 * (ret == -EINPROGRESS), decrement the
1421 * PM usage counter before returning.
1422 */
1423 if ((ret == 1) || (ret == -EINPROGRESS))
1424 pm_runtime_put_noidle(mehci->dev);
1425 else
1426 atomic_set(&mehci->pm_usage_cnt, 1);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001427 }
1428
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001429 return IRQ_HANDLED;
1430}
1431
Hemant Kumare6275972012-02-29 20:06:21 -08001432static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
1433{
1434 if (debug_bus_voting_enabled)
1435 seq_printf(s, "enabled\n");
1436 else
1437 seq_printf(s, "disabled\n");
1438
1439 return 0;
1440}
1441
1442static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
1443{
1444 return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
1445}
1446
1447static ssize_t ehci_hsic_msm_bus_write(struct file *file,
1448 const char __user *ubuf, size_t count, loff_t *ppos)
1449{
1450 char buf[8];
1451 int ret;
1452 struct seq_file *s = file->private_data;
1453 struct msm_hsic_hcd *mehci = s->private;
1454
1455 memset(buf, 0x00, sizeof(buf));
1456
1457 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1458 return -EFAULT;
1459
1460 if (!strncmp(buf, "enable", 6)) {
1461 /* Do not vote here. Let hsic driver decide when to vote */
1462 debug_bus_voting_enabled = true;
1463 } else {
1464 debug_bus_voting_enabled = false;
1465 if (mehci->bus_perf_client) {
1466 ret = msm_bus_scale_client_update_request(
1467 mehci->bus_perf_client, 0);
1468 if (ret)
1469 dev_err(mehci->dev, "%s: Failed to devote "
1470 "for bus bw %d\n", __func__, ret);
1471 }
1472 }
1473
1474 return count;
1475}
1476
1477const struct file_operations ehci_hsic_msm_bus_fops = {
1478 .open = ehci_hsic_msm_bus_open,
1479 .read = seq_read,
1480 .write = ehci_hsic_msm_bus_write,
1481 .llseek = seq_lseek,
1482 .release = single_release,
1483};
1484
Hemant Kumar6fd65032012-05-23 13:02:24 -07001485static int ehci_hsic_msm_wakeup_cnt_show(struct seq_file *s, void *unused)
1486{
1487 struct msm_hsic_hcd *mehci = s->private;
1488
1489 seq_printf(s, "%u\n", mehci->wakeup_int_cnt);
1490
1491 return 0;
1492}
1493
1494static int ehci_hsic_msm_wakeup_cnt_open(struct inode *inode, struct file *f)
1495{
1496 return single_open(f, ehci_hsic_msm_wakeup_cnt_show, inode->i_private);
1497}
1498
1499const struct file_operations ehci_hsic_msm_wakeup_cnt_fops = {
1500 .open = ehci_hsic_msm_wakeup_cnt_open,
1501 .read = seq_read,
1502 .llseek = seq_lseek,
1503 .release = single_release,
1504};
1505
Hemant Kumar45d211b2012-05-31 17:58:43 -07001506static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
1507{
1508 unsigned long flags;
1509 unsigned i;
1510
1511 read_lock_irqsave(&dbg_hsic_data.lck, flags);
1512
1513 i = dbg_hsic_data.idx;
1514 for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
1515 if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
1516 continue;
1517 seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
1518 }
1519
1520 read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
1521
1522 return 0;
1523}
1524
1525static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
1526{
1527 return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
1528}
1529
1530const struct file_operations ehci_hsic_msm_dbg_data_fops = {
1531 .open = ehci_hsic_msm_data_events_open,
1532 .read = seq_read,
1533 .llseek = seq_lseek,
1534 .release = single_release,
1535};
1536
1537static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
1538{
1539 unsigned long flags;
1540 unsigned i;
1541
1542 read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
1543
1544 i = dbg_hsic_ctrl.idx;
1545 for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
1546 if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
1547 continue;
1548 seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
1549 }
1550
1551 read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
1552
1553 return 0;
1554}
1555
1556static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
1557{
1558 return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
1559}
1560
1561const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
1562 .open = ehci_hsic_msm_ctrl_events_open,
1563 .read = seq_read,
1564 .llseek = seq_lseek,
1565 .release = single_release,
1566};
1567
Hemant Kumare6275972012-02-29 20:06:21 -08001568static struct dentry *ehci_hsic_msm_dbg_root;
1569static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
1570{
1571 struct dentry *ehci_hsic_msm_dentry;
1572
1573 ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
1574
1575 if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
1576 return -ENODEV;
1577
1578 ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
1579 S_IRUGO | S_IWUSR,
1580 ehci_hsic_msm_dbg_root, mehci,
1581 &ehci_hsic_msm_bus_fops);
1582
1583 if (!ehci_hsic_msm_dentry) {
1584 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1585 return -ENODEV;
1586 }
1587
Hemant Kumar6fd65032012-05-23 13:02:24 -07001588 ehci_hsic_msm_dentry = debugfs_create_file("wakeup_cnt",
1589 S_IRUGO,
1590 ehci_hsic_msm_dbg_root, mehci,
1591 &ehci_hsic_msm_wakeup_cnt_fops);
1592
1593 if (!ehci_hsic_msm_dentry) {
1594 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1595 return -ENODEV;
1596 }
1597
Hemant Kumar45d211b2012-05-31 17:58:43 -07001598 ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
1599 S_IRUGO,
1600 ehci_hsic_msm_dbg_root, mehci,
1601 &ehci_hsic_msm_dbg_ctrl_fops);
1602
1603 if (!ehci_hsic_msm_dentry) {
1604 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1605 return -ENODEV;
1606 }
1607
1608 ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
1609 S_IRUGO,
1610 ehci_hsic_msm_dbg_root, mehci,
1611 &ehci_hsic_msm_dbg_data_fops);
1612
1613 if (!ehci_hsic_msm_dentry) {
1614 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1615 return -ENODEV;
1616 }
1617
Hemant Kumare6275972012-02-29 20:06:21 -08001618 return 0;
1619}
1620
1621static void ehci_hsic_msm_debugfs_cleanup(void)
1622{
1623 debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
1624}
1625
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301626static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
1627{
1628 struct usb_hcd *hcd;
1629 struct resource *res;
1630 struct msm_hsic_hcd *mehci;
Vijayavardhan Vennapusa2b592824f2011-11-02 19:51:32 +05301631 struct msm_hsic_host_platform_data *pdata;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301632 int ret;
1633
1634 dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
1635
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301636 /* After parent device's probe is executed, it will be put in suspend
1637 * mode. When child device's probe is called, driver core is not
1638 * resuming parent device due to which parent will be in suspend even
1639 * though child is active. Hence resume the parent device explicitly.
1640 */
1641 if (pdev->dev.parent)
1642 pm_runtime_get_sync(pdev->dev.parent);
1643
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301644 hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
1645 dev_name(&pdev->dev));
1646 if (!hcd) {
1647 dev_err(&pdev->dev, "Unable to create HCD\n");
1648 return -ENOMEM;
1649 }
1650
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301651 hcd_to_bus(hcd)->skip_resume = true;
1652
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301653 hcd->irq = platform_get_irq(pdev, 0);
1654 if (hcd->irq < 0) {
1655 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1656 ret = hcd->irq;
1657 goto put_hcd;
1658 }
1659
1660 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1661 if (!res) {
1662 dev_err(&pdev->dev, "Unable to get memory resource\n");
1663 ret = -ENODEV;
1664 goto put_hcd;
1665 }
1666
1667 hcd->rsrc_start = res->start;
1668 hcd->rsrc_len = resource_size(res);
1669 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1670 if (!hcd->regs) {
1671 dev_err(&pdev->dev, "ioremap failed\n");
1672 ret = -ENOMEM;
1673 goto put_hcd;
1674 }
1675
1676 mehci = hcd_to_hsic(hcd);
1677 mehci->dev = &pdev->dev;
Ajay Dudanic4e40db2012-08-20 14:44:40 -07001678 pdata = mehci->dev->platform_data;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301679
Hemant Kumar4cd49e12012-09-06 19:57:14 -07001680 spin_lock_init(&mehci->wakeup_lock);
1681
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001682 mehci->ehci.susp_sof_bug = 1;
Vamsi Krishna8e6edcb2012-06-20 18:08:50 -07001683 mehci->ehci.reset_sof_bug = 1;
Hemant Kumar38ce5d82012-05-29 13:00:58 -07001684
Hemant Kumare4040492012-06-21 17:35:42 -07001685 mehci->ehci.resume_sof_bug = 1;
1686
Ajay Dudanic4e40db2012-08-20 14:44:40 -07001687 if (pdata)
1688 mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
Hemant Kumar933e0402012-05-22 11:11:40 -07001689
Vamsi Krishna34f01582011-12-14 19:54:42 -08001690 res = platform_get_resource_byname(pdev,
1691 IORESOURCE_IRQ,
1692 "peripheral_status_irq");
1693 if (res)
1694 mehci->peripheral_status_irq = res->start;
1695
Hemant Kumar6fd65032012-05-23 13:02:24 -07001696 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
1697 if (res) {
1698 mehci->wakeup_gpio = res->start;
1699 mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
1700 dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
1701 }
1702
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301703 ret = msm_hsic_init_clocks(mehci, 1);
1704 if (ret) {
1705 dev_err(&pdev->dev, "unable to initialize clocks\n");
1706 ret = -ENODEV;
1707 goto unmap;
1708 }
1709
1710 ret = msm_hsic_init_vddcx(mehci, 1);
1711 if (ret) {
1712 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1713 ret = -ENODEV;
1714 goto deinit_clocks;
1715 }
1716
Ajay Dudani11ab1d52012-08-17 17:12:26 -07001717 init_completion(&mehci->rt_completion);
1718 init_completion(&mehci->gpt0_completion);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301719 ret = msm_hsic_reset(mehci);
1720 if (ret) {
1721 dev_err(&pdev->dev, "unable to initialize PHY\n");
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301722 goto deinit_vddcx;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301723 }
1724
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001725 ehci_wq = create_singlethread_workqueue("ehci_wq");
1726 if (!ehci_wq) {
1727 dev_err(&pdev->dev, "unable to create workqueue\n");
1728 ret = -ENOMEM;
1729 goto deinit_vddcx;
1730 }
1731
1732 INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
1733
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301734 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1735 if (ret) {
1736 dev_err(&pdev->dev, "unable to register HCD\n");
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301737 goto unconfig_gpio;
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301738 }
1739
1740 device_init_wakeup(&pdev->dev, 1);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001741 wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
1742 wake_lock(&mehci->wlock);
Vamsi Krishna34f01582011-12-14 19:54:42 -08001743
1744 if (mehci->peripheral_status_irq) {
1745 ret = request_threaded_irq(mehci->peripheral_status_irq,
1746 NULL, hsic_peripheral_status_change,
1747 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
1748 | IRQF_SHARED,
1749 "hsic_peripheral_status", mehci);
1750 if (ret)
1751 dev_err(&pdev->dev, "%s:request_irq:%d failed:%d",
1752 __func__, mehci->peripheral_status_irq, ret);
1753 }
1754
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001755 /* configure wakeup irq */
Hemant Kumar6fd65032012-05-23 13:02:24 -07001756 if (mehci->wakeup_irq) {
Hemant Kumar5e386632012-08-30 14:23:38 -07001757 /* In case if wakeup gpio is pulled high at this point
1758 * remote wakeup interrupt fires right after request_irq.
1759 * Remote wake up interrupt only needs to be enabled when
1760 * HSIC bus goes to suspend.
1761 */
1762 irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001763 ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
Hemant Kumar6fd65032012-05-23 13:02:24 -07001764 IRQF_TRIGGER_HIGH,
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001765 "msm_hsic_wakeup", mehci);
Hemant Kumar5e386632012-08-30 14:23:38 -07001766 if (ret) {
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001767 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1768 mehci->wakeup_irq, ret);
1769 mehci->wakeup_irq = 0;
1770 }
1771 }
1772
Hemant Kumare6275972012-02-29 20:06:21 -08001773 ret = ehci_hsic_msm_debugfs_init(mehci);
1774 if (ret)
1775 dev_dbg(&pdev->dev, "mode debugfs file is"
1776 "not available\n");
1777
1778 if (pdata && pdata->bus_scale_table) {
1779 mehci->bus_perf_client =
1780 msm_bus_scale_register_client(pdata->bus_scale_table);
1781 /* Configure BUS performance parameters for MAX bandwidth */
1782 if (mehci->bus_perf_client) {
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001783 mehci->bus_vote = true;
1784 queue_work(ehci_wq, &mehci->bus_vote_w);
Hemant Kumare6275972012-02-29 20:06:21 -08001785 } else {
1786 dev_err(&pdev->dev, "%s: Failed to register BUS "
1787 "scaling client!!\n", __func__);
1788 }
1789 }
1790
Hemant Kumar105d07f2012-07-02 15:33:07 -07001791 __mehci = mehci;
1792
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301793 if (pdata && pdata->swfi_latency)
1794 pm_qos_add_request(&mehci->pm_qos_req_dma,
1795 PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
1796
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301797 /*
1798 * This pdev->dev is assigned parent of root-hub by USB core,
1799 * hence, runtime framework automatically calls this driver's
1800 * runtime APIs based on root-hub's state.
1801 */
1802 pm_runtime_set_active(&pdev->dev);
1803 pm_runtime_enable(&pdev->dev);
Vijayavardhan Vennapusaafbbb8f2012-04-13 16:28:45 +05301804 /* Decrement the parent device's counter after probe.
1805 * As child is active, parent will not be put into
1806 * suspend mode.
1807 */
1808 if (pdev->dev.parent)
1809 pm_runtime_put_sync(pdev->dev.parent);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301810
1811 return 0;
1812
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301813unconfig_gpio:
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001814 destroy_workqueue(ehci_wq);
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301815 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301816deinit_vddcx:
1817 msm_hsic_init_vddcx(mehci, 0);
1818deinit_clocks:
1819 msm_hsic_init_clocks(mehci, 0);
1820unmap:
1821 iounmap(hcd->regs);
1822put_hcd:
1823 usb_put_hcd(hcd);
1824
1825 return ret;
1826}
1827
1828static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev)
1829{
1830 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1831 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301832 struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
1833
Pavankumar Kondetifff3f2e2013-02-12 21:43:56 +05301834 /* Remove the HCD prior to releasing our resources. */
1835 usb_remove_hcd(hcd);
1836
Pavankumar Kondetife2d4d32012-09-07 15:33:09 +05301837 if (pdata && pdata->swfi_latency)
1838 pm_qos_remove_request(&mehci->pm_qos_req_dma);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301839
Vamsi Krishna34f01582011-12-14 19:54:42 -08001840 if (mehci->peripheral_status_irq)
1841 free_irq(mehci->peripheral_status_irq, mehci);
Jack Phamfe441ea2012-03-23 17:03:15 -07001842
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001843 if (mehci->wakeup_irq) {
Jack Phamfe441ea2012-03-23 17:03:15 -07001844 if (mehci->wakeup_irq_enabled)
1845 disable_irq_wake(mehci->wakeup_irq);
Vamsi Krishna6921cbe2012-02-21 18:34:43 -08001846 free_irq(mehci->wakeup_irq, mehci);
1847 }
Vamsi Krishna34f01582011-12-14 19:54:42 -08001848
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001849 /*
1850 * If the update request is called after unregister, the request will
1851 * fail. Results are undefined if unregister is called in the middle of
1852 * update request.
1853 */
1854 mehci->bus_vote = false;
1855 cancel_work_sync(&mehci->bus_vote_w);
1856
Hemant Kumare6275972012-02-29 20:06:21 -08001857 if (mehci->bus_perf_client)
1858 msm_bus_scale_unregister_client(mehci->bus_perf_client);
1859
1860 ehci_hsic_msm_debugfs_cleanup();
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301861 device_init_wakeup(&pdev->dev, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301862 pm_runtime_set_suspended(&pdev->dev);
1863
Hemant Kumar2309eaa2012-08-14 16:46:42 -07001864 destroy_workqueue(ehci_wq);
1865
Vijayavardhan Vennapusae3316a12011-10-15 06:05:17 +05301866 msm_hsic_config_gpios(mehci, 0);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301867 msm_hsic_init_vddcx(mehci, 0);
1868
1869 msm_hsic_init_clocks(mehci, 0);
Ajay Dudaniab3bf192012-08-28 09:58:04 -07001870 wake_lock_destroy(&mehci->wlock);
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301871 iounmap(hcd->regs);
1872 usb_put_hcd(hcd);
1873
1874 return 0;
1875}
1876
1877#ifdef CONFIG_PM_SLEEP
1878static int msm_hsic_pm_suspend(struct device *dev)
1879{
1880 struct usb_hcd *hcd = dev_get_drvdata(dev);
1881 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1882
1883 dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
1884
Hemant Kumar45d211b2012-05-31 17:58:43 -07001885 dbg_log_event(NULL, "PM Suspend", 0);
1886
Pavankumar Kondetife319632013-04-25 13:51:24 +05301887 if (!atomic_read(&mehci->in_lpm)) {
1888 dev_info(dev, "abort suspend\n");
1889 dbg_log_event(NULL, "PM Suspend abort", 0);
1890 return -EBUSY;
1891 }
1892
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301893 if (device_may_wakeup(dev))
1894 enable_irq_wake(hcd->irq);
1895
Pavankumar Kondetife319632013-04-25 13:51:24 +05301896 return 0;
Jack Phamfe441ea2012-03-23 17:03:15 -07001897}
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301898
Jack Pham16b06f82012-08-14 20:03:59 -07001899static int msm_hsic_pm_suspend_noirq(struct device *dev)
1900{
1901 struct usb_hcd *hcd = dev_get_drvdata(dev);
1902 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1903
Pavankumar Kondetibbd05822013-01-28 17:04:39 +05301904 if (atomic_read(&mehci->async_int)) {
Jack Pham16b06f82012-08-14 20:03:59 -07001905 dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
1906 return -EBUSY;
1907 }
1908
1909 return 0;
1910}
1911
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301912static int msm_hsic_pm_resume(struct device *dev)
1913{
1914 int ret;
1915 struct usb_hcd *hcd = dev_get_drvdata(dev);
1916 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1917
Jack Pham16b06f82012-08-14 20:03:59 -07001918 dev_dbg(dev, "ehci-msm-hsic PM resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001919 dbg_log_event(NULL, "PM Resume", 0);
1920
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301921 if (device_may_wakeup(dev))
1922 disable_irq_wake(hcd->irq);
1923
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301924 /*
1925 * Keep HSIC in Low Power Mode if system is resumed
1926 * by any other wakeup source. HSIC is resumed later
1927 * when remote wakeup is received or interface driver
1928 * start I/O.
1929 */
Pavankumar Kondeti98089c02012-11-09 10:54:00 +05301930 if (!atomic_read(&mehci->pm_usage_cnt) &&
Pavankumar Kondetibbd05822013-01-28 17:04:39 +05301931 !atomic_read(&mehci->async_int) &&
Pavankumar Kondeti98089c02012-11-09 10:54:00 +05301932 pm_runtime_suspended(dev))
Pavankumar Kondeti1c851692012-09-18 17:52:51 +05301933 return 0;
1934
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301935 ret = msm_hsic_resume(mehci);
1936 if (ret)
1937 return ret;
1938
1939 /* Bring the device to full powered state upon system resume */
1940 pm_runtime_disable(dev);
1941 pm_runtime_set_active(dev);
1942 pm_runtime_enable(dev);
1943
1944 return 0;
1945}
1946#endif
1947
1948#ifdef CONFIG_PM_RUNTIME
1949static int msm_hsic_runtime_idle(struct device *dev)
1950{
1951 dev_dbg(dev, "EHCI runtime idle\n");
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301952 return 0;
1953}
1954
1955static int msm_hsic_runtime_suspend(struct device *dev)
1956{
1957 struct usb_hcd *hcd = dev_get_drvdata(dev);
1958 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1959
1960 dev_dbg(dev, "EHCI runtime suspend\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001961
1962 dbg_log_event(NULL, "Run Time PM Suspend", 0);
1963
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301964 return msm_hsic_suspend(mehci);
1965}
1966
1967static int msm_hsic_runtime_resume(struct device *dev)
1968{
1969 struct usb_hcd *hcd = dev_get_drvdata(dev);
1970 struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
1971
1972 dev_dbg(dev, "EHCI runtime resume\n");
Hemant Kumar45d211b2012-05-31 17:58:43 -07001973
1974 dbg_log_event(NULL, "Run Time PM Resume", 0);
1975
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301976 return msm_hsic_resume(mehci);
1977}
1978#endif
1979
1980#ifdef CONFIG_PM
1981static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
1982 SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
Jack Pham16b06f82012-08-14 20:03:59 -07001983 .suspend_noirq = msm_hsic_pm_suspend_noirq,
Vijayavardhan Vennapusa39025fe2011-10-15 05:55:10 +05301984 SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
1985 msm_hsic_runtime_idle)
1986};
1987#endif
1988
1989static struct platform_driver ehci_msm_hsic_driver = {
1990 .probe = ehci_hsic_msm_probe,
1991 .remove = __devexit_p(ehci_hsic_msm_remove),
1992 .driver = {
1993 .name = "msm_hsic_host",
1994#ifdef CONFIG_PM
1995 .pm = &msm_hsic_dev_pm_ops,
1996#endif
1997 },
1998};