示例#1
0
int dwc2_init_params(struct dwc2_hsotg *hsotg)
{
	const struct of_device_id *match;
	struct dwc2_core_params params;

	match = of_match_device(dwc2_of_match_table, hsotg->dev);
	if (match && match->data)
		params = *((struct dwc2_core_params *)match->data);
	else
		params = params_default;

	if (dwc2_is_fs_iot(hsotg)) {
		params.speed = DWC2_SPEED_PARAM_FULL;
		params.phy_type = DWC2_PHY_TYPE_PARAM_FS;
	}

	dwc2_set_parameters(hsotg, &params);

	return 0;
}
示例#2
0
文件: platform.c 项目: hewking/linux
/**
 * 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;
}