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>
23 #include "host-export.h"
28 static int cdns_role_start(struct cdns *cdns, enum usb_role role) in cdns_role_start() argument
32 if (WARN_ON(role > USB_ROLE_DEVICE)) in cdns_role_start()
35 mutex_lock(&cdns->mutex); in cdns_role_start()
36 cdns->role = role; in cdns_role_start()
37 mutex_unlock(&cdns->mutex); in cdns_role_start()
39 if (!cdns->roles[role]) in cdns_role_start()
40 return -ENXIO; in cdns_role_start()
42 if (cdns->roles[role]->state == CDNS_ROLE_STATE_ACTIVE) in cdns_role_start()
45 mutex_lock(&cdns->mutex); in cdns_role_start()
46 ret = cdns->roles[role]->start(cdns); in cdns_role_start()
48 cdns->roles[role]->state = CDNS_ROLE_STATE_ACTIVE; in cdns_role_start()
49 mutex_unlock(&cdns->mutex); in cdns_role_start()
56 enum usb_role role = cdns->role; in cdns_role_stop() local
58 if (WARN_ON(role > USB_ROLE_DEVICE)) in cdns_role_stop()
61 if (cdns->roles[role]->state == CDNS_ROLE_STATE_INACTIVE) in cdns_role_stop()
64 mutex_lock(&cdns->mutex); in cdns_role_stop()
65 cdns->roles[role]->stop(cdns); in cdns_role_stop()
66 cdns->roles[role]->state = CDNS_ROLE_STATE_INACTIVE; in cdns_role_stop()
67 mutex_unlock(&cdns->mutex); in cdns_role_stop()
77 * cdns_core_init_role - initialize role of operation
84 struct device *dev = cdns->dev; in cdns_core_init_role()
90 cdns->role = USB_ROLE_NONE; in cdns_core_init_role()
98 if (cdns->version == CDNSP_CONTROLLER_V2) { in cdns_core_init_role()
118 * At this point cdns->dr_mode contains strap configuration. in cdns_core_init_role()
121 best_dr_mode = cdns->dr_mode; in cdns_core_init_role()
128 best_dr_mode = cdns->dr_mode; in cdns_core_init_role()
129 } else if (cdns->dr_mode == USB_DR_MODE_OTG) { in cdns_core_init_role()
131 } else if (cdns->dr_mode != dr_mode) { in cdns_core_init_role()
133 return -EINVAL; in cdns_core_init_role()
139 if ((cdns->version == CDNSP_CONTROLLER_V2 && in cdns_core_init_role()
141 (cdns->version < CDNSP_CONTROLLER_V2 && in cdns_core_init_role()
145 ret = -ENXIO; in cdns_core_init_role()
155 if (cdns->gadget_init) in cdns_core_init_role()
156 ret = cdns->gadget_init(cdns); in cdns_core_init_role()
158 ret = -ENXIO; in cdns_core_init_role()
167 cdns->dr_mode = dr_mode; in cdns_core_init_role()
173 /* Initialize idle role to start with */ in cdns_core_init_role()
178 switch (cdns->dr_mode) { in cdns_core_init_role()
195 ret = -EINVAL; in cdns_core_init_role()
206 * cdns_hw_role_state_machine - role switch state machine based on hw events.
209 * Returns next role to be entered based on hw events.
213 enum usb_role role = USB_ROLE_NONE; in cdns_hw_role_state_machine() local
216 if (cdns->dr_mode != USB_DR_MODE_OTG) { in cdns_hw_role_state_machine()
218 role = USB_ROLE_HOST; in cdns_hw_role_state_machine()
220 role = USB_ROLE_DEVICE; in cdns_hw_role_state_machine()
222 return role; in cdns_hw_role_state_machine()
229 * Role change state machine in cdns_hw_role_state_machine()
231 * Previous state: cdns->role in cdns_hw_role_state_machine()
232 * Next state: role in cdns_hw_role_state_machine()
234 role = cdns->role; in cdns_hw_role_state_machine()
236 switch (role) { in cdns_hw_role_state_machine()
243 role = USB_ROLE_HOST; in cdns_hw_role_state_machine()
245 role = USB_ROLE_DEVICE; in cdns_hw_role_state_machine()
249 role = USB_ROLE_NONE; in cdns_hw_role_state_machine()
253 role = USB_ROLE_NONE; in cdns_hw_role_state_machine()
257 dev_dbg(cdns->dev, "role %d -> %d\n", cdns->role, role); in cdns_hw_role_state_machine()
259 return role; in cdns_hw_role_state_machine()
270 phy_reset(cdns->usb3_phy); in cdns_idle_role_stop()
277 rdrv = devm_kzalloc(cdns->dev, sizeof(*rdrv), GFP_KERNEL); in cdns_idle_init()
279 return -ENOMEM; in cdns_idle_init()
281 rdrv->start = cdns_idle_role_start; in cdns_idle_init()
282 rdrv->stop = cdns_idle_role_stop; in cdns_idle_init()
283 rdrv->state = CDNS_ROLE_STATE_INACTIVE; in cdns_idle_init()
284 rdrv->suspend = NULL; in cdns_idle_init()
285 rdrv->resume = NULL; in cdns_idle_init()
286 rdrv->name = "idle"; in cdns_idle_init()
288 cdns->roles[USB_ROLE_NONE] = rdrv; in cdns_idle_init()
294 * cdns_hw_role_switch - switch roles based on HW state
302 /* Depends on role switch class */ in cdns_hw_role_switch()
303 if (cdns->role_sw) in cdns_hw_role_switch()
306 pm_runtime_get_sync(cdns->dev); in cdns_hw_role_switch()
308 current_role = cdns->role; in cdns_hw_role_switch()
317 dev_dbg(cdns->dev, "Switching role %d -> %d", current_role, real_role); in cdns_hw_role_switch()
321 /* Back to current role */ in cdns_hw_role_switch()
322 dev_err(cdns->dev, "set %d has failed, back to %d\n", in cdns_hw_role_switch()
326 dev_err(cdns->dev, "back to %d failed too\n", in cdns_hw_role_switch()
330 pm_runtime_put_sync(cdns->dev); in cdns_hw_role_switch()
335 * cdns_role_get - get current role of controller.
337 * @sw: pointer to USB role switch structure
339 * Returns role
345 return cdns->role; in cdns_role_get()
349 * cdns_role_set - set current role of controller.
351 * @sw: pointer to USB role switch structure
352 * @role: the previous role
354 * - Role switch for dual-role devices
355 * - USB_ROLE_GADGET <--> USB_ROLE_NONE for peripheral-only devices
357 static int cdns_role_set(struct usb_role_switch *sw, enum usb_role role) in cdns_role_set() argument
362 pm_runtime_get_sync(cdns->dev); in cdns_role_set()
364 if (cdns->role == role) in cdns_role_set()
367 if (cdns->dr_mode == USB_DR_MODE_HOST) { in cdns_role_set()
368 switch (role) { in cdns_role_set()
377 if (cdns->dr_mode == USB_DR_MODE_PERIPHERAL) { in cdns_role_set()
378 switch (role) { in cdns_role_set()
388 ret = cdns_role_start(cdns, role); in cdns_role_set()
390 dev_err(cdns->dev, "set role %d has failed\n", role); in cdns_role_set()
393 pm_runtime_put_sync(cdns->dev); in cdns_role_set()
399 * cdns_wakeup_irq - interrupt handler for wakeup events
401 * @data: structure of cdns
405 static irqreturn_t cdns_wakeup_irq(int irq, void *data) in cdns_wakeup_irq() argument
407 struct cdns *cdns = data; in cdns_wakeup_irq()
409 if (cdns->in_lpm) { in cdns_wakeup_irq()
411 cdns->wakeup_pending = true; in cdns_wakeup_irq()
412 if ((cdns->role == USB_ROLE_HOST) && cdns->host_dev) in cdns_wakeup_irq()
413 pm_request_resume(&cdns->host_dev->dev); in cdns_wakeup_irq()
422 * cdns_init - probe for cdns3/cdnsp core device
429 struct device *dev = cdns->dev; in cdns_init()
438 mutex_init(&cdns->mutex); in cdns_init()
440 if (device_property_read_bool(dev, "usb-role-switch")) { in cdns_init()
447 sw_desc.fwnode = dev->fwnode; in cdns_init()
449 cdns->role_sw = usb_role_switch_register(dev, &sw_desc); in cdns_init()
450 if (IS_ERR(cdns->role_sw)) { in cdns_init()
451 dev_warn(dev, "Unable to register Role Switch\n"); in cdns_init()
452 return PTR_ERR(cdns->role_sw); in cdns_init()
456 if (cdns->wakeup_irq) { in cdns_init()
457 ret = devm_request_irq(cdns->dev, cdns->wakeup_irq, in cdns_init()
460 dev_name(cdns->dev), cdns); in cdns_init()
463 dev_err(cdns->dev, "couldn't register wakeup irq handler\n"); in cdns_init()
476 spin_lock_init(&cdns->lock); in cdns_init()
484 if (cdns->role_sw) in cdns_init()
485 usb_role_switch_unregister(cdns->role_sw); in cdns_init()
492 * cdns_remove - unbind drd driver and clean up
500 usb_role_switch_unregister(cdns->role_sw); in cdns_remove()
509 struct device *dev = cdns->dev; in cdns_suspend()
515 if (cdns->roles[cdns->role]->suspend) { in cdns_suspend()
516 spin_lock_irqsave(&cdns->lock, flags); in cdns_suspend()
517 cdns->roles[cdns->role]->suspend(cdns, false); in cdns_suspend()
518 spin_unlock_irqrestore(&cdns->lock, flags); in cdns_suspend()
527 struct device *dev = cdns->dev; in cdns_resume()
533 if (cdns->role_sw) { in cdns_resume()
534 cdns->role = cdns_role_get(cdns->role_sw); in cdns_resume()
537 if (real_role != cdns->role) { in cdns_resume()
546 if (cdns->role == USB_ROLE_HOST) in cdns_resume()
548 else if (cdns->role == USB_ROLE_DEVICE) in cdns_resume()
556 if (cdns->roles[cdns->role]->resume) in cdns_resume()
557 cdns->roles[cdns->role]->resume(cdns, cdns_power_is_lost(cdns)); in cdns_resume()