Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Cadence USBSS and USBSSP DRD Driver.
0004  *
0005  * Copyright (C) 2018-2019 Cadence.
0006  * Copyright (C) 2017-2018 NXP
0007  * Copyright (C) 2019 Texas Instruments
0008  *
0009  * Author: Peter Chen <peter.chen@nxp.com>
0010  *         Pawel Laszczak <pawell@cadence.com>
0011  *         Roger Quadros <rogerq@ti.com>
0012  */
0013 
0014 #include <linux/dma-mapping.h>
0015 #include <linux/module.h>
0016 #include <linux/kernel.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/io.h>
0020 #include <linux/pm_runtime.h>
0021 
0022 #include "core.h"
0023 #include "host-export.h"
0024 #include "drd.h"
0025 
0026 static int cdns_idle_init(struct cdns *cdns);
0027 
0028 static int cdns_role_start(struct cdns *cdns, enum usb_role role)
0029 {
0030     int ret;
0031 
0032     if (WARN_ON(role > USB_ROLE_DEVICE))
0033         return 0;
0034 
0035     mutex_lock(&cdns->mutex);
0036     cdns->role = role;
0037     mutex_unlock(&cdns->mutex);
0038 
0039     if (!cdns->roles[role])
0040         return -ENXIO;
0041 
0042     if (cdns->roles[role]->state == CDNS_ROLE_STATE_ACTIVE)
0043         return 0;
0044 
0045     mutex_lock(&cdns->mutex);
0046     ret = cdns->roles[role]->start(cdns);
0047     if (!ret)
0048         cdns->roles[role]->state = CDNS_ROLE_STATE_ACTIVE;
0049     mutex_unlock(&cdns->mutex);
0050 
0051     return ret;
0052 }
0053 
0054 static void cdns_role_stop(struct cdns *cdns)
0055 {
0056     enum usb_role role = cdns->role;
0057 
0058     if (WARN_ON(role > USB_ROLE_DEVICE))
0059         return;
0060 
0061     if (cdns->roles[role]->state == CDNS_ROLE_STATE_INACTIVE)
0062         return;
0063 
0064     mutex_lock(&cdns->mutex);
0065     cdns->roles[role]->stop(cdns);
0066     cdns->roles[role]->state = CDNS_ROLE_STATE_INACTIVE;
0067     mutex_unlock(&cdns->mutex);
0068 }
0069 
0070 static void cdns_exit_roles(struct cdns *cdns)
0071 {
0072     cdns_role_stop(cdns);
0073     cdns_drd_exit(cdns);
0074 }
0075 
0076 /**
0077  * cdns_core_init_role - initialize role of operation
0078  * @cdns: Pointer to cdns structure
0079  *
0080  * Returns 0 on success otherwise negative errno
0081  */
0082 static int cdns_core_init_role(struct cdns *cdns)
0083 {
0084     struct device *dev = cdns->dev;
0085     enum usb_dr_mode best_dr_mode;
0086     enum usb_dr_mode dr_mode;
0087     int ret;
0088 
0089     dr_mode = usb_get_dr_mode(dev);
0090     cdns->role = USB_ROLE_NONE;
0091 
0092     /*
0093      * If driver can't read mode by means of usb_get_dr_mode function then
0094      * chooses mode according with Kernel configuration. This setting
0095      * can be restricted later depending on strap pin configuration.
0096      */
0097     if (dr_mode == USB_DR_MODE_UNKNOWN) {
0098         if (cdns->version == CDNSP_CONTROLLER_V2) {
0099             if (IS_ENABLED(CONFIG_USB_CDNSP_HOST) &&
0100                 IS_ENABLED(CONFIG_USB_CDNSP_GADGET))
0101                 dr_mode = USB_DR_MODE_OTG;
0102             else if (IS_ENABLED(CONFIG_USB_CDNSP_HOST))
0103                 dr_mode = USB_DR_MODE_HOST;
0104             else if (IS_ENABLED(CONFIG_USB_CDNSP_GADGET))
0105                 dr_mode = USB_DR_MODE_PERIPHERAL;
0106         } else {
0107             if (IS_ENABLED(CONFIG_USB_CDNS3_HOST) &&
0108                 IS_ENABLED(CONFIG_USB_CDNS3_GADGET))
0109                 dr_mode = USB_DR_MODE_OTG;
0110             else if (IS_ENABLED(CONFIG_USB_CDNS3_HOST))
0111                 dr_mode = USB_DR_MODE_HOST;
0112             else if (IS_ENABLED(CONFIG_USB_CDNS3_GADGET))
0113                 dr_mode = USB_DR_MODE_PERIPHERAL;
0114         }
0115     }
0116 
0117     /*
0118      * At this point cdns->dr_mode contains strap configuration.
0119      * Driver try update this setting considering kernel configuration
0120      */
0121     best_dr_mode = cdns->dr_mode;
0122 
0123     ret = cdns_idle_init(cdns);
0124     if (ret)
0125         return ret;
0126 
0127     if (dr_mode == USB_DR_MODE_OTG) {
0128         best_dr_mode = cdns->dr_mode;
0129     } else if (cdns->dr_mode == USB_DR_MODE_OTG) {
0130         best_dr_mode = dr_mode;
0131     } else if (cdns->dr_mode != dr_mode) {
0132         dev_err(dev, "Incorrect DRD configuration\n");
0133         return -EINVAL;
0134     }
0135 
0136     dr_mode = best_dr_mode;
0137 
0138     if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
0139         if ((cdns->version == CDNSP_CONTROLLER_V2 &&
0140              IS_ENABLED(CONFIG_USB_CDNSP_HOST)) ||
0141             (cdns->version < CDNSP_CONTROLLER_V2 &&
0142              IS_ENABLED(CONFIG_USB_CDNS3_HOST)))
0143             ret = cdns_host_init(cdns);
0144         else
0145             ret = -ENXIO;
0146 
0147         if (ret) {
0148             dev_err(dev, "Host initialization failed with %d\n",
0149                 ret);
0150             goto err;
0151         }
0152     }
0153 
0154     if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) {
0155         if (cdns->gadget_init)
0156             ret = cdns->gadget_init(cdns);
0157         else
0158             ret = -ENXIO;
0159 
0160         if (ret) {
0161             dev_err(dev, "Device initialization failed with %d\n",
0162                 ret);
0163             goto err;
0164         }
0165     }
0166 
0167     cdns->dr_mode = dr_mode;
0168 
0169     ret = cdns_drd_update_mode(cdns);
0170     if (ret)
0171         goto err;
0172 
0173     /* Initialize idle role to start with */
0174     ret = cdns_role_start(cdns, USB_ROLE_NONE);
0175     if (ret)
0176         goto err;
0177 
0178     switch (cdns->dr_mode) {
0179     case USB_DR_MODE_OTG:
0180         ret = cdns_hw_role_switch(cdns);
0181         if (ret)
0182             goto err;
0183         break;
0184     case USB_DR_MODE_PERIPHERAL:
0185         ret = cdns_role_start(cdns, USB_ROLE_DEVICE);
0186         if (ret)
0187             goto err;
0188         break;
0189     case USB_DR_MODE_HOST:
0190         ret = cdns_role_start(cdns, USB_ROLE_HOST);
0191         if (ret)
0192             goto err;
0193         break;
0194     default:
0195         ret = -EINVAL;
0196         goto err;
0197     }
0198 
0199     return 0;
0200 err:
0201     cdns_exit_roles(cdns);
0202     return ret;
0203 }
0204 
0205 /**
0206  * cdns_hw_role_state_machine  - role switch state machine based on hw events.
0207  * @cdns: Pointer to controller structure.
0208  *
0209  * Returns next role to be entered based on hw events.
0210  */
0211 static enum usb_role cdns_hw_role_state_machine(struct cdns *cdns)
0212 {
0213     enum usb_role role = USB_ROLE_NONE;
0214     int id, vbus;
0215 
0216     if (cdns->dr_mode != USB_DR_MODE_OTG) {
0217         if (cdns_is_host(cdns))
0218             role = USB_ROLE_HOST;
0219         if (cdns_is_device(cdns))
0220             role = USB_ROLE_DEVICE;
0221 
0222         return role;
0223     }
0224 
0225     id = cdns_get_id(cdns);
0226     vbus = cdns_get_vbus(cdns);
0227 
0228     /*
0229      * Role change state machine
0230      * Inputs: ID, VBUS
0231      * Previous state: cdns->role
0232      * Next state: role
0233      */
0234     role = cdns->role;
0235 
0236     switch (role) {
0237     case USB_ROLE_NONE:
0238         /*
0239          * Driver treats USB_ROLE_NONE synonymous to IDLE state from
0240          * controller specification.
0241          */
0242         if (!id)
0243             role = USB_ROLE_HOST;
0244         else if (vbus)
0245             role = USB_ROLE_DEVICE;
0246         break;
0247     case USB_ROLE_HOST: /* from HOST, we can only change to NONE */
0248         if (id)
0249             role = USB_ROLE_NONE;
0250         break;
0251     case USB_ROLE_DEVICE: /* from GADGET, we can only change to NONE*/
0252         if (!vbus)
0253             role = USB_ROLE_NONE;
0254         break;
0255     }
0256 
0257     dev_dbg(cdns->dev, "role %d -> %d\n", cdns->role, role);
0258 
0259     return role;
0260 }
0261 
0262 static int cdns_idle_role_start(struct cdns *cdns)
0263 {
0264     return 0;
0265 }
0266 
0267 static void cdns_idle_role_stop(struct cdns *cdns)
0268 {
0269     /* Program Lane swap and bring PHY out of RESET */
0270     phy_reset(cdns->usb3_phy);
0271 }
0272 
0273 static int cdns_idle_init(struct cdns *cdns)
0274 {
0275     struct cdns_role_driver *rdrv;
0276 
0277     rdrv = devm_kzalloc(cdns->dev, sizeof(*rdrv), GFP_KERNEL);
0278     if (!rdrv)
0279         return -ENOMEM;
0280 
0281     rdrv->start = cdns_idle_role_start;
0282     rdrv->stop = cdns_idle_role_stop;
0283     rdrv->state = CDNS_ROLE_STATE_INACTIVE;
0284     rdrv->suspend = NULL;
0285     rdrv->resume = NULL;
0286     rdrv->name = "idle";
0287 
0288     cdns->roles[USB_ROLE_NONE] = rdrv;
0289 
0290     return 0;
0291 }
0292 
0293 /**
0294  * cdns_hw_role_switch - switch roles based on HW state
0295  * @cdns: controller
0296  */
0297 int cdns_hw_role_switch(struct cdns *cdns)
0298 {
0299     enum usb_role real_role, current_role;
0300     int ret = 0;
0301 
0302     /* Depends on role switch class */
0303     if (cdns->role_sw)
0304         return 0;
0305 
0306     pm_runtime_get_sync(cdns->dev);
0307 
0308     current_role = cdns->role;
0309     real_role = cdns_hw_role_state_machine(cdns);
0310 
0311     /* Do nothing if nothing changed */
0312     if (current_role == real_role)
0313         goto exit;
0314 
0315     cdns_role_stop(cdns);
0316 
0317     dev_dbg(cdns->dev, "Switching role %d -> %d", current_role, real_role);
0318 
0319     ret = cdns_role_start(cdns, real_role);
0320     if (ret) {
0321         /* Back to current role */
0322         dev_err(cdns->dev, "set %d has failed, back to %d\n",
0323             real_role, current_role);
0324         ret = cdns_role_start(cdns, current_role);
0325         if (ret)
0326             dev_err(cdns->dev, "back to %d failed too\n",
0327                 current_role);
0328     }
0329 exit:
0330     pm_runtime_put_sync(cdns->dev);
0331     return ret;
0332 }
0333 
0334 /**
0335  * cdns_role_get - get current role of controller.
0336  *
0337  * @sw: pointer to USB role switch structure
0338  *
0339  * Returns role
0340  */
0341 static enum usb_role cdns_role_get(struct usb_role_switch *sw)
0342 {
0343     struct cdns *cdns = usb_role_switch_get_drvdata(sw);
0344 
0345     return cdns->role;
0346 }
0347 
0348 /**
0349  * cdns_role_set - set current role of controller.
0350  *
0351  * @sw: pointer to USB role switch structure
0352  * @role: the previous role
0353  * Handles below events:
0354  * - Role switch for dual-role devices
0355  * - USB_ROLE_GADGET <--> USB_ROLE_NONE for peripheral-only devices
0356  */
0357 static int cdns_role_set(struct usb_role_switch *sw, enum usb_role role)
0358 {
0359     struct cdns *cdns = usb_role_switch_get_drvdata(sw);
0360     int ret = 0;
0361 
0362     pm_runtime_get_sync(cdns->dev);
0363 
0364     if (cdns->role == role)
0365         goto pm_put;
0366 
0367     if (cdns->dr_mode == USB_DR_MODE_HOST) {
0368         switch (role) {
0369         case USB_ROLE_NONE:
0370         case USB_ROLE_HOST:
0371             break;
0372         default:
0373             goto pm_put;
0374         }
0375     }
0376 
0377     if (cdns->dr_mode == USB_DR_MODE_PERIPHERAL) {
0378         switch (role) {
0379         case USB_ROLE_NONE:
0380         case USB_ROLE_DEVICE:
0381             break;
0382         default:
0383             goto pm_put;
0384         }
0385     }
0386 
0387     cdns_role_stop(cdns);
0388     ret = cdns_role_start(cdns, role);
0389     if (ret)
0390         dev_err(cdns->dev, "set role %d has failed\n", role);
0391 
0392 pm_put:
0393     pm_runtime_put_sync(cdns->dev);
0394     return ret;
0395 }
0396 
0397 
0398 /**
0399  * cdns_wakeup_irq - interrupt handler for wakeup events
0400  * @irq: irq number for cdns3/cdnsp core device
0401  * @data: structure of cdns
0402  *
0403  * Returns IRQ_HANDLED or IRQ_NONE
0404  */
0405 static irqreturn_t cdns_wakeup_irq(int irq, void *data)
0406 {
0407     struct cdns *cdns = data;
0408 
0409     if (cdns->in_lpm) {
0410         disable_irq_nosync(irq);
0411         cdns->wakeup_pending = true;
0412         if ((cdns->role == USB_ROLE_HOST) && cdns->host_dev)
0413             pm_request_resume(&cdns->host_dev->dev);
0414 
0415         return IRQ_HANDLED;
0416     }
0417 
0418     return IRQ_NONE;
0419 }
0420 
0421 /**
0422  * cdns_init - probe for cdns3/cdnsp core device
0423  * @cdns: Pointer to cdns structure.
0424  *
0425  * Returns 0 on success otherwise negative errno
0426  */
0427 int cdns_init(struct cdns *cdns)
0428 {
0429     struct device *dev = cdns->dev;
0430     int ret;
0431 
0432     ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
0433     if (ret) {
0434         dev_err(dev, "error setting dma mask: %d\n", ret);
0435         return ret;
0436     }
0437 
0438     mutex_init(&cdns->mutex);
0439 
0440     if (device_property_read_bool(dev, "usb-role-switch")) {
0441         struct usb_role_switch_desc sw_desc = { };
0442 
0443         sw_desc.set = cdns_role_set;
0444         sw_desc.get = cdns_role_get;
0445         sw_desc.allow_userspace_control = true;
0446         sw_desc.driver_data = cdns;
0447         sw_desc.fwnode = dev->fwnode;
0448 
0449         cdns->role_sw = usb_role_switch_register(dev, &sw_desc);
0450         if (IS_ERR(cdns->role_sw)) {
0451             dev_warn(dev, "Unable to register Role Switch\n");
0452             return PTR_ERR(cdns->role_sw);
0453         }
0454     }
0455 
0456     if (cdns->wakeup_irq) {
0457         ret = devm_request_irq(cdns->dev, cdns->wakeup_irq,
0458                         cdns_wakeup_irq,
0459                         IRQF_SHARED,
0460                         dev_name(cdns->dev), cdns);
0461 
0462         if (ret) {
0463             dev_err(cdns->dev, "couldn't register wakeup irq handler\n");
0464             goto role_switch_unregister;
0465         }
0466     }
0467 
0468     ret = cdns_drd_init(cdns);
0469     if (ret)
0470         goto init_failed;
0471 
0472     ret = cdns_core_init_role(cdns);
0473     if (ret)
0474         goto init_failed;
0475 
0476     spin_lock_init(&cdns->lock);
0477 
0478     dev_dbg(dev, "Cadence USB3 core: probe succeed\n");
0479 
0480     return 0;
0481 init_failed:
0482     cdns_drd_exit(cdns);
0483 role_switch_unregister:
0484     if (cdns->role_sw)
0485         usb_role_switch_unregister(cdns->role_sw);
0486 
0487     return ret;
0488 }
0489 EXPORT_SYMBOL_GPL(cdns_init);
0490 
0491 /**
0492  * cdns_remove - unbind drd driver and clean up
0493  * @cdns: Pointer to cdns structure.
0494  *
0495  * Returns 0 on success otherwise negative errno
0496  */
0497 int cdns_remove(struct cdns *cdns)
0498 {
0499     cdns_exit_roles(cdns);
0500     usb_role_switch_unregister(cdns->role_sw);
0501 
0502     return 0;
0503 }
0504 EXPORT_SYMBOL_GPL(cdns_remove);
0505 
0506 #ifdef CONFIG_PM_SLEEP
0507 int cdns_suspend(struct cdns *cdns)
0508 {
0509     struct device *dev = cdns->dev;
0510     unsigned long flags;
0511 
0512     if (pm_runtime_status_suspended(dev))
0513         pm_runtime_resume(dev);
0514 
0515     if (cdns->roles[cdns->role]->suspend) {
0516         spin_lock_irqsave(&cdns->lock, flags);
0517         cdns->roles[cdns->role]->suspend(cdns, false);
0518         spin_unlock_irqrestore(&cdns->lock, flags);
0519     }
0520 
0521     return 0;
0522 }
0523 EXPORT_SYMBOL_GPL(cdns_suspend);
0524 
0525 int cdns_resume(struct cdns *cdns, u8 set_active)
0526 {
0527     struct device *dev = cdns->dev;
0528     enum usb_role real_role;
0529     bool role_changed = false;
0530     int ret = 0;
0531 
0532     if (cdns_power_is_lost(cdns)) {
0533         if (cdns->role_sw) {
0534             cdns->role = cdns_role_get(cdns->role_sw);
0535         } else {
0536             real_role = cdns_hw_role_state_machine(cdns);
0537             if (real_role != cdns->role) {
0538                 ret = cdns_hw_role_switch(cdns);
0539                 if (ret)
0540                     return ret;
0541                 role_changed = true;
0542             }
0543         }
0544 
0545         if (!role_changed) {
0546             if (cdns->role == USB_ROLE_HOST)
0547                 ret = cdns_drd_host_on(cdns);
0548             else if (cdns->role == USB_ROLE_DEVICE)
0549                 ret = cdns_drd_gadget_on(cdns);
0550 
0551             if (ret)
0552                 return ret;
0553         }
0554     }
0555 
0556     if (cdns->roles[cdns->role]->resume)
0557         cdns->roles[cdns->role]->resume(cdns, cdns_power_is_lost(cdns));
0558 
0559     if (set_active) {
0560         pm_runtime_disable(dev);
0561         pm_runtime_set_active(dev);
0562         pm_runtime_enable(dev);
0563     }
0564 
0565     return 0;
0566 }
0567 EXPORT_SYMBOL_GPL(cdns_resume);
0568 #endif /* CONFIG_PM_SLEEP */
0569 
0570 MODULE_AUTHOR("Peter Chen <peter.chen@nxp.com>");
0571 MODULE_AUTHOR("Pawel Laszczak <pawell@cadence.com>");
0572 MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
0573 MODULE_DESCRIPTION("Cadence USBSS and USBSSP DRD Driver");
0574 MODULE_LICENSE("GPL");