usb: phy: mxs: Add platform judgement code
authorPeter Chen <peter.chen@freescale.com>
Mon, 24 Feb 2014 02:20:54 +0000 (10:20 +0800)
committerFelipe Balbi <balbi@ti.com>
Wed, 5 Mar 2014 20:40:06 +0000 (14:40 -0600)
The mxs-phy has several bugs and features at different
versions, the driver code can get it through of_device_id.data.

Signed-off-by: Peter Chen <peter.chen@freescale.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/phy/phy-mxs-usb.c

index b42897b6474c3347f11d2daebedf648a91bbd49a..cf58d8ec9901cd4c5f20348853a20eeb1dfa1210 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
  * Copyright (C) 2012 Marek Vasut <marex@denx.de>
  * on behalf of DENX Software Engineering GmbH
  *
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/of_device.h>
 
 #define DRIVER_NAME "mxs_phy"
 
 #define BM_USBPHY_CTRL_ENUTMILEVEL2            BIT(14)
 #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT      BIT(1)
 
+#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
+
+/* Do disconnection between PHY and controller without vbus */
+#define MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS   BIT(0)
+
+/*
+ * The PHY will be in messy if there is a wakeup after putting
+ * bus to suspend (set portsc.suspendM) but before setting PHY to low
+ * power mode (set portsc.phcd).
+ */
+#define MXS_PHY_ABNORMAL_IN_SUSPEND            BIT(1)
+
+/*
+ * The SOF sends too fast after resuming, it will cause disconnection
+ * between host and high speed device.
+ */
+#define MXS_PHY_SENDING_SOF_TOO_FAST           BIT(2)
+
+struct mxs_phy_data {
+       unsigned int flags;
+};
+
+static const struct mxs_phy_data imx23_phy_data = {
+       .flags = MXS_PHY_ABNORMAL_IN_SUSPEND | MXS_PHY_SENDING_SOF_TOO_FAST,
+};
+
+static const struct mxs_phy_data imx6q_phy_data = {
+       .flags = MXS_PHY_SENDING_SOF_TOO_FAST |
+               MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
+};
+
+static const struct mxs_phy_data imx6sl_phy_data = {
+       .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
+};
+
+static const struct of_device_id mxs_phy_dt_ids[] = {
+       { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
+       { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
+       { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
+
 struct mxs_phy {
        struct usb_phy phy;
        struct clk *clk;
+       const struct mxs_phy_data *data;
 };
 
-#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
-
 static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
 {
        int ret;
@@ -138,6 +181,8 @@ static int mxs_phy_probe(struct platform_device *pdev)
        struct clk *clk;
        struct mxs_phy *mxs_phy;
        int ret;
+       const struct of_device_id *of_id =
+                       of_match_device(mxs_phy_dt_ids, &pdev->dev);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        base = devm_ioremap_resource(&pdev->dev, res);
@@ -168,6 +213,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
        mxs_phy->phy.type               = USB_PHY_TYPE_USB2;
 
        mxs_phy->clk = clk;
+       mxs_phy->data = of_id->data;
 
        platform_set_drvdata(pdev, mxs_phy);
 
@@ -187,12 +233,6 @@ static int mxs_phy_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id mxs_phy_dt_ids[] = {
-       { .compatible = "fsl,imx23-usbphy", },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
-
 static struct platform_driver mxs_phy_driver = {
        .probe = mxs_phy_probe,
        .remove = mxs_phy_remove,