コード例 #1
0
ファイル: msm72k_otg.c プロジェクト: ANFS/ANFS-kernel
static int __init msm_otg_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct resource *res;
	struct msm_otg *motg;
	struct otg_transceiver *otg;

	dev_info(&pdev->dev, "msm_otg probe\n");
	if (!pdev->dev.platform_data) {
		dev_err(&pdev->dev, "No platform data given. Bailing out\n");
		return -ENODEV;
	}

	motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
	if (!motg) {
		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
		return -ENOMEM;
	}

	motg->pdata = pdev->dev.platform_data;
	otg = &motg->otg;
	otg->dev = &pdev->dev;

	motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
	if (IS_ERR(motg->phy_reset_clk)) {
		dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
		ret = PTR_ERR(motg->phy_reset_clk);
		goto free_motg;
	}

	motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
	if (IS_ERR(motg->clk)) {
		dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
		ret = PTR_ERR(motg->clk);
		goto put_phy_reset_clk;
	}

	motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
	if (IS_ERR(motg->pclk)) {
		dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
		ret = PTR_ERR(motg->pclk);
		goto put_clk;
	}

	/*
	 * USB core clock is not present on all MSM chips. This
	 * clock is introduced to remove the dependency on AXI
	 * bus frequency.
	 */
	motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
	if (IS_ERR(motg->core_clk))
		motg->core_clk = NULL;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "failed to get platform resource mem\n");
		ret = -ENODEV;
		goto put_core_clk;
	}

	motg->regs = ioremap(res->start, resource_size(res));
	if (!motg->regs) {
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto put_core_clk;
	}
	dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);

	motg->irq = platform_get_irq(pdev, 0);
	if (!motg->irq) {
		dev_err(&pdev->dev, "platform_get_irq failed\n");
		ret = -ENODEV;
		goto free_regs;
	}

	clk_enable(motg->clk);
	clk_enable(motg->pclk);
	if (motg->core_clk)
		clk_enable(motg->core_clk);

	writel(0, USB_USBINTR);
	writel(0, USB_OTGSC);

	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
	ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
					"msm_otg", motg);
	if (ret) {
		dev_err(&pdev->dev, "request irq failed\n");
		goto disable_clks;
	}

	otg->init = msm_otg_reset;
	otg->set_host = msm_otg_set_host;
	otg->set_peripheral = msm_otg_set_peripheral;

	otg->io_ops = &msm_otg_io_ops;

	ret = otg_set_transceiver(&motg->otg);
	if (ret) {
		dev_err(&pdev->dev, "otg_set_transceiver failed\n");
		goto free_irq;
	}

	platform_set_drvdata(pdev, motg);
	device_init_wakeup(&pdev->dev, 1);

	if (motg->pdata->mode == USB_OTG &&
			motg->pdata->otg_control == OTG_USER_CONTROL) {
		ret = msm_otg_debugfs_init(motg);
		if (ret)
			dev_dbg(&pdev->dev, "mode debugfs file is"
					"not available\n");
	}

	pm_runtime_set_active(&pdev->dev);
	pm_runtime_enable(&pdev->dev);

	return 0;
free_irq:
	free_irq(motg->irq, motg);
disable_clks:
	clk_disable(motg->pclk);
	clk_disable(motg->clk);
free_regs:
	iounmap(motg->regs);
put_core_clk:
	if (motg->core_clk)
		clk_put(motg->core_clk);
	clk_put(motg->pclk);
put_clk:
	clk_put(motg->clk);
put_phy_reset_clk:
	clk_put(motg->phy_reset_clk);
