aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/chipidea/ci_hdrc_imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/chipidea/ci_hdrc_imx.c')
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c161
1 files changed, 63 insertions, 98 deletions
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 14362c00db3..2e58f8dfd31 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -19,70 +19,76 @@
#include <linux/dma-mapping.h>
#include <linux/usb/chipidea.h>
#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
#include "ci.h"
#include "ci_hdrc_imx.h"
-#define pdev_to_phy(pdev) \
- ((struct usb_phy *)platform_get_drvdata(pdev))
+#define CI_HDRC_IMX_IMX28_WRITE_FIX BIT(0)
+
+struct ci_hdrc_imx_platform_flag {
+ unsigned int flags;
+};
+
+static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
+};
+
+static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
+ .flags = CI_HDRC_IMX_IMX28_WRITE_FIX,
+};
+
+static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
+ { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
+ { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
struct ci_hdrc_imx_data {
struct usb_phy *phy;
struct platform_device *ci_pdev;
struct clk *clk;
- struct regulator *reg_vbus;
+ struct imx_usbmisc_data *usbmisc_data;
};
-static const struct usbmisc_ops *usbmisc_ops;
-
/* Common functions shared by usbmisc drivers */
-int usbmisc_set_ops(const struct usbmisc_ops *ops)
-{
- if (usbmisc_ops)
- return -EBUSY;
-
- usbmisc_ops = ops;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usbmisc_set_ops);
-
-void usbmisc_unset_ops(const struct usbmisc_ops *ops)
-{
- usbmisc_ops = NULL;
-}
-EXPORT_SYMBOL_GPL(usbmisc_unset_ops);
-
-int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev)
+static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
{
struct device_node *np = dev->of_node;
struct of_phandle_args args;
+ struct imx_usbmisc_data *data;
int ret;
- usbdev->dev = dev;
+ /*
+ * In case the fsl,usbmisc property is not present this device doesn't
+ * need usbmisc. Return NULL (which is no error here)
+ */
+ if (!of_get_property(np, "fsl,usbmisc", NULL))
+ return NULL;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return ERR_PTR(-ENOMEM);
ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells",
0, &args);
if (ret) {
dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n",
ret);
- memset(usbdev, 0, sizeof(*usbdev));
- return ret;
+ return ERR_PTR(ret);
}
- usbdev->index = args.args[0];
+
+ data->index = args.args[0];
of_node_put(args.np);
if (of_find_property(np, "disable-over-current", NULL))
- usbdev->disable_oc = 1;
+ data->disable_oc = 1;
if (of_find_property(np, "external-vbus-divider", NULL))
- usbdev->evdo = 1;
+ data->evdo = 1;
- return 0;
+ return data;
}
-EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
/* End of common functions shared by usbmisc drivers*/
@@ -90,18 +96,15 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
{
struct ci_hdrc_imx_data *data;
struct ci_hdrc_platform_data pdata = {
- .name = "ci_hdrc_imx",
+ .name = dev_name(&pdev->dev),
.capoffset = DEF_CAPOFFSET,
.flags = CI_HDRC_REQUIRE_TRANSCEIVER |
- CI_HDRC_PULLUP_ON_VBUS |
CI_HDRC_DISABLE_STREAMING,
};
- struct resource *res;
int ret;
-
- if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL)
- && !usbmisc_ops)
- return -EPROBE_DEFER;
+ const struct of_device_id *of_id =
+ of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
+ const struct ci_hdrc_imx_platform_flag *imx_platform_flag = of_id->data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
@@ -109,11 +112,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
return -ENOMEM;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "Can't get device resources!\n");
- return -ENOENT;
- }
+ data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
+ if (IS_ERR(data->usbmisc_data))
+ return PTR_ERR(data->usbmisc_data);
data->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(data->clk)) {
@@ -130,44 +131,26 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
}
data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
- if (!IS_ERR(data->phy)) {
- ret = usb_phy_init(data->phy);
- if (ret) {
- dev_err(&pdev->dev, "unable to init phy: %d\n", ret);
- goto err_clk;
- }
- } else if (PTR_ERR(data->phy) == -EPROBE_DEFER) {
- ret = -EPROBE_DEFER;
+ if (IS_ERR(data->phy)) {
+ ret = PTR_ERR(data->phy);
goto err_clk;
}
- /* we only support host now, so enable vbus here */
- data->reg_vbus = devm_regulator_get(&pdev->dev, "vbus");
- if (!IS_ERR(data->reg_vbus)) {
- ret = regulator_enable(data->reg_vbus);
- if (ret) {
- dev_err(&pdev->dev,
- "Failed to enable vbus regulator, err=%d\n",
- ret);
- goto err_clk;
- }
- } else {
- data->reg_vbus = NULL;
- }
-
pdata.phy = data->phy;
- if (!pdev->dev.dma_mask)
- pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
- if (!pdev->dev.coherent_dma_mask)
- pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ if (imx_platform_flag->flags & CI_HDRC_IMX_IMX28_WRITE_FIX)
+ pdata.flags |= CI_HDRC_IMX28_WRITE_FIX;
+
+ ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ goto err_clk;
- if (usbmisc_ops && usbmisc_ops->init) {
- ret = usbmisc_ops->init(&pdev->dev);
+ if (data->usbmisc_data) {
+ ret = imx_usbmisc_init(data->usbmisc_data);
if (ret) {
- dev_err(&pdev->dev,
- "usbmisc init failed, ret=%d\n", ret);
- goto err;
+ dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n",
+ ret);
+ goto err_clk;
}
}
@@ -179,14 +162,14 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"Can't register ci_hdrc platform device, err=%d\n",
ret);
- goto err;
+ goto err_clk;
}
- if (usbmisc_ops && usbmisc_ops->post) {
- ret = usbmisc_ops->post(&pdev->dev);
+ if (data->usbmisc_data) {
+ ret = imx_usbmisc_init_post(data->usbmisc_data);
if (ret) {
- dev_err(&pdev->dev,
- "usbmisc post failed, ret=%d\n", ret);
+ dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n",
+ ret);
goto disable_device;
}
}
@@ -200,9 +183,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
disable_device:
ci_hdrc_remove_device(data->ci_pdev);
-err:
- if (data->reg_vbus)
- regulator_disable(data->reg_vbus);
err_clk:
clk_disable_unprepare(data->clk);
return ret;
@@ -214,26 +194,11 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
ci_hdrc_remove_device(data->ci_pdev);
-
- if (data->reg_vbus)
- regulator_disable(data->reg_vbus);
-
- if (data->phy) {
- usb_phy_shutdown(data->phy);
- module_put(data->phy->dev->driver->owner);
- }
-
clk_disable_unprepare(data->clk);
return 0;
}
-static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
- { .compatible = "fsl,imx27-usb", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
-
static struct platform_driver ci_hdrc_imx_driver = {
.probe = ci_hdrc_imx_probe,
.remove = ci_hdrc_imx_remove,