static int omap_usb2_probe()

in ti/phy-omap-usb2.c [365:507]


static int omap_usb2_probe(struct platform_device *pdev)
{
	struct omap_usb	*phy;
	struct phy *generic_phy;
	struct phy_provider *phy_provider;
	struct usb_otg *otg;
	struct device_node *node = pdev->dev.of_node;
	struct device_node *control_node;
	struct platform_device *control_pdev;
	const struct of_device_id *of_id;
	struct usb_phy_data *phy_data;

	of_id = of_match_device(omap_usb2_id_table, &pdev->dev);

	if (!of_id)
		return -EINVAL;

	phy_data = (struct usb_phy_data *)of_id->data;

	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
	if (!phy)
		return -ENOMEM;

	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
	if (!otg)
		return -ENOMEM;

	phy->dev		= &pdev->dev;

	phy->phy.dev		= phy->dev;
	phy->phy.label		= phy_data->label;
	phy->phy.otg		= otg;
	phy->phy.type		= USB_PHY_TYPE_USB2;
	phy->mask		= phy_data->mask;
	phy->power_on		= phy_data->power_on;
	phy->power_off		= phy_data->power_off;
	phy->flags		= phy_data->flags;

	omap_usb2_init_errata(phy);

	phy->phy_base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(phy->phy_base))
		return PTR_ERR(phy->phy_base);

	phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node,
								"syscon-phy-power");
	if (IS_ERR(phy->syscon_phy_power)) {
		dev_dbg(&pdev->dev,
			"can't get syscon-phy-power, using control device\n");
		phy->syscon_phy_power = NULL;

		control_node = of_parse_phandle(node, "ctrl-module", 0);
		if (!control_node) {
			dev_err(&pdev->dev,
				"Failed to get control device phandle\n");
			return -EINVAL;
		}

		control_pdev = of_find_device_by_node(control_node);
		if (!control_pdev) {
			dev_err(&pdev->dev, "Failed to get control device\n");
			return -EINVAL;
		}
		phy->control_dev = &control_pdev->dev;
	} else {
		if (of_property_read_u32_index(node,
					       "syscon-phy-power", 1,
					       &phy->power_reg)) {
			dev_err(&pdev->dev,
				"couldn't get power reg. offset\n");
			return -EINVAL;
		}
	}

	phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
	if (IS_ERR(phy->wkupclk)) {
		if (PTR_ERR(phy->wkupclk) == -EPROBE_DEFER)
			return -EPROBE_DEFER;

		dev_warn(&pdev->dev, "unable to get wkupclk %ld, trying old name\n",
			 PTR_ERR(phy->wkupclk));
		phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");

		if (IS_ERR(phy->wkupclk)) {
			if (PTR_ERR(phy->wkupclk) != -EPROBE_DEFER)
				dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
			return PTR_ERR(phy->wkupclk);
		}

		dev_warn(&pdev->dev,
			 "found usb_phy_cm_clk32k, please fix DTS\n");
	}

	phy->optclk = devm_clk_get(phy->dev, "refclk");
	if (IS_ERR(phy->optclk)) {
		if (PTR_ERR(phy->optclk) == -EPROBE_DEFER)
			return -EPROBE_DEFER;

		dev_dbg(&pdev->dev, "unable to get refclk, trying old name\n");
		phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");

		if (IS_ERR(phy->optclk)) {
			if (PTR_ERR(phy->optclk) != -EPROBE_DEFER) {
				dev_dbg(&pdev->dev,
					"unable to get usb_otg_ss_refclk960m\n");
			}
		} else {
			dev_warn(&pdev->dev,
				 "found usb_otg_ss_refclk960m, please fix DTS\n");
		}
	}

	otg->set_host = omap_usb_set_host;
	otg->set_peripheral = omap_usb_set_peripheral;
	if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
		otg->set_vbus = omap_usb_set_vbus;
	if (phy_data->flags & OMAP_USB2_HAS_START_SRP)
		otg->start_srp = omap_usb_start_srp;
	otg->usb_phy = &phy->phy;

	platform_set_drvdata(pdev, phy);
	pm_runtime_enable(phy->dev);

	generic_phy = devm_phy_create(phy->dev, NULL, &ops);
	if (IS_ERR(generic_phy)) {
		pm_runtime_disable(phy->dev);
		return PTR_ERR(generic_phy);
	}

	phy_set_drvdata(generic_phy, phy);
	omap_usb_power_off(generic_phy);

	phy_provider = devm_of_phy_provider_register(phy->dev,
						     of_phy_simple_xlate);
	if (IS_ERR(phy_provider)) {
		pm_runtime_disable(phy->dev);
		return PTR_ERR(phy_provider);
	}

	usb_add_phy_dev(&phy->phy);

	return 0;
}