summaryrefslogtreecommitdiffstats
path: root/drivers/usb/imx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/imx')
-rw-r--r--drivers/usb/imx/Kconfig9
-rw-r--r--drivers/usb/imx/Makefile4
-rw-r--r--drivers/usb/imx/chipidea-imx.c154
-rw-r--r--drivers/usb/imx/imx-usb-misc.c60
-rw-r--r--drivers/usb/imx/imx-usb-phy.c62
5 files changed, 176 insertions, 113 deletions
diff --git a/drivers/usb/imx/Kconfig b/drivers/usb/imx/Kconfig
index 34f35e0ff6..2b9ae607bc 100644
--- a/drivers/usb/imx/Kconfig
+++ b/drivers/usb/imx/Kconfig
@@ -1,7 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
config USB_IMX_CHIPIDEA
bool "i.MX USB support (read help)"
- depends on ARCH_IMX
+ depends on ARCH_IMX || ARCH_MXS
select USB_OTGDEV
help
The Freescale i.MX SoCs have a variant of the chipidea ci13xxx for
@@ -15,8 +16,12 @@ config USB_IMX_CHIPIDEA
support to work.
It's safe to say yes here. Also select EHCI support for USB host.
+config USB_IMX_CHIPIDEA_USBMISC
+ bool
+ default y if ARCH_IMX
+
config USB_IMX_PHY
bool
- default y if (ARCH_IMX6 || ARCH_VF610) && GENERIC_PHY
+ default y if (ARCH_IMX6 || ARCH_VF610 || ARCH_MXS) && GENERIC_PHY
select STMP_DEVICE
select MFD_SYSCON
diff --git a/drivers/usb/imx/Makefile b/drivers/usb/imx/Makefile
index e15bc711a9..8a70fceb78 100644
--- a/drivers/usb/imx/Makefile
+++ b/drivers/usb/imx/Makefile
@@ -1,2 +1,4 @@
-obj-$(CONFIG_USB_IMX_CHIPIDEA) += imx-usb-misc.o chipidea-imx.o
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_USB_IMX_CHIPIDEA) += chipidea-imx.o
+obj-$(CONFIG_USB_IMX_CHIPIDEA_USBMISC) += imx-usb-misc.o
obj-$(CONFIG_USB_IMX_PHY) += imx-usb-phy.o
diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c
index 03301d9c3e..c5e6ce61e9 100644
--- a/drivers/usb/imx/chipidea-imx.c
+++ b/drivers/usb/imx/chipidea-imx.c
@@ -1,15 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
*/
#include <common.h>
@@ -18,27 +9,31 @@
#include <of.h>
#include <errno.h>
#include <driver.h>
-#include <usb/usb.h>
-#include <usb/ehci.h>
+#include <linux/usb/usb.h>
+#include <linux/usb/ehci.h>
#include <regulator.h>
-#include <usb/chipidea-imx.h>
-#include <usb/phy.h>
-#include <usb/ulpi.h>
-#include <usb/fsl_usb2.h>
+#include <linux/usb/chipidea-imx.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/ulpi.h>
+#include <linux/usb/fsl_usb2.h>
#include <linux/err.h>
#include <linux/phy/phy.h>
#include <linux/clk.h>
#define MXC_EHCI_PORTSC_MASK ((0xf << 28) | (1 << 25))
+struct imx_chipidea_data {
+ bool have_usb_misc;
+};
+
struct imx_chipidea {
- struct device_d *dev;
+ struct device *dev;
void __iomem *base;
struct ehci_data data;
unsigned long flags;
enum usb_dr_mode mode;
int portno;
- struct device_d *usbmisc;
+ struct device *usbmisc;
enum usb_phy_interface phymode;
struct param_d *param_mode;
struct regulator *vbus;
@@ -47,13 +42,14 @@ struct imx_chipidea {
struct clk *clk;
struct ehci_host *ehci;
struct fsl_udc *udc;
+ bool have_usb_misc;
};
static int imx_chipidea_port_init(void *drvdata)
{
struct imx_chipidea *ci = drvdata;
uint32_t portsc;
- int ret;
+ int ret = 0;
if ((ci->flags & MXC_EHCI_PORTSC_MASK) == MXC_EHCI_MODE_ULPI) {
dev_dbg(ci->dev, "using ULPI phy\n");
@@ -72,9 +68,11 @@ static int imx_chipidea_port_init(void *drvdata)
return ret;
}
- ret = imx_usbmisc_port_init(ci->usbmisc, ci->portno, ci->flags);
- if (ret)
- dev_err(ci->dev, "misc init failed: %s\n", strerror(-ret));
+ if (ci->have_usb_misc) {
+ ret = imx_usbmisc_port_init(ci->usbmisc, ci->portno, ci->flags);
+ if (ret)
+ dev_err(ci->dev, "misc init failed: %s\n", strerror(-ret));
+ }
/* PFSC bit is reset by ehci_reset(), thus have to set it not in
* probe but here, after ehci_reset() is already called */
@@ -90,11 +88,13 @@ static int imx_chipidea_port_init(void *drvdata)
static int imx_chipidea_port_post_init(void *drvdata)
{
struct imx_chipidea *ci = drvdata;
- int ret;
+ int ret = 0;
- ret = imx_usbmisc_port_post_init(ci->usbmisc, ci->portno, ci->flags);
- if (ret)
- dev_err(ci->dev, "post misc init failed: %s\n", strerror(-ret));
+ if (ci->have_usb_misc) {
+ ret = imx_usbmisc_port_post_init(ci->usbmisc, ci->portno, ci->flags);
+ if (ret)
+ dev_err(ci->dev, "post misc init failed: %s\n", strerror(-ret));
+ }
return ret;
}
@@ -103,18 +103,21 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci)
{
struct of_phandle_args out_args;
- if (of_parse_phandle_with_args(ci->dev->device_node, "fsl,usbmisc",
- "#index-cells", 0, &out_args))
- return -ENODEV;
+ if (ci->have_usb_misc) {
+ if (of_parse_phandle_with_args(ci->dev->of_node, "fsl,usbmisc",
+ "#index-cells", 0, &out_args))
+ return -ENODEV;
+
+ ci->usbmisc = of_find_device_by_node(out_args.np);
+ if (!ci->usbmisc)
+ return -ENODEV;
- ci->usbmisc = of_find_device_by_node(out_args.np);
- if (!ci->usbmisc)
- return -ENODEV;
+ ci->portno = out_args.args[0];
+ }
- ci->portno = out_args.args[0];
ci->flags = MXC_EHCI_MODE_UTMI_8BIT;
- ci->mode = of_usb_get_dr_mode(ci->dev->device_node, NULL);
+ ci->mode = of_usb_get_dr_mode(ci->dev->of_node, NULL);
if (ci->mode == USB_DR_MODE_UNKNOWN) {
/*
@@ -127,7 +130,7 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci)
ci->mode = USB_DR_MODE_HOST;
}
- ci->phymode = of_usb_get_phy_mode(ci->dev->device_node, NULL);
+ ci->phymode = of_usb_get_phy_mode(ci->dev->of_node, NULL);
switch (ci->phymode) {
case USBPHY_INTERFACE_MODE_UTMI:
ci->flags = MXC_EHCI_MODE_UTMI_8BIT;
@@ -148,28 +151,24 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci)
dev_dbg(ci->dev, "no phy_type setting. Relying on reset default\n");
}
- if (of_find_property(ci->dev->device_node,
+ if (of_find_property(ci->dev->of_node,
"disable-over-current", NULL))
ci->flags |= MXC_EHCI_DISABLE_OVERCURRENT;
- else if (!of_find_property(ci->dev->device_node,
+ else if (!of_find_property(ci->dev->of_node,
"over-current-active-high", NULL))
ci->flags |= MXC_EHCI_OC_PIN_ACTIVE_LOW;
- if (of_usb_get_maximum_speed(ci->dev->device_node, NULL) ==
+ if (of_find_property(ci->dev->of_node, "power-active-high", NULL))
+ ci->flags |= MXC_EHCI_PWR_PIN_ACTIVE_HIGH;
+
+ if (of_usb_get_maximum_speed(ci->dev->of_node, NULL) ==
USB_SPEED_FULL)
ci->flags |= MXC_EHCI_PFSC;
return 0;
}
-static int ci_ehci_detect(struct device_d *dev)
-{
- struct imx_chipidea *ci = dev->priv;
-
- return ehci_detect(ci->ehci);
-}
-
static int ci_set_mode(void *ctx, enum usb_dr_mode mode)
{
struct imx_chipidea *ci = ctx;
@@ -190,8 +189,6 @@ static int ci_set_mode(void *ctx, enum usb_dr_mode mode)
}
ci->ehci = ehci;
-
- ci->dev->detect = ci_ehci_detect;
} else {
dev_err(ci->dev, "Host support not available\n");
return -ENODEV;
@@ -216,10 +213,12 @@ static int ci_set_mode(void *ctx, enum usb_dr_mode mode)
return 0;
}
-static int imx_chipidea_probe(struct device_d *dev)
+static int imx_chipidea_probe(struct device *dev)
{
struct resource *iores;
+ struct imx_chipidea_data *imx_data;
struct imxusb_platformdata *pdata = dev->platform_data;
+ char const *phynode_name;
int ret;
void __iomem *base;
struct imx_chipidea *ci;
@@ -229,7 +228,11 @@ static int imx_chipidea_probe(struct device_d *dev)
ci->dev = dev;
dev->priv = ci;
- if (IS_ENABLED(CONFIG_OFDEVICE) && dev->device_node) {
+ ret = dev_get_drvdata(dev, (const void **)&imx_data);
+ if (!ret)
+ ci->have_usb_misc = imx_data->have_usb_misc;
+
+ if (IS_ENABLED(CONFIG_OFDEVICE) && dev->of_node) {
ret = imx_chipidea_probe_dt(ci);
if (ret)
return ret;
@@ -245,8 +248,11 @@ static int imx_chipidea_probe(struct device_d *dev)
}
ci->vbus = regulator_get(dev, "vbus");
- if (IS_ERR(ci->vbus))
+ if (IS_ERR(ci->vbus)) {
+ dev_warn(dev, "Cannot get vbus regulator: %pe (ignoring)\n",
+ ci->vbus);
ci->vbus = NULL;
+ }
/*
* Some devices have more than one clock, in this case they are enabled
@@ -254,15 +260,23 @@ static int imx_chipidea_probe(struct device_d *dev)
* devices which have only one.
*/
ci->clk = clk_get(dev, NULL);
- if (!IS_ERR(ci->clk))
- clk_enable(ci->clk);
- if (of_property_read_bool(dev->device_node, "fsl,usbphy")) {
- ci->phy = of_phy_get_by_phandle(dev, "fsl,usbphy", 0);
+ /* Device trees are using both "phys" and "fsl,usbphy". Prefer the
+ * more modern former one but fall back to the old one.
+ *
+ * Code should be removed when all devicetrees are using "phys" */
+ if (of_property_read_bool(dev->of_node, "phys"))
+ phynode_name = "phys";
+ else if (of_property_read_bool(dev->of_node, "fsl,usbphy"))
+ phynode_name = "fsl,usbphy";
+ else
+ phynode_name = NULL;
+
+ if (phynode_name) {
+ ci->phy = of_phy_get_by_phandle(dev, phynode_name, 0);
if (IS_ERR(ci->phy)) {
- ret = PTR_ERR(ci->phy);
- dev_err(dev, "Cannot get phy: %s\n", strerror(-ret));
- return ret;
+ dev_err(dev, "Cannot get phy: %pe\n", ci->phy);
+ return PTR_ERR(ci->phy);
} else {
ci->usbphy = phy_to_usbphy(ci->phy);
if (IS_ERR(ci->usbphy))
@@ -286,6 +300,14 @@ static int imx_chipidea_probe(struct device_d *dev)
ci->data.drvdata = ci;
ci->data.usbphy = ci->usbphy;
+ /*
+ * Enable the clock after we ensured that all resources are available.
+ * This is crucial since the phy can be missing which and so the
+ * usb-controller <-> usb-phy communication is only partly initialized.
+ * This can trigger strange system hangs at least on i.MX8M SoCs.
+ */
+ clk_enable(ci->clk);
+
if ((ci->flags & MXC_EHCI_PORTSC_MASK) == MXC_EHCI_MODE_HSIC)
imx_chipidea_port_init(ci);
@@ -308,7 +330,7 @@ static int imx_chipidea_probe(struct device_d *dev)
return ret;
};
-static void imx_chipidea_remove(struct device_d *dev)
+static void imx_chipidea_remove(struct device *dev)
{
struct imx_chipidea *ci = dev->priv;
@@ -319,17 +341,31 @@ static void imx_chipidea_remove(struct device_d *dev)
ci_udc_unregister(ci->udc);
}
+static const struct imx_chipidea_data imx_data = {
+ .have_usb_misc = 1,
+};
+
+static const struct imx_chipidea_data imx28_data = {
+ .have_usb_misc = 0,
+};
+
static __maybe_unused struct of_device_id imx_chipidea_dt_ids[] = {
{
.compatible = "fsl,imx27-usb",
+ .data = &imx_data,
+ }, {
+ .compatible = "fsl,imx28-usb",
+ .data = &imx28_data,
}, {
.compatible = "fsl,imx7d-usb",
+ .data = &imx_data,
}, {
/* sentinel */
},
};
+MODULE_DEVICE_TABLE(of, imx_chipidea_dt_ids);
-static struct driver_d imx_chipidea_driver = {
+static struct driver imx_chipidea_driver = {
.name = "imx-usb",
.probe = imx_chipidea_probe,
.of_compatible = DRV_OF_COMPAT(imx_chipidea_dt_ids),
diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c
index aa4485ccba..bf9583e626 100644
--- a/drivers/usb/imx/imx-usb-misc.c
+++ b/drivers/usb/imx/imx-usb-misc.c
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
* Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
*/
#include <common.h>
@@ -18,9 +9,9 @@
#include <io.h>
#include <of.h>
#include <errno.h>
-#include <usb/chipidea-imx.h>
-#include <mach/imx6-regs.h>
-#include <mach/iomux-mx6.h>
+#include <linux/usb/chipidea-imx.h>
+#include <mach/imx/imx6-regs.h>
+#include <mach/imx/iomux-mx6.h>
#define MX25_OTG_SIC_SHIFT 29
#define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT)
@@ -353,7 +344,8 @@ static __maybe_unused struct imx_usb_misc_data mx5_data = {
#define MX6_USB_CTRL(n) ((n) * 4)
#define MX6_USB_CTRL_OVER_CUR_DIS (1 << 7)
-#define MX6_USB_CTRL_OVER_CUR_ACT_HIGH (1 << 8)
+#define MX6_USB_CTRL_OVER_CUR_ACT_LOW (1 << 8)
+#define MX6_USB_CTRL_PWR_POLARITY (1 << 9)
static void mx6_hsic_pullup(unsigned long reg, int on)
{
@@ -378,8 +370,17 @@ static __maybe_unused int mx6_initialize_usb_hw(void __iomem *base, int port,
case 0:
case 1:
val = readl(base + MX6_USB_CTRL(port));
- if (flags & MXC_EHCI_DISABLE_OVERCURRENT)
+ if (flags & MXC_EHCI_DISABLE_OVERCURRENT) {
val |= MX6_USB_CTRL_OVER_CUR_DIS;
+ } else {
+ val &= ~MX6_USB_CTRL_OVER_CUR_DIS;
+ if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
+ val |= MX6_USB_CTRL_OVER_CUR_ACT_LOW;
+ else
+ val &= ~MX6_USB_CTRL_OVER_CUR_ACT_LOW;
+ }
+ if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+ val |= MX6_USB_CTRL_PWR_POLARITY;
writel(val, base + MX6_USB_CTRL(port));
break;
case 2: /* HSIC port */
@@ -450,10 +451,12 @@ static int usbmisc_imx7d_init(void __iomem *base, int port,
} else {
reg &= ~MX6_USB_CTRL_OVER_CUR_DIS;
if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
- reg &= ~MX6_USB_CTRL_OVER_CUR_ACT_HIGH;
+ reg |= MX6_USB_CTRL_OVER_CUR_ACT_LOW;
else
- reg |= MX6_USB_CTRL_OVER_CUR_ACT_HIGH;
+ reg &= ~MX6_USB_CTRL_OVER_CUR_ACT_LOW;
}
+ if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+ reg |= MX6_USB_CTRL_PWR_POLARITY;
writel(reg, base);
reg = readl(base + MX7D_USBNC_USB_CTRL2);
@@ -599,11 +602,15 @@ static __maybe_unused struct of_device_id imx_usbmisc_dt_ids[] = {
.data = &mx7_data,
},
#endif
-#ifdef CONFIG_ARCH_IMX8M
+#if defined CONFIG_ARCH_IMX8M || defined CONFIG_ARCH_IMX93
{
.compatible = "fsl,imx8mm-usbmisc",
.data = &mx7_data,
},
+ {
+ .compatible = "fsl,imx8mn-usbmisc",
+ .data = &mx7_data,
+ },
#endif
#ifdef CONFIG_ARCH_VF610
{
@@ -615,8 +622,9 @@ static __maybe_unused struct of_device_id imx_usbmisc_dt_ids[] = {
/* sentinel */
},
};
+MODULE_DEVICE_TABLE(of, imx_usbmisc_dt_ids);
-int imx_usbmisc_port_init(struct device_d *dev, int port, unsigned flags)
+int imx_usbmisc_port_init(struct device *dev, int port, unsigned flags)
{
struct imx_usb_misc_priv *usbmisc = dev->priv;
@@ -629,7 +637,7 @@ int imx_usbmisc_port_init(struct device_d *dev, int port, unsigned flags)
return usbmisc->data->init(usbmisc->base, port, flags);
}
-int imx_usbmisc_port_post_init(struct device_d *dev, int port, unsigned flags)
+int imx_usbmisc_port_post_init(struct device *dev, int port, unsigned flags)
{
struct imx_usb_misc_priv *usbmisc = dev->priv;
@@ -642,7 +650,7 @@ int imx_usbmisc_port_post_init(struct device_d *dev, int port, unsigned flags)
return usbmisc->data->post_init(usbmisc->base, port, flags);
}
-static int imx_usbmisc_probe(struct device_d *dev)
+static int imx_usbmisc_probe(struct device *dev)
{
struct resource *iores;
struct imx_usb_misc_data *devtype;
@@ -666,17 +674,11 @@ static int imx_usbmisc_probe(struct device_d *dev)
return 0;
}
-static struct driver_d imx_usbmisc_driver = {
+static struct driver imx_usbmisc_driver = {
.name = "imx-usbmisc",
.probe = imx_usbmisc_probe,
.id_table = imx_usbmisc_ids,
.of_compatible = DRV_OF_COMPAT(imx_usbmisc_dt_ids),
};
-static int imx_usbmisc_init(void)
-{
- platform_driver_register(&imx_usbmisc_driver);
- return 0;
-}
-
-coredevice_initcall(imx_usbmisc_init);
+coredevice_platform_driver(imx_usbmisc_driver);
diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c
index 069dddcacb..70bf292f80 100644
--- a/drivers/usb/imx/imx-usb-phy.c
+++ b/drivers/usb/imx/imx-usb-phy.c
@@ -1,15 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
*/
#include <common.h>
@@ -19,7 +10,7 @@
#include <errno.h>
#include <driver.h>
#include <malloc.h>
-#include <usb/phy.h>
+#include <linux/usb/phy.h>
#include <linux/phy/phy.h>
#include <linux/clk.h>
#include <linux/err.h>
@@ -37,9 +28,12 @@
#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1)
#define ANADIG_USB1_CHRG_DETECT_SET 0x1b4
-#define ANADIG_USB2_CHRG_DETECT_SET 0x214
#define ANADIG_USB1_CHRG_DETECT_EN_B BIT(20)
#define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B BIT(19)
+#define ANADIG_USB1_VBUS_DETECT_STAT 0x1c0
+#define ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID BIT(3)
+#define ANADIG_USB2_CHRG_DETECT_SET 0x214
+#define ANADIG_USB2_VBUS_DETECT_STAT 0x220
struct imx_usbphy {
struct usb_phy usb_phy;
@@ -49,6 +43,8 @@ struct imx_usbphy {
struct clk *clk;
struct phy_provider *provider;
int port_id;
+
+ unsigned int vbus_valid;
};
static int imx_usbphy_phy_init(struct phy *phy)
@@ -57,6 +53,7 @@ static int imx_usbphy_phy_init(struct phy *phy)
int ret;
clk_enable(imxphy->clk);
+ mdelay(1);
ret = stmp_reset_block(imxphy->base + HW_USBPHY_CTRL, false);
if (ret)
@@ -111,7 +108,7 @@ static int imx_usbphy_notify_disconnect(struct usb_phy *phy,
return 0;
}
-static struct phy *imx_usbphy_xlate(struct device_d *dev,
+static struct phy *imx_usbphy_xlate(struct device *dev,
struct of_phandle_args *args)
{
struct imx_usbphy *imxphy = dev->priv;
@@ -131,10 +128,25 @@ static const struct phy_ops imx_phy_ops = {
.to_usbphy = imx_usbphy_to_usbphy,
};
-static int imx_usbphy_probe(struct device_d *dev)
+static int imx_usbphy_get_vbus_state(struct param_d *p, void *priv)
+{
+ struct imx_usbphy *imxphy = priv;
+ unsigned int reg, val;
+
+ reg = imxphy->port_id ?
+ ANADIG_USB1_VBUS_DETECT_STAT :
+ ANADIG_USB2_VBUS_DETECT_STAT;
+ val = readl(imxphy->anatop + reg);
+
+ imxphy->vbus_valid = !!(val & ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID);
+
+ return 0;
+}
+
+static int imx_usbphy_probe(struct device *dev)
{
struct resource *iores;
- struct device_node *np = dev->device_node;
+ struct device_node *np = dev->of_node;
int ret;
struct imx_usbphy *imxphy;
@@ -153,6 +165,15 @@ static int imx_usbphy_probe(struct device_d *dev)
ret = PTR_ERR_OR_ZERO(imxphy->anatop);
if (ret)
goto err_free;
+
+ /*
+ * This is useful in case of usb-otg = device. In host case
+ * it isn't that useful since we are the supplier of the vbus
+ * signal.
+ */
+ dev_add_param_bool(dev, "vbus_valid", param_set_readonly,
+ imx_usbphy_get_vbus_state,
+ &imxphy->vbus_valid, imxphy);
}
iores = dev_request_mem_resource(dev, 0);
@@ -164,7 +185,7 @@ static int imx_usbphy_probe(struct device_d *dev)
imxphy->clk = clk_get(dev, NULL);
if (IS_ERR(imxphy->clk)) {
- dev_err(dev, "could not get clk: %s\n", strerrorp(imxphy->clk));
+ dev_err(dev, "could not get clk: %pe\n", imxphy->clk);
ret = PTR_ERR(imxphy->clk);
goto err_clk;
}
@@ -208,15 +229,12 @@ static __maybe_unused struct of_device_id imx_usbphy_dt_ids[] = {
/* sentinel */
},
};
+MODULE_DEVICE_TABLE(of, imx_usbphy_dt_ids);
-static struct driver_d imx_usbphy_driver = {
+static struct driver imx_usbphy_driver = {
.name = "imx-usb-phy",
.probe = imx_usbphy_probe,
.of_compatible = DRV_OF_COMPAT(imx_usbphy_dt_ids),
};
-static int imx_usbphy_init(void)
-{
- return platform_driver_register(&imx_usbphy_driver);
-}
-fs_initcall(imx_usbphy_init);
+fs_platform_driver(imx_usbphy_driver);