Lines Matching +full:data +full:- +full:role
1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2018-2019 Cadence.
6 * Copyright (C) 2017-2018 NXP
14 #include <linux/dma-mapping.h>
24 #include "host-export.h"
25 #include "gadget-export.h"
30 static int cdns3_role_start(struct cdns3 *cdns, enum usb_role role) in cdns3_role_start() argument
34 if (WARN_ON(role > USB_ROLE_DEVICE)) in cdns3_role_start()
37 mutex_lock(&cdns->mutex); in cdns3_role_start()
38 cdns->role = role; in cdns3_role_start()
39 mutex_unlock(&cdns->mutex); in cdns3_role_start()
41 if (!cdns->roles[role]) in cdns3_role_start()
42 return -ENXIO; in cdns3_role_start()
44 if (cdns->roles[role]->state == CDNS3_ROLE_STATE_ACTIVE) in cdns3_role_start()
47 mutex_lock(&cdns->mutex); in cdns3_role_start()
48 ret = cdns->roles[role]->start(cdns); in cdns3_role_start()
50 cdns->roles[role]->state = CDNS3_ROLE_STATE_ACTIVE; in cdns3_role_start()
51 mutex_unlock(&cdns->mutex); in cdns3_role_start()
58 enum usb_role role = cdns->role; in cdns3_role_stop() local
60 if (WARN_ON(role > USB_ROLE_DEVICE)) in cdns3_role_stop()
63 if (cdns->roles[role]->state == CDNS3_ROLE_STATE_INACTIVE) in cdns3_role_stop()
66 mutex_lock(&cdns->mutex); in cdns3_role_stop()
67 cdns->roles[role]->stop(cdns); in cdns3_role_stop()
68 cdns->roles[role]->state = CDNS3_ROLE_STATE_INACTIVE; in cdns3_role_stop()
69 mutex_unlock(&cdns->mutex); in cdns3_role_stop()
79 * cdns3_core_init_role - initialize role of operation
86 struct device *dev = cdns->dev; in cdns3_core_init_role()
92 cdns->role = USB_ROLE_NONE; in cdns3_core_init_role()
110 * At this point cdns->dr_mode contains strap configuration. in cdns3_core_init_role()
113 best_dr_mode = cdns->dr_mode; in cdns3_core_init_role()
120 best_dr_mode = cdns->dr_mode; in cdns3_core_init_role()
121 } else if (cdns->dr_mode == USB_DR_MODE_OTG) { in cdns3_core_init_role()
123 } else if (cdns->dr_mode != dr_mode) { in cdns3_core_init_role()
125 return -EINVAL; in cdns3_core_init_role()
148 cdns->dr_mode = dr_mode; in cdns3_core_init_role()
154 /* Initialize idle role to start with */ in cdns3_core_init_role()
159 switch (cdns->dr_mode) { in cdns3_core_init_role()
176 ret = -EINVAL; in cdns3_core_init_role()
187 * cdns3_hw_role_state_machine - role switch state machine based on hw events.
190 * Returns next role to be entered based on hw events.
194 enum usb_role role = USB_ROLE_NONE; in cdns3_hw_role_state_machine() local
197 if (cdns->dr_mode != USB_DR_MODE_OTG) { in cdns3_hw_role_state_machine()
199 role = USB_ROLE_HOST; in cdns3_hw_role_state_machine()
201 role = USB_ROLE_DEVICE; in cdns3_hw_role_state_machine()
203 return role; in cdns3_hw_role_state_machine()
210 * Role change state machine in cdns3_hw_role_state_machine()
212 * Previous state: cdns->role in cdns3_hw_role_state_machine()
213 * Next state: role in cdns3_hw_role_state_machine()
215 role = cdns->role; in cdns3_hw_role_state_machine()
217 switch (role) { in cdns3_hw_role_state_machine()
224 role = USB_ROLE_HOST; in cdns3_hw_role_state_machine()
226 role = USB_ROLE_DEVICE; in cdns3_hw_role_state_machine()
230 role = USB_ROLE_NONE; in cdns3_hw_role_state_machine()
234 role = USB_ROLE_NONE; in cdns3_hw_role_state_machine()
238 dev_dbg(cdns->dev, "role %d -> %d\n", cdns->role, role); in cdns3_hw_role_state_machine()
240 return role; in cdns3_hw_role_state_machine()
251 phy_reset(cdns->usb3_phy); in cdns3_idle_role_stop()
258 rdrv = devm_kzalloc(cdns->dev, sizeof(*rdrv), GFP_KERNEL); in cdns3_idle_init()
260 return -ENOMEM; in cdns3_idle_init()
262 rdrv->start = cdns3_idle_role_start; in cdns3_idle_init()
263 rdrv->stop = cdns3_idle_role_stop; in cdns3_idle_init()
264 rdrv->state = CDNS3_ROLE_STATE_INACTIVE; in cdns3_idle_init()
265 rdrv->suspend = NULL; in cdns3_idle_init()
266 rdrv->resume = NULL; in cdns3_idle_init()
267 rdrv->name = "idle"; in cdns3_idle_init()
269 cdns->roles[USB_ROLE_NONE] = rdrv; in cdns3_idle_init()
275 * cdns3_hw_role_switch - switch roles based on HW state
283 /* Depends on role switch class */ in cdns3_hw_role_switch()
284 if (cdns->role_sw) in cdns3_hw_role_switch()
287 pm_runtime_get_sync(cdns->dev); in cdns3_hw_role_switch()
289 current_role = cdns->role; in cdns3_hw_role_switch()
298 dev_dbg(cdns->dev, "Switching role %d -> %d", current_role, real_role); in cdns3_hw_role_switch()
302 /* Back to current role */ in cdns3_hw_role_switch()
303 dev_err(cdns->dev, "set %d has failed, back to %d\n", in cdns3_hw_role_switch()
307 dev_err(cdns->dev, "back to %d failed too\n", in cdns3_hw_role_switch()
311 pm_runtime_put_sync(cdns->dev); in cdns3_hw_role_switch()
316 * cdsn3_role_get - get current role of controller.
318 * @sw: pointer to USB role switch structure
320 * Returns role
326 return cdns->role; in cdns3_role_get()
330 * cdns3_role_set - set current role of controller.
332 * @sw: pointer to USB role switch structure
333 * @role: the previous role
335 * - Role switch for dual-role devices
336 * - USB_ROLE_GADGET <--> USB_ROLE_NONE for peripheral-only devices
338 static int cdns3_role_set(struct usb_role_switch *sw, enum usb_role role) in cdns3_role_set() argument
343 pm_runtime_get_sync(cdns->dev); in cdns3_role_set()
345 if (cdns->role == role) in cdns3_role_set()
348 if (cdns->dr_mode == USB_DR_MODE_HOST) { in cdns3_role_set()
349 switch (role) { in cdns3_role_set()
358 if (cdns->dr_mode == USB_DR_MODE_PERIPHERAL) { in cdns3_role_set()
359 switch (role) { in cdns3_role_set()
369 ret = cdns3_role_start(cdns, role); in cdns3_role_set()
371 dev_err(cdns->dev, "set role %d has failed\n", role); in cdns3_role_set()
374 pm_runtime_put_sync(cdns->dev); in cdns3_role_set()
382 ret = phy_power_on(cdns->usb2_phy); in set_phy_power_on()
386 ret = phy_power_on(cdns->usb3_phy); in set_phy_power_on()
388 phy_power_off(cdns->usb2_phy); in set_phy_power_on()
395 phy_power_off(cdns->usb3_phy); in set_phy_power_off()
396 phy_power_off(cdns->usb2_phy); in set_phy_power_off()
400 * cdns3_wakeup_irq - interrupt handler for wakeup events
402 * @data: structure of cdns3
406 static irqreturn_t cdns3_wakeup_irq(int irq, void *data) in cdns3_wakeup_irq() argument
408 struct cdns3 *cdns = data; in cdns3_wakeup_irq()
410 if (cdns->in_lpm) { in cdns3_wakeup_irq()
412 cdns->wakeup_pending = true; in cdns3_wakeup_irq()
413 if ((cdns->role == USB_ROLE_HOST) && cdns->host_dev) in cdns3_wakeup_irq()
414 pm_request_resume(&cdns->host_dev->dev); in cdns3_wakeup_irq()
423 * cdns3_probe - probe for cdns3 core device
430 struct device *dev = &pdev->dev; in cdns3_probe()
444 return -ENOMEM; in cdns3_probe()
446 cdns->dev = dev; in cdns3_probe()
447 cdns->pdata = dev_get_platdata(dev); in cdns3_probe()
454 return -ENODEV; in cdns3_probe()
457 cdns->xhci_res[0] = *res; in cdns3_probe()
462 return -ENXIO; in cdns3_probe()
465 cdns->xhci_res[1] = *res; in cdns3_probe()
467 cdns->dev_irq = platform_get_irq_byname(pdev, "peripheral"); in cdns3_probe()
468 if (cdns->dev_irq == -EPROBE_DEFER) in cdns3_probe()
469 return cdns->dev_irq; in cdns3_probe()
471 if (cdns->dev_irq < 0) in cdns3_probe()
477 cdns->dev_regs = regs; in cdns3_probe()
479 cdns->otg_irq = platform_get_irq_byname(pdev, "otg"); in cdns3_probe()
480 if (cdns->otg_irq == -EPROBE_DEFER) in cdns3_probe()
481 return cdns->otg_irq; in cdns3_probe()
483 if (cdns->otg_irq < 0) { in cdns3_probe()
485 return cdns->otg_irq; in cdns3_probe()
491 return -ENXIO; in cdns3_probe()
494 cdns->phyrst_a_enable = device_property_read_bool(dev, "cdns,phyrst-a-enable"); in cdns3_probe()
496 cdns->otg_res = *res; in cdns3_probe()
498 cdns->wakeup_irq = platform_get_irq_byname_optional(pdev, "wakeup"); in cdns3_probe()
499 if (cdns->wakeup_irq == -EPROBE_DEFER) in cdns3_probe()
500 return cdns->wakeup_irq; in cdns3_probe()
501 else if (cdns->wakeup_irq == 0) in cdns3_probe()
502 return -EINVAL; in cdns3_probe()
504 if (cdns->wakeup_irq < 0) { in cdns3_probe()
506 cdns->wakeup_irq = 0x0; in cdns3_probe()
509 mutex_init(&cdns->mutex); in cdns3_probe()
511 cdns->usb2_phy = devm_phy_optional_get(dev, "cdns3,usb2-phy"); in cdns3_probe()
512 if (IS_ERR(cdns->usb2_phy)) in cdns3_probe()
513 return PTR_ERR(cdns->usb2_phy); in cdns3_probe()
515 ret = phy_init(cdns->usb2_phy); in cdns3_probe()
519 cdns->usb3_phy = devm_phy_optional_get(dev, "cdns3,usb3-phy"); in cdns3_probe()
520 if (IS_ERR(cdns->usb3_phy)) in cdns3_probe()
521 return PTR_ERR(cdns->usb3_phy); in cdns3_probe()
523 ret = phy_init(cdns->usb3_phy); in cdns3_probe()
531 if (device_property_read_bool(dev, "usb-role-switch")) { in cdns3_probe()
538 sw_desc.fwnode = dev->fwnode; in cdns3_probe()
540 cdns->role_sw = usb_role_switch_register(dev, &sw_desc); in cdns3_probe()
541 if (IS_ERR(cdns->role_sw)) { in cdns3_probe()
542 ret = PTR_ERR(cdns->role_sw); in cdns3_probe()
543 dev_warn(dev, "Unable to register Role Switch\n"); in cdns3_probe()
548 if (cdns->wakeup_irq) { in cdns3_probe()
549 ret = devm_request_irq(cdns->dev, cdns->wakeup_irq, in cdns3_probe()
552 dev_name(cdns->dev), cdns); in cdns3_probe()
555 dev_err(cdns->dev, "couldn't register wakeup irq handler\n"); in cdns3_probe()
568 spin_lock_init(&cdns->lock); in cdns3_probe()
587 if (cdns->role_sw) in cdns3_probe()
588 usb_role_switch_unregister(cdns->role_sw); in cdns3_probe()
592 phy_exit(cdns->usb3_phy); in cdns3_probe()
594 phy_exit(cdns->usb2_phy); in cdns3_probe()
600 * cdns3_remove - unbind drd driver and clean up
609 pm_runtime_get_sync(&pdev->dev); in cdns3_remove()
610 pm_runtime_disable(&pdev->dev); in cdns3_remove()
611 pm_runtime_put_noidle(&pdev->dev); in cdns3_remove()
613 usb_role_switch_unregister(cdns->role_sw); in cdns3_remove()
615 phy_exit(cdns->usb2_phy); in cdns3_remove()
616 phy_exit(cdns->usb3_phy); in cdns3_remove()
628 if (cdns->pdata && cdns->pdata->platform_suspend) in cdns3_set_platform_suspend()
629 ret = cdns->pdata->platform_suspend(dev, suspend, wakeup); in cdns3_set_platform_suspend()
640 if (cdns->in_lpm) in cdns3_controller_suspend()
648 cdns3_set_platform_suspend(cdns->dev, true, wakeup); in cdns3_controller_suspend()
650 spin_lock_irqsave(&cdns->lock, flags); in cdns3_controller_suspend()
651 cdns->in_lpm = true; in cdns3_controller_suspend()
652 spin_unlock_irqrestore(&cdns->lock, flags); in cdns3_controller_suspend()
653 dev_dbg(cdns->dev, "%s ends\n", __func__); in cdns3_controller_suspend()
664 if (!cdns->in_lpm) in cdns3_controller_resume()
671 cdns3_set_platform_suspend(cdns->dev, false, false); in cdns3_controller_resume()
673 spin_lock_irqsave(&cdns->lock, flags); in cdns3_controller_resume()
674 if (cdns->roles[cdns->role]->resume && !PMSG_IS_AUTO(msg)) in cdns3_controller_resume()
675 cdns->roles[cdns->role]->resume(cdns, false); in cdns3_controller_resume()
677 cdns->in_lpm = false; in cdns3_controller_resume()
678 spin_unlock_irqrestore(&cdns->lock, flags); in cdns3_controller_resume()
679 if (cdns->wakeup_pending) { in cdns3_controller_resume()
680 cdns->wakeup_pending = false; in cdns3_controller_resume()
681 enable_irq(cdns->wakeup_irq); in cdns3_controller_resume()
683 dev_dbg(cdns->dev, "%s ends\n", __func__); in cdns3_controller_resume()
707 if (cdns->roles[cdns->role]->suspend) { in cdns3_suspend()
708 spin_lock_irqsave(&cdns->lock, flags); in cdns3_suspend()
709 cdns->roles[cdns->role]->suspend(cdns, false); in cdns3_suspend()
710 spin_unlock_irqrestore(&cdns->lock, flags); in cdns3_suspend()
750 .name = "cdns-usb3",