/** * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg * driver * * @dev: Platform device * * This routine creates the driver components required to control the device * (core, HCD, and PCD) and initializes the device. The driver components are * stored in a dwc2_hsotg structure. A reference to the dwc2_hsotg is saved * in the device private data. This allows the driver to access the dwc2_hsotg * structure on subsequent calls to driver methods for this device. */ static int dwc2_driver_probe(struct platform_device *dev) { struct dwc2_hsotg *hsotg; struct resource *res; int retval; hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL); if (!hsotg) return -ENOMEM; hsotg->dev = &dev->dev; /* * Use reasonable defaults so platforms don't have to provide these. */ if (!dev->dev.dma_mask) dev->dev.dma_mask = &dev->dev.coherent_dma_mask; retval = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32)); if (retval) { dev_err(&dev->dev, "can't set coherent DMA mask: %d\n", retval); return retval; } res = platform_get_resource(dev, IORESOURCE_MEM, 0); hsotg->regs = devm_ioremap_resource(&dev->dev, res); if (IS_ERR(hsotg->regs)) return PTR_ERR(hsotg->regs); dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", (unsigned long)res->start, hsotg->regs); retval = dwc2_lowlevel_hw_init(hsotg); if (retval) return retval; spin_lock_init(&hsotg->lock); hsotg->irq = platform_get_irq(dev, 0); if (hsotg->irq < 0) { dev_err(&dev->dev, "missing IRQ resource\n"); return hsotg->irq; } dev_dbg(hsotg->dev, "registering common handler for irq%d\n", hsotg->irq); retval = devm_request_irq(hsotg->dev, hsotg->irq, dwc2_handle_common_intr, IRQF_SHARED, dev_name(hsotg->dev), hsotg); if (retval) return retval; hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus"); if (IS_ERR(hsotg->vbus_supply)) { retval = PTR_ERR(hsotg->vbus_supply); hsotg->vbus_supply = NULL; if (retval != -ENODEV) return retval; } retval = dwc2_lowlevel_hw_enable(hsotg); if (retval) return retval; hsotg->needs_byte_swap = dwc2_check_core_endianness(hsotg); retval = dwc2_get_dr_mode(hsotg); if (retval) goto error; /* * Reset before dwc2_get_hwparams() then it could get power-on real * reset value form registers. */ retval = dwc2_core_reset(hsotg, false); if (retval) goto error; /* Detect config values from hardware */ retval = dwc2_get_hwparams(hsotg); if (retval) goto error; /* * For OTG cores, set the force mode bits to reflect the value * of dr_mode. Force mode bits should not be touched at any * other time after this. */ dwc2_force_dr_mode(hsotg); retval = dwc2_init_params(hsotg); if (retval) goto error; if (hsotg->dr_mode != USB_DR_MODE_HOST) { retval = dwc2_gadget_init(hsotg); if (retval) goto error; hsotg->gadget_enabled = 1; } hsotg->reset_phy_on_wake = of_property_read_bool(dev->dev.of_node, "snps,reset-phy-on-wake"); if (hsotg->reset_phy_on_wake && !hsotg->phy) { dev_warn(hsotg->dev, "Quirk reset-phy-on-wake only supports generic PHYs\n"); hsotg->reset_phy_on_wake = false; } if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) { retval = dwc2_hcd_init(hsotg); if (retval) { if (hsotg->gadget_enabled) dwc2_hsotg_remove(hsotg); goto error; } hsotg->hcd_enabled = 1; } platform_set_drvdata(dev, hsotg); hsotg->hibernated = 0; dwc2_debugfs_init(hsotg); /* Gadget code manages lowlevel hw on its own */ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) dwc2_lowlevel_hw_disable(hsotg); return 0; error: dwc2_lowlevel_hw_disable(hsotg); return retval; }
/** * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg * driver * * @dev: Platform device * * This routine creates the driver components required to control the device * (core, HCD, and PCD) and initializes the device. The driver components are * stored in a dwc2_hsotg structure. A reference to the dwc2_hsotg is saved * in the device private data. This allows the driver to access the dwc2_hsotg * structure on subsequent calls to driver methods for this device. */ static int dwc2_driver_probe(struct platform_device *dev) { struct dwc2_hsotg *hsotg; struct resource *res; int retval; hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL); if (!hsotg) return -ENOMEM; hsotg->dev = &dev->dev; /* * Use reasonable defaults so platforms don't have to provide these. */ if (!dev->dev.dma_mask) dev->dev.dma_mask = &dev->dev.coherent_dma_mask; retval = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32)); if (retval) return retval; res = platform_get_resource(dev, IORESOURCE_MEM, 0); hsotg->regs = devm_ioremap_resource(&dev->dev, res); if (IS_ERR(hsotg->regs)) return PTR_ERR(hsotg->regs); dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", (unsigned long)res->start, hsotg->regs); retval = dwc2_lowlevel_hw_init(hsotg); if (retval) return retval; spin_lock_init(&hsotg->lock); hsotg->irq = platform_get_irq(dev, 0); if (hsotg->irq < 0) { dev_err(&dev->dev, "missing IRQ resource\n"); return hsotg->irq; } dev_dbg(hsotg->dev, "registering common handler for irq%d\n", hsotg->irq); retval = devm_request_irq(hsotg->dev, hsotg->irq, dwc2_handle_common_intr, IRQF_SHARED, dev_name(hsotg->dev), hsotg); if (retval) return retval; retval = dwc2_lowlevel_hw_enable(hsotg); if (retval) return retval; retval = dwc2_get_dr_mode(hsotg); if (retval) goto error; /* * Reset before dwc2_get_hwparams() then it could get power-on real * reset value form registers. */ dwc2_core_reset_and_force_dr_mode(hsotg); /* Detect config values from hardware */ retval = dwc2_get_hwparams(hsotg); if (retval) goto error; dwc2_force_dr_mode(hsotg); retval = dwc2_init_params(hsotg); if (retval) goto error; if (hsotg->dr_mode != USB_DR_MODE_HOST) { retval = dwc2_gadget_init(hsotg, hsotg->irq); if (retval) goto error; hsotg->gadget_enabled = 1; } if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) { retval = dwc2_hcd_init(hsotg); if (retval) { if (hsotg->gadget_enabled) dwc2_hsotg_remove(hsotg); goto error; } hsotg->hcd_enabled = 1; } platform_set_drvdata(dev, hsotg); dwc2_debugfs_init(hsotg); /* Gadget code manages lowlevel hw on its own */ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) dwc2_lowlevel_hw_disable(hsotg); return 0; error: dwc2_lowlevel_hw_disable(hsotg); return retval; }
/** * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg * driver * * @dev: Platform device * * This routine creates the driver components required to control the device * (core, HCD, and PCD) and initializes the device. The driver components are * stored in a dwc2_hsotg structure. A reference to the dwc2_hsotg is saved * in the device private data. This allows the driver to access the dwc2_hsotg * structure on subsequent calls to driver methods for this device. */ static int dwc2_driver_probe(struct platform_device *dev) { const struct of_device_id *match; const struct dwc2_core_params *params; struct dwc2_core_params defparams; struct dwc2_hsotg *hsotg; struct resource *res; int retval; int irq; match = of_match_device(dwc2_of_match_table, &dev->dev); if (match && match->data) { params = match->data; } else { /* Default all params to autodetect */ dwc2_set_all_params(&defparams, -1); params = &defparams; /* * Disable descriptor dma mode by default as the HW can support * it, but does not support it for SPLIT transactions. */ defparams.dma_desc_enable = 0; } hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL); if (!hsotg) return -ENOMEM; hsotg->dev = &dev->dev; /* * Use reasonable defaults so platforms don't have to provide these. */ if (!dev->dev.dma_mask) dev->dev.dma_mask = &dev->dev.coherent_dma_mask; retval = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32)); if (retval) return retval; irq = platform_get_irq(dev, 0); if (irq < 0) { dev_err(&dev->dev, "missing IRQ resource\n"); return irq; } dev_dbg(hsotg->dev, "registering common handler for irq%d\n", irq); retval = devm_request_irq(hsotg->dev, irq, dwc2_handle_common_intr, IRQF_SHARED, dev_name(hsotg->dev), hsotg); if (retval) return retval; res = platform_get_resource(dev, IORESOURCE_MEM, 0); hsotg->regs = devm_ioremap_resource(&dev->dev, res); if (IS_ERR(hsotg->regs)) return PTR_ERR(hsotg->regs); dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", (unsigned long)res->start, hsotg->regs); hsotg->dr_mode = usb_get_dr_mode(&dev->dev); if (IS_ENABLED(CONFIG_USB_DWC2_HOST) && hsotg->dr_mode != USB_DR_MODE_HOST) { hsotg->dr_mode = USB_DR_MODE_HOST; dev_warn(hsotg->dev, "Configuration mismatch. Forcing host mode\n"); } else if (IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) && hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) { hsotg->dr_mode = USB_DR_MODE_PERIPHERAL; dev_warn(hsotg->dev, "Configuration mismatch. Forcing peripheral mode\n"); } retval = dwc2_lowlevel_hw_init(hsotg); if (retval) return retval; spin_lock_init(&hsotg->lock); hsotg->core_params = devm_kzalloc(&dev->dev, sizeof(*hsotg->core_params), GFP_KERNEL); if (!hsotg->core_params) return -ENOMEM; dwc2_set_all_params(hsotg->core_params, -1); retval = dwc2_lowlevel_hw_enable(hsotg); if (retval) return retval; /* Detect config values from hardware */ retval = dwc2_get_hwparams(hsotg); if (retval) goto error; /* Validate parameter values */ dwc2_set_parameters(hsotg, params); if (hsotg->dr_mode != USB_DR_MODE_HOST) { retval = dwc2_gadget_init(hsotg, irq); if (retval) goto error; hsotg->gadget_enabled = 1; } if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) { retval = dwc2_hcd_init(hsotg, irq); if (retval) { if (hsotg->gadget_enabled) dwc2_hsotg_remove(hsotg); goto error; } hsotg->hcd_enabled = 1; } platform_set_drvdata(dev, hsotg); dwc2_debugfs_init(hsotg); /* Gadget code manages lowlevel hw on its own */ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) dwc2_lowlevel_hw_disable(hsotg); return 0; error: dwc2_lowlevel_hw_disable(hsotg); return retval; }