Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2014 Marvell Technology Group Ltd.
0004  *
0005  * Antoine Tenart <antoine.tenart@free-electrons.com>
0006  */
0007 
0008 #include <linux/clk.h>
0009 #include <linux/dma-mapping.h>
0010 #include <linux/module.h>
0011 #include <linux/of.h>
0012 #include <linux/of_platform.h>
0013 #include <linux/phy/phy.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/usb/chipidea.h>
0016 #include <linux/usb/hcd.h>
0017 #include <linux/usb/ulpi.h>
0018 
0019 #include "ci.h"
0020 
0021 struct ci_hdrc_usb2_priv {
0022     struct platform_device  *ci_pdev;
0023     struct clk      *clk;
0024 };
0025 
0026 static const struct ci_hdrc_platform_data ci_default_pdata = {
0027     .capoffset  = DEF_CAPOFFSET,
0028     .flags      = CI_HDRC_DISABLE_STREAMING,
0029 };
0030 
0031 static const struct ci_hdrc_platform_data ci_zynq_pdata = {
0032     .capoffset  = DEF_CAPOFFSET,
0033 };
0034 
0035 static const struct ci_hdrc_platform_data ci_zevio_pdata = {
0036     .capoffset  = DEF_CAPOFFSET,
0037     .flags      = CI_HDRC_REGS_SHARED | CI_HDRC_FORCE_FULLSPEED,
0038 };
0039 
0040 static const struct of_device_id ci_hdrc_usb2_of_match[] = {
0041     { .compatible = "chipidea,usb2" },
0042     { .compatible = "xlnx,zynq-usb-2.20a", .data = &ci_zynq_pdata },
0043     { .compatible = "lsi,zevio-usb", .data = &ci_zevio_pdata },
0044     { }
0045 };
0046 MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match);
0047 
0048 static int ci_hdrc_usb2_probe(struct platform_device *pdev)
0049 {
0050     struct device *dev = &pdev->dev;
0051     struct ci_hdrc_usb2_priv *priv;
0052     struct ci_hdrc_platform_data *ci_pdata = dev_get_platdata(dev);
0053     int ret;
0054     const struct of_device_id *match;
0055 
0056     if (!ci_pdata) {
0057         ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL);
0058         if (!ci_pdata)
0059             return -ENOMEM;
0060         *ci_pdata = ci_default_pdata;   /* struct copy */
0061     }
0062 
0063     match = of_match_device(ci_hdrc_usb2_of_match, &pdev->dev);
0064     if (match && match->data) {
0065         /* struct copy */
0066         *ci_pdata = *(struct ci_hdrc_platform_data *)match->data;
0067     }
0068 
0069     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0070     if (!priv)
0071         return -ENOMEM;
0072 
0073     priv->clk = devm_clk_get_optional(dev, NULL);
0074     if (IS_ERR(priv->clk))
0075         return PTR_ERR(priv->clk);
0076 
0077     ret = clk_prepare_enable(priv->clk);
0078     if (ret) {
0079         dev_err(dev, "failed to enable the clock: %d\n", ret);
0080         return ret;
0081     }
0082 
0083     ci_pdata->name = dev_name(dev);
0084 
0085     priv->ci_pdev = ci_hdrc_add_device(dev, pdev->resource,
0086                        pdev->num_resources, ci_pdata);
0087     if (IS_ERR(priv->ci_pdev)) {
0088         ret = PTR_ERR(priv->ci_pdev);
0089         if (ret != -EPROBE_DEFER)
0090             dev_err(dev,
0091                 "failed to register ci_hdrc platform device: %d\n",
0092                 ret);
0093         goto clk_err;
0094     }
0095 
0096     platform_set_drvdata(pdev, priv);
0097 
0098     pm_runtime_no_callbacks(dev);
0099     pm_runtime_enable(dev);
0100 
0101     return 0;
0102 
0103 clk_err:
0104     clk_disable_unprepare(priv->clk);
0105     return ret;
0106 }
0107 
0108 static int ci_hdrc_usb2_remove(struct platform_device *pdev)
0109 {
0110     struct ci_hdrc_usb2_priv *priv = platform_get_drvdata(pdev);
0111 
0112     pm_runtime_disable(&pdev->dev);
0113     ci_hdrc_remove_device(priv->ci_pdev);
0114     clk_disable_unprepare(priv->clk);
0115 
0116     return 0;
0117 }
0118 
0119 static struct platform_driver ci_hdrc_usb2_driver = {
0120     .probe  = ci_hdrc_usb2_probe,
0121     .remove = ci_hdrc_usb2_remove,
0122     .driver = {
0123         .name       = "chipidea-usb2",
0124         .of_match_table = of_match_ptr(ci_hdrc_usb2_of_match),
0125     },
0126 };
0127 module_platform_driver(ci_hdrc_usb2_driver);
0128 
0129 MODULE_DESCRIPTION("ChipIdea HDRC USB2 binding for ci13xxx");
0130 MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
0131 MODULE_LICENSE("GPL");