free_motg:
	kfree(motg);
	return ret;
}
コード例 #2
0
static int msm_otg_probe(struct platform_device *pdev)
{
	struct regulator_bulk_data regs[3];
	int ret = 0;
	struct device_node *np = pdev->dev.of_node;
	struct msm_otg_platform_data *pdata;
	struct resource *res;
	struct msm_otg *motg;
	struct usb_phy *phy;
	void __iomem *phy_select;

	motg = devm_kzalloc(&pdev->dev, sizeof(struct msm_otg), GFP_KERNEL);
	if (!motg) {
		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
		return -ENOMEM;
	}

	pdata = dev_get_platdata(&pdev->dev);
	if (!pdata) {
		if (!np)
			return -ENXIO;
		ret = msm_otg_read_dt(pdev, motg);
		if (ret)
			return ret;
	}

	motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
				     GFP_KERNEL);
	if (!motg->phy.otg) {
		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
		return -ENOMEM;
	}

	phy = &motg->phy;
	phy->dev = &pdev->dev;

	motg->phy_reset_clk = devm_clk_get(&pdev->dev,
					   np ? "phy" : "usb_phy_clk");
	if (IS_ERR(motg->phy_reset_clk)) {
		dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
		motg->phy_reset_clk = NULL;
	}

	motg->clk = devm_clk_get(&pdev->dev, np ? "core" : "usb_hs_clk");
	if (IS_ERR(motg->clk)) {
		dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
		return PTR_ERR(motg->clk);
	}

	/*
	 * If USB Core is running its protocol engine based on CORE CLK,
	 * CORE CLK  must be running at >55Mhz for correct HSUSB
	 * operation and USB core cannot tolerate frequency changes on
	 * CORE CLK.
	 */
	motg->pclk = devm_clk_get(&pdev->dev, np ? "iface" : "usb_hs_pclk");
	if (IS_ERR(motg->pclk)) {
		dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
		return PTR_ERR(motg->pclk);
	}

	/*
	 * USB core clock is not present on all MSM chips. This
	 * clock is introduced to remove the dependency on AXI
	 * bus frequency.
	 */
	motg->core_clk = devm_clk_get(&pdev->dev,
				      np ? "alt_core" : "usb_hs_core_clk");

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -EINVAL;
	motg->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
	if (!motg->regs)
		return -ENOMEM;

	/*
	 * NOTE: The PHYs can be multiplexed between the chipidea controller
	 * and the dwc3 controller, using a single bit. It is important that
	 * the dwc3 driver does not set this bit in an incompatible way.
	 */
	if (motg->phy_number) {
		phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4);
		if (!phy_select)
			return -ENOMEM;
		/* Enable second PHY with the OTG port */
		writel(0x1, phy_select);
	}

	dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);

	motg->irq = platform_get_irq(pdev, 0);
	if (motg->irq < 0) {
		dev_err(&pdev->dev, "platform_get_irq failed\n");
		return motg->irq;
	}

	regs[0].supply = "vddcx";
	regs[1].supply = "v3p3";
	regs[2].supply = "v1p8";

	ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(regs), regs);
	if (ret)
		return ret;

	motg->vddcx = regs[0].consumer;
	motg->v3p3  = regs[1].consumer;
	motg->v1p8  = regs[2].consumer;

	clk_set_rate(motg->clk, 60000000);

	clk_prepare_enable(motg->clk);
	clk_prepare_enable(motg->pclk);

	if (!IS_ERR(motg->core_clk))
		clk_prepare_enable(motg->core_clk);

	ret = msm_hsusb_init_vddcx(motg, 1);
	if (ret) {
		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
		goto disable_clks;
	}

	ret = msm_hsusb_ldo_init(motg, 1);
	if (ret) {
		dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
		goto disable_vddcx;
	}
	ret = msm_hsusb_ldo_set_mode(motg, 1);
	if (ret) {
		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
		goto disable_ldo;
	}

	writel(0, USB_USBINTR);
	writel(0, USB_OTGSC);

	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
	INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
	ret = devm_request_irq(&pdev->dev, motg->irq, msm_otg_irq, IRQF_SHARED,
					"msm_otg", motg);
	if (ret) {
		dev_err(&pdev->dev, "request irq failed\n");
		goto disable_ldo;
	}

	phy->init = msm_phy_init;
	phy->set_power = msm_otg_set_power;
	phy->notify_disconnect = msm_phy_notify_disconnect;
	phy->type = USB_PHY_TYPE_USB2;

	phy->io_ops = &msm_otg_io_ops;

	phy->otg->phy = &motg->phy;
	phy->otg->set_host = msm_otg_set_host;
	phy->otg->set_peripheral = msm_otg_set_peripheral;

	msm_usb_reset(phy);

	ret = usb_add_phy_dev(&motg->phy);
	if (ret) {
		dev_err(&pdev->dev, "usb_add_phy failed\n");
		goto disable_ldo;
	}

	platform_set_drvdata(pdev, motg);
	device_init_wakeup(&pdev->dev, 1);

	if (motg->pdata->mode == USB_DR_MODE_OTG &&
		motg->pdata->otg_control == OTG_USER_CONTROL) {
		ret = msm_otg_debugfs_init(motg);
		if (ret)
			dev_dbg(&pdev->dev, "Can not create mode change file\n");
	}

	pm_runtime_set_active(&pdev->dev);
	pm_runtime_enable(&pdev->dev);

	return 0;

disable_ldo:
	msm_hsusb_ldo_init(motg, 0);
disable_vddcx:
	msm_hsusb_init_vddcx(motg, 0);
disable_clks:
	clk_disable_unprepare(motg->pclk);
	clk_disable_unprepare(motg->clk);
	if (!IS_ERR(motg->core_clk))
		clk_disable_unprepare(motg->core_clk);
	return ret;
}
コード例 #3
0
static int __init msm_otg_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct resource *res;
	struct msm_otg *dev;
	struct msm_otg_platform_data *pdata;

	dev = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
	if (!dev)
		return -ENOMEM;

	dev->otg.dev = &pdev->dev;

	if (pdev->dev.platform_data) {
		pdata = pdev->dev.platform_data;
		dev->rpc_connect = pdata->rpc_connect;
		dev->phy_reset = pdata->phy_reset;
	}

	if (dev->rpc_connect) {
		ret = dev->rpc_connect(1);
		pr_info("%s: rpc_connect(%d)\n", __func__, ret);
		if (ret) {
			pr_err("%s: rpc connect failed\n", __func__);
			ret = -ENODEV;
			goto free_dev;
		}
	}

	dev->clk = clk_get(&pdev->dev, "usb_hs_clk");
	if (IS_ERR(dev->clk)) {
		pr_err("%s: failed to get usb_hs_clk\n", __func__);
		ret = PTR_ERR(dev->clk);
		goto rpc_fail;
	}
	dev->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
	if (IS_ERR(dev->clk)) {
		pr_err("%s: failed to get usb_hs_pclk\n", __func__);
		ret = PTR_ERR(dev->pclk);
		goto put_clk;
	}
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		pr_err("%s: failed to get platform resource mem\n", __func__);
		ret = -ENODEV;
		goto put_pclk;
	}

	dev->regs = ioremap(res->start, resource_size(res));
	if (!dev->regs) {
		pr_err("%s: ioremap failed\n", __func__);
		ret = -ENOMEM;
		goto put_pclk;
	}
	dev->irq = platform_get_irq(pdev, 0);
	if (!dev->irq) {
		pr_err("%s: platform_get_irq failed\n", __func__);
		ret = -ENODEV;
		goto free_regs;
	}

	/* enable clocks */
	clk_enable(dev->clk);
	clk_enable(dev->pclk);

	otg_reset(dev);

	ret = request_irq(dev->irq, msm_otg_irq, IRQF_SHARED,
					"msm_otg", dev);
	if (ret) {
		pr_info("%s: request irq failed\n", __func__);
		clk_disable(dev->clk);
		clk_disable(dev->pclk);
		goto free_regs;
	}

	the_msm_otg = dev;
	dev->otg.set_peripheral = msm_otg_set_peripheral;
	dev->otg.set_host = msm_otg_set_host;
	dev->otg.set_suspend = msm_otg_set_suspend;
	if (otg_set_transceiver(&dev->otg)) {
		WARN_ON(1);
		goto free_regs;
	}

	wake_lock_init(&dev->wlock,
			WAKE_LOCK_SUSPEND, "usb_bus_active");
	wake_lock(&dev->wlock);
	msm_otg_debugfs_init(dev);
	device_init_wakeup(&pdev->dev, 1);

	return 0;
free_regs:
	iounmap(dev->regs);
put_pclk:
	clk_put(dev->pclk);
put_clk:
	clk_put(dev->clk);
rpc_fail:
	dev->rpc_connect(0);
free_dev:
	kfree(dev);
	return ret;
}