blob: 42936f16df027f5dee9ee7fd25d5fa8eb5e05b34 [file] [log] [blame]
Ajay Agarwal76081082018-01-31 14:32:19 +05301/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
Manu Gautam115c2982013-07-17 11:58:34 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 */
7
8#include <linux/module.h>
9#include <linux/platform_device.h>
10#include <linux/pm_runtime.h>
11#include <linux/usb/msm_hsusb_hw.h>
12#include <linux/usb/ulpi.h>
13#include <linux/gpio.h>
Ajay Agarwal76081082018-01-31 14:32:19 +053014#include <linux/pinctrl/consumer.h>
Manu Gautam115c2982013-07-17 11:58:34 +053015
16#include "ci13xxx_udc.c"
17
18#define MSM_USB_BASE (udc->regs)
19
20#define CI13XXX_MSM_MAX_LOG2_ITC 7
21
22struct ci13xxx_udc_context {
23 int irq;
24 void __iomem *regs;
25 int wake_gpio;
26 int wake_irq;
27 bool wake_irq_state;
Ajay Agarwal76081082018-01-31 14:32:19 +053028 struct pinctrl *ci13xxx_pinctrl;
29 struct timer_list irq_enable_timer;
30 bool irq_disabled;
Manu Gautam115c2982013-07-17 11:58:34 +053031};
32
33static struct ci13xxx_udc_context _udc_ctxt;
Ajay Agarwal76081082018-01-31 14:32:19 +053034#define IRQ_ENABLE_DELAY (jiffies + msecs_to_jiffies(1000))
Manu Gautam115c2982013-07-17 11:58:34 +053035
36static irqreturn_t msm_udc_irq(int irq, void *data)
37{
38 return udc_irq();
39}
40
41static void ci13xxx_msm_suspend(void)
42{
43 struct device *dev = _udc->gadget.dev.parent;
Ajay Agarwal76081082018-01-31 14:32:19 +053044
Manu Gautam115c2982013-07-17 11:58:34 +053045 dev_dbg(dev, "ci13xxx_msm_suspend\n");
46
47 if (_udc_ctxt.wake_irq && !_udc_ctxt.wake_irq_state) {
48 enable_irq_wake(_udc_ctxt.wake_irq);
49 enable_irq(_udc_ctxt.wake_irq);
50 _udc_ctxt.wake_irq_state = true;
51 }
52}
53
54static void ci13xxx_msm_resume(void)
55{
56 struct device *dev = _udc->gadget.dev.parent;
Ajay Agarwal76081082018-01-31 14:32:19 +053057
Manu Gautam115c2982013-07-17 11:58:34 +053058 dev_dbg(dev, "ci13xxx_msm_resume\n");
59
60 if (_udc_ctxt.wake_irq && _udc_ctxt.wake_irq_state) {
61 disable_irq_wake(_udc_ctxt.wake_irq);
62 disable_irq_nosync(_udc_ctxt.wake_irq);
63 _udc_ctxt.wake_irq_state = false;
64 }
65}
66
67static void ci13xxx_msm_disconnect(void)
68{
69 struct ci13xxx *udc = _udc;
70 struct usb_phy *phy = udc->transceiver;
71
Ajay Agarwal76081082018-01-31 14:32:19 +053072 if (phy && (phy->flags & ENABLE_DP_MANUAL_PULLUP)) {
Manu Gautam115c2982013-07-17 11:58:34 +053073 usb_phy_io_write(phy,
74 ULPI_MISC_A_VBUSVLDEXT |
75 ULPI_MISC_A_VBUSVLDEXTSEL,
76 ULPI_CLR(ULPI_MISC_A));
Ajay Agarwal76081082018-01-31 14:32:19 +053077
Ajay Agarwal76081082018-01-31 14:32:19 +053078 /*
79 * Add memory barrier as it is must to complete
80 * above USB PHY and Link register writes before
81 * moving ahead with USB peripheral mode enumeration,
82 * otherwise USB peripheral mode may not work.
83 */
84 mb();
85 }
Manu Gautam115c2982013-07-17 11:58:34 +053086}
87
88/* Link power management will reduce power consumption by
89 * short time HW suspend/resume.
90 */
91static void ci13xxx_msm_set_l1(struct ci13xxx *udc)
92{
93 int temp;
94 struct device *dev = udc->gadget.dev.parent;
95
96 dev_dbg(dev, "Enable link power management\n");
97
98 /* Enable remote wakeup and L1 for IN EPs */
99 writel_relaxed(0xffff0000, USB_L1_EP_CTRL);
100
101 temp = readl_relaxed(USB_L1_CONFIG);
102 temp |= L1_CONFIG_LPM_EN | L1_CONFIG_REMOTE_WAKEUP |
103 L1_CONFIG_GATE_SYS_CLK | L1_CONFIG_PHY_LPM |
104 L1_CONFIG_PLL;
105 writel_relaxed(temp, USB_L1_CONFIG);
106}
107
108static void ci13xxx_msm_connect(void)
109{
110 struct ci13xxx *udc = _udc;
111 struct usb_phy *phy = udc->transceiver;
112
113 if (phy && (phy->flags & ENABLE_DP_MANUAL_PULLUP)) {
114 int temp;
115
116 usb_phy_io_write(phy,
117 ULPI_MISC_A_VBUSVLDEXT |
118 ULPI_MISC_A_VBUSVLDEXTSEL,
119 ULPI_SET(ULPI_MISC_A));
120
Ajay Agarwal76081082018-01-31 14:32:19 +0530121 temp = readl_relaxed(USB_GENCONFIG_2);
122 temp |= GENCONFIG_2_SESS_VLD_CTRL_EN;
123 writel_relaxed(temp, USB_GENCONFIG_2);
Manu Gautam115c2982013-07-17 11:58:34 +0530124
125 temp = readl_relaxed(USB_USBCMD);
126 temp |= USBCMD_SESS_VLD_CTRL;
127 writel_relaxed(temp, USB_USBCMD);
128
129 /*
130 * Add memory barrier as it is must to complete
131 * above USB PHY and Link register writes before
132 * moving ahead with USB peripheral mode enumeration,
133 * otherwise USB peripheral mode may not work.
134 */
135 mb();
136 }
137}
138
139static void ci13xxx_msm_reset(void)
140{
141 struct ci13xxx *udc = _udc;
142 struct usb_phy *phy = udc->transceiver;
143 struct device *dev = udc->gadget.dev.parent;
Ajay Agarwal76081082018-01-31 14:32:19 +0530144 int temp;
Manu Gautam115c2982013-07-17 11:58:34 +0530145
146 writel_relaxed(0, USB_AHBBURST);
147 writel_relaxed(0x08, USB_AHBMODE);
148
Ajay Agarwal76081082018-01-31 14:32:19 +0530149 /* workaround for rx buffer collision issue */
150 temp = readl_relaxed(USB_GENCONFIG);
151 temp &= ~GENCONFIG_TXFIFO_IDLE_FORCE_DISABLE;
152 temp &= ~GENCONFIG_ULPI_SERIAL_EN;
153 writel_relaxed(temp, USB_GENCONFIG);
154
Manu Gautam115c2982013-07-17 11:58:34 +0530155 if (udc->gadget.l1_supported)
156 ci13xxx_msm_set_l1(udc);
157
158 if (phy && (phy->flags & ENABLE_SECONDARY_PHY)) {
159 int temp;
160
161 dev_dbg(dev, "using secondary hsphy\n");
162 temp = readl_relaxed(USB_PHY_CTRL2);
163 temp |= (1<<16);
164 writel_relaxed(temp, USB_PHY_CTRL2);
165
166 /*
167 * Add memory barrier to make sure above LINK writes are
168 * complete before moving ahead with USB peripheral mode
169 * enumeration.
170 */
171 mb();
172 }
173}
174
Ajay Agarwal76081082018-01-31 14:32:19 +0530175static void ci13xxx_msm_mark_err_event(void)
176{
177 struct ci13xxx *udc = _udc;
178 struct msm_otg *otg;
179
180 if (udc == NULL)
181 return;
182
183 if (udc->transceiver == NULL)
184 return;
185
186 otg = container_of(udc->transceiver, struct msm_otg, phy);
187
188 /* This will trigger hardware reset before next connection */
189 otg->err_event_seen = true;
190}
191
192static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned int event)
Manu Gautam115c2982013-07-17 11:58:34 +0530193{
194 struct device *dev = udc->gadget.dev.parent;
195
196 switch (event) {
197 case CI13XXX_CONTROLLER_RESET_EVENT:
198 dev_info(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
199 ci13xxx_msm_reset();
200 break;
201 case CI13XXX_CONTROLLER_DISCONNECT_EVENT:
202 dev_info(dev, "CI13XXX_CONTROLLER_DISCONNECT_EVENT received\n");
203 ci13xxx_msm_disconnect();
204 ci13xxx_msm_resume();
205 break;
206 case CI13XXX_CONTROLLER_CONNECT_EVENT:
207 dev_info(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
208 ci13xxx_msm_connect();
209 break;
210 case CI13XXX_CONTROLLER_SUSPEND_EVENT:
211 dev_info(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
212 ci13xxx_msm_suspend();
213 break;
214 case CI13XXX_CONTROLLER_RESUME_EVENT:
215 dev_info(dev, "CI13XXX_CONTROLLER_RESUME_EVENT received\n");
216 ci13xxx_msm_resume();
217 break;
Ajay Agarwal76081082018-01-31 14:32:19 +0530218 case CI13XXX_CONTROLLER_ERROR_EVENT:
219 dev_info(dev, "CI13XXX_CONTROLLER_ERROR_EVENT received\n");
220 ci13xxx_msm_mark_err_event();
221 break;
222 case CI13XXX_CONTROLLER_UDC_STARTED_EVENT:
223 dev_info(dev,
224 "CI13XXX_CONTROLLER_UDC_STARTED_EVENT received\n");
225 break;
Manu Gautam115c2982013-07-17 11:58:34 +0530226 default:
227 dev_dbg(dev, "unknown ci13xxx_udc event\n");
228 break;
229 }
230}
231
Ajay Agarwal76081082018-01-31 14:32:19 +0530232static bool ci13xxx_msm_in_lpm(struct ci13xxx *udc)
233{
234 struct msm_otg *otg;
235
236 if (udc == NULL)
237 return false;
238
239 if (udc->transceiver == NULL)
240 return false;
241
242 otg = container_of(udc->transceiver, struct msm_otg, phy);
243
244 return (atomic_read(&otg->in_lpm) != 0);
245}
246
247
Manu Gautam115c2982013-07-17 11:58:34 +0530248static irqreturn_t ci13xxx_msm_resume_irq(int irq, void *data)
249{
250 struct ci13xxx *udc = _udc;
251
252 if (udc->transceiver && udc->vbus_active && udc->suspended)
253 usb_phy_set_suspend(udc->transceiver, 0);
254 else if (!udc->suspended)
255 ci13xxx_msm_resume();
256
257 return IRQ_HANDLED;
258}
259
260static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
261 .name = "ci13xxx_msm",
262 .flags = CI13XXX_REGS_SHARED |
263 CI13XXX_REQUIRE_TRANSCEIVER |
264 CI13XXX_PULLUP_ON_VBUS |
265 CI13XXX_ZERO_ITC |
Ajay Agarwal76081082018-01-31 14:32:19 +0530266 CI13XXX_DISABLE_STREAMING,
Manu Gautam115c2982013-07-17 11:58:34 +0530267 .nz_itc = 0,
268 .notify_event = ci13xxx_msm_notify_event,
Ajay Agarwal76081082018-01-31 14:32:19 +0530269 .in_lpm = ci13xxx_msm_in_lpm,
Manu Gautam115c2982013-07-17 11:58:34 +0530270};
271
272static int ci13xxx_msm_install_wake_gpio(struct platform_device *pdev,
273 struct resource *res)
274{
275 int wake_irq;
276 int ret;
Ajay Agarwal76081082018-01-31 14:32:19 +0530277 struct pinctrl_state *set_state;
Manu Gautam115c2982013-07-17 11:58:34 +0530278
279 dev_dbg(&pdev->dev, "ci13xxx_msm_install_wake_gpio\n");
280
281 _udc_ctxt.wake_gpio = res->start;
Ajay Agarwal76081082018-01-31 14:32:19 +0530282 if (_udc_ctxt.ci13xxx_pinctrl) {
283 set_state = pinctrl_lookup_state(_udc_ctxt.ci13xxx_pinctrl,
284 "ci13xxx_active");
285 if (IS_ERR(set_state)) {
286 pr_err("cannot get ci13xxx pinctrl active state\n");
287 return PTR_ERR(set_state);
288 }
289 pinctrl_select_state(_udc_ctxt.ci13xxx_pinctrl, set_state);
290 }
Manu Gautam115c2982013-07-17 11:58:34 +0530291 gpio_request(_udc_ctxt.wake_gpio, "USB_RESUME");
292 gpio_direction_input(_udc_ctxt.wake_gpio);
293 wake_irq = gpio_to_irq(_udc_ctxt.wake_gpio);
294 if (wake_irq < 0) {
295 dev_err(&pdev->dev, "could not register USB_RESUME GPIO.\n");
296 return -ENXIO;
297 }
298
299 dev_dbg(&pdev->dev, "_udc_ctxt.gpio_irq = %d and irq = %d\n",
300 _udc_ctxt.wake_gpio, wake_irq);
301 ret = request_irq(wake_irq, ci13xxx_msm_resume_irq,
302 IRQF_TRIGGER_RISING | IRQF_ONESHOT, "usb resume", NULL);
303 if (ret < 0) {
304 dev_err(&pdev->dev, "could not register USB_RESUME IRQ.\n");
305 goto gpio_free;
306 }
307 disable_irq(wake_irq);
308 _udc_ctxt.wake_irq = wake_irq;
309
310 return 0;
311
312gpio_free:
313 gpio_free(_udc_ctxt.wake_gpio);
Ajay Agarwal76081082018-01-31 14:32:19 +0530314 if (_udc_ctxt.ci13xxx_pinctrl) {
315 set_state = pinctrl_lookup_state(_udc_ctxt.ci13xxx_pinctrl,
316 "ci13xxx_sleep");
317 if (IS_ERR(set_state))
318 pr_err("cannot get ci13xxx pinctrl sleep state\n");
319 else
320 pinctrl_select_state(_udc_ctxt.ci13xxx_pinctrl,
321 set_state);
322 }
Manu Gautam115c2982013-07-17 11:58:34 +0530323 _udc_ctxt.wake_gpio = 0;
324 return ret;
325}
326
327static void ci13xxx_msm_uninstall_wake_gpio(struct platform_device *pdev)
328{
Ajay Agarwal76081082018-01-31 14:32:19 +0530329 struct pinctrl_state *set_state;
330
Manu Gautam115c2982013-07-17 11:58:34 +0530331 dev_dbg(&pdev->dev, "ci13xxx_msm_uninstall_wake_gpio\n");
332
333 if (_udc_ctxt.wake_gpio) {
334 gpio_free(_udc_ctxt.wake_gpio);
Ajay Agarwal76081082018-01-31 14:32:19 +0530335 if (_udc_ctxt.ci13xxx_pinctrl) {
336 set_state =
337 pinctrl_lookup_state(_udc_ctxt.ci13xxx_pinctrl,
338 "ci13xxx_sleep");
339 if (IS_ERR(set_state))
340 pr_err("cannot get ci13xxx pinctrl sleep state\n");
341 else
342 pinctrl_select_state(_udc_ctxt.ci13xxx_pinctrl,
343 set_state);
344 }
Manu Gautam115c2982013-07-17 11:58:34 +0530345 _udc_ctxt.wake_gpio = 0;
346 }
347}
348
Ajay Agarwal76081082018-01-31 14:32:19 +0530349static void enable_usb_irq_timer_func(unsigned long data);
Manu Gautam115c2982013-07-17 11:58:34 +0530350static int ci13xxx_msm_probe(struct platform_device *pdev)
351{
352 struct resource *res;
353 int ret;
354 struct ci13xxx_platform_data *pdata = pdev->dev.platform_data;
355 bool is_l1_supported = false;
356
357 dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
358
359 if (pdata) {
360 /* Acceptable values for nz_itc are: 0,1,2,4,8,16,32,64 */
361 if (pdata->log2_itc > CI13XXX_MSM_MAX_LOG2_ITC ||
362 pdata->log2_itc <= 0)
363 ci13xxx_msm_udc_driver.nz_itc = 0;
364 else
365 ci13xxx_msm_udc_driver.nz_itc =
366 1 << (pdata->log2_itc-1);
367
368 is_l1_supported = pdata->l1_supported;
Ajay Agarwal76081082018-01-31 14:32:19 +0530369 /* Set ahb2ahb bypass flag if it is requested. */
370 if (pdata->enable_ahb2ahb_bypass)
371 ci13xxx_msm_udc_driver.flags |=
372 CI13XXX_ENABLE_AHB2AHB_BYPASS;
373
374 /* Clear disable streaming flag if is requested. */
375 if (pdata->enable_streaming)
376 ci13xxx_msm_udc_driver.flags &=
377 ~CI13XXX_DISABLE_STREAMING;
Manu Gautam115c2982013-07-17 11:58:34 +0530378 }
379
380 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
381 if (!res) {
382 dev_err(&pdev->dev, "failed to get platform resource mem\n");
383 return -ENXIO;
384 }
385
386 _udc_ctxt.regs = ioremap(res->start, resource_size(res));
387 if (!_udc_ctxt.regs) {
388 dev_err(&pdev->dev, "ioremap failed\n");
389 return -ENOMEM;
390 }
391
392 ret = udc_probe(&ci13xxx_msm_udc_driver, &pdev->dev, _udc_ctxt.regs);
393 if (ret < 0) {
394 dev_err(&pdev->dev, "udc_probe failed\n");
395 goto iounmap;
396 }
397
398 _udc->gadget.l1_supported = is_l1_supported;
399
400 _udc_ctxt.irq = platform_get_irq(pdev, 0);
401 if (_udc_ctxt.irq < 0) {
402 dev_err(&pdev->dev, "IRQ not found\n");
403 ret = -ENXIO;
404 goto udc_remove;
405 }
406
407 res = platform_get_resource_byname(pdev, IORESOURCE_IO, "USB_RESUME");
Ajay Agarwal76081082018-01-31 14:32:19 +0530408 /* Get pinctrl if target uses pinctrl */
409 _udc_ctxt.ci13xxx_pinctrl = devm_pinctrl_get(&pdev->dev);
410 if (IS_ERR(_udc_ctxt.ci13xxx_pinctrl)) {
411 if (of_property_read_bool(pdev->dev.of_node, "pinctrl-names")) {
412 dev_err(&pdev->dev, "Error encountered while getting pinctrl");
413 ret = PTR_ERR(_udc_ctxt.ci13xxx_pinctrl);
414 goto udc_remove;
415 }
416 dev_dbg(&pdev->dev, "Target does not use pinctrl\n");
417 _udc_ctxt.ci13xxx_pinctrl = NULL;
418 }
Manu Gautam115c2982013-07-17 11:58:34 +0530419 if (res) {
420 ret = ci13xxx_msm_install_wake_gpio(pdev, res);
421 if (ret < 0) {
422 dev_err(&pdev->dev, "gpio irq install failed\n");
423 goto udc_remove;
424 }
425 }
426
427 ret = request_irq(_udc_ctxt.irq, msm_udc_irq, IRQF_SHARED, pdev->name,
428 pdev);
429 if (ret < 0) {
430 dev_err(&pdev->dev, "request_irq failed\n");
431 goto gpio_uninstall;
432 }
433
Ajay Agarwal76081082018-01-31 14:32:19 +0530434 setup_timer(&_udc_ctxt.irq_enable_timer, enable_usb_irq_timer_func,
435 (unsigned long)NULL);
436
Manu Gautam115c2982013-07-17 11:58:34 +0530437 pm_runtime_no_callbacks(&pdev->dev);
Ajay Agarwal76081082018-01-31 14:32:19 +0530438 pm_runtime_set_active(&pdev->dev);
Manu Gautam115c2982013-07-17 11:58:34 +0530439 pm_runtime_enable(&pdev->dev);
440
441 return 0;
442
443gpio_uninstall:
444 ci13xxx_msm_uninstall_wake_gpio(pdev);
445udc_remove:
446 udc_remove();
447iounmap:
448 iounmap(_udc_ctxt.regs);
449
450 return ret;
451}
452
453int ci13xxx_msm_remove(struct platform_device *pdev)
454{
455 pm_runtime_disable(&pdev->dev);
456 free_irq(_udc_ctxt.irq, pdev);
457 ci13xxx_msm_uninstall_wake_gpio(pdev);
458 udc_remove();
459 iounmap(_udc_ctxt.regs);
460 return 0;
461}
462
Ajay Agarwal76081082018-01-31 14:32:19 +0530463void ci13xxx_msm_shutdown(struct platform_device *pdev)
464{
465 ci13xxx_pullup(&_udc->gadget, 0);
466}
467
468void msm_hw_soft_reset(void)
469{
470 struct ci13xxx *udc = _udc;
471
472 hw_device_reset(udc);
473}
474
Manu Gautam115c2982013-07-17 11:58:34 +0530475void msm_hw_bam_disable(bool bam_disable)
476{
477 u32 val;
478 struct ci13xxx *udc = _udc;
479
480 if (bam_disable)
481 val = readl_relaxed(USB_GENCONFIG) | GENCONFIG_BAM_DISABLE;
482 else
483 val = readl_relaxed(USB_GENCONFIG) & ~GENCONFIG_BAM_DISABLE;
484
485 writel_relaxed(val, USB_GENCONFIG);
486}
487
Ajay Agarwal76081082018-01-31 14:32:19 +0530488void msm_usb_irq_disable(bool disable)
489{
490 struct ci13xxx *udc = _udc;
491 unsigned long flags;
492
493 spin_lock_irqsave(udc->lock, flags);
494
495 if (_udc_ctxt.irq_disabled == disable) {
496 pr_debug("Interrupt state already disable = %d\n", disable);
497 if (disable)
498 mod_timer(&_udc_ctxt.irq_enable_timer,
499 IRQ_ENABLE_DELAY);
500 spin_unlock_irqrestore(udc->lock, flags);
501 return;
502 }
503
504 if (disable) {
505 disable_irq_nosync(_udc_ctxt.irq);
506 /* start timer here */
507 pr_debug("%s: Disabling interrupts\n", __func__);
508 mod_timer(&_udc_ctxt.irq_enable_timer, IRQ_ENABLE_DELAY);
509 _udc_ctxt.irq_disabled = true;
510
511 } else {
512 pr_debug("%s: Enabling interrupts\n", __func__);
513 del_timer(&_udc_ctxt.irq_enable_timer);
514 enable_irq(_udc_ctxt.irq);
515 _udc_ctxt.irq_disabled = false;
516 }
517
518 spin_unlock_irqrestore(udc->lock, flags);
519}
520
521static void enable_usb_irq_timer_func(unsigned long data)
522{
523 pr_debug("enabling interrupt from timer\n");
524 msm_usb_irq_disable(false);
525}
526
Manu Gautam115c2982013-07-17 11:58:34 +0530527static struct platform_driver ci13xxx_msm_driver = {
528 .probe = ci13xxx_msm_probe,
529 .driver = {
530 .name = "msm_hsusb",
531 },
532 .remove = ci13xxx_msm_remove,
Ajay Agarwal76081082018-01-31 14:32:19 +0530533 .shutdown = ci13xxx_msm_shutdown,
Manu Gautam115c2982013-07-17 11:58:34 +0530534};
535MODULE_ALIAS("platform:msm_hsusb");
536
537static int __init ci13xxx_msm_init(void)
538{
539 return platform_driver_register(&ci13xxx_msm_driver);
540}
541module_init(ci13xxx_msm_init);
542
543static void __exit ci13xxx_msm_exit(void)
544{
545 platform_driver_unregister(&ci13xxx_msm_driver);
546}
547module_exit(ci13xxx_msm_exit);
548
549MODULE_LICENSE("GPL v2");