0001
0002
0003
0004
0005
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;
0061 }
0062
0063 match = of_match_device(ci_hdrc_usb2_of_match, &pdev->dev);
0064 if (match && match->data) {
0065
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");