From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
To: Felipe Balbi <balbi@ti.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
David Cohen <david.a.cohen@linux.intel.com>,
Stephen Boyd <sboyd@codeaurora.org>,
Baolu Lu <baolu.lu@linux.intel.com>,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCHv2 10/12] usb: dwc3: add ULPI interface support
Date: Wed, 18 Mar 2015 14:40:31 +0200 [thread overview]
Message-ID: <1426682433-133813-11-git-send-email-heikki.krogerus@linux.intel.com> (raw)
In-Reply-To: <1426682433-133813-1-git-send-email-heikki.krogerus@linux.intel.com>
Registers DWC3's ULPI interface with the ULPI bus when it's
available.
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
drivers/usb/dwc3/Kconfig | 7 ++++
drivers/usb/dwc3/Makefile | 4 +++
drivers/usb/dwc3/core.c | 14 ++++++++
drivers/usb/dwc3/core.h | 14 ++++++++
drivers/usb/dwc3/ulpi.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 130 insertions(+)
create mode 100644 drivers/usb/dwc3/ulpi.c
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 827c4f8..324bed7 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -11,6 +11,13 @@ config USB_DWC3
if USB_DWC3
+config USB_DWC3_ULPI
+ bool "Register ULPI PHY Interface"
+ depends on USB_ULPI_BUS=y
+ help
+ Select this if you have ULPI type PHY attached to your DWC3
+ controller.
+
choice
bool "DWC3 Mode Selection"
default USB_DWC3_DUAL_ROLE if (USB && USB_GADGET)
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 46172f4..c7076e3 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -15,6 +15,10 @@ ifneq ($(filter y,$(CONFIG_USB_DWC3_GADGET) $(CONFIG_USB_DWC3_DUAL_ROLE)),)
dwc3-y += gadget.o ep0.o
endif
+ifneq ($(CONFIG_USB_DWC3_ULPI),)
+ dwc3-y += ulpi.o
+endif
+
ifneq ($(CONFIG_DEBUG_FS),)
dwc3-y += debugfs.o
endif
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index b229ba1..4dce614 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -444,13 +444,25 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI:
if (!strncmp(dwc->hsphy_interface, "utmi", 4)) {
reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI;
+ break;
} else if (!strncmp(dwc->hsphy_interface, "ulpi", 4)) {
reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
} else {
dev_err(dwc->dev, "HSPHY Interface not defined\n");
return -EINVAL;
}
/* FALLTHROUGH */
+ case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
+ /* Soft reset here to sync the clocks */
+ ret = dwc3_soft_reset(dwc);
+ if (ret)
+ return ret;
+
+ ret = dwc3_ulpi_init(dwc);
+ if (ret)
+ return ret;
+ /* FALLTHROUGH */
default:
break;
}
@@ -999,6 +1011,7 @@ err2:
err1:
dwc3_free_event_buffers(dwc);
+ dwc3_ulpi_exit(dwc);
err0:
/*
@@ -1034,6 +1047,7 @@ static int dwc3_remove(struct platform_device *pdev)
phy_power_off(dwc->usb3_generic_phy);
dwc3_core_exit(dwc);
+ dwc3_ulpi_exit(dwc);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 7b3ab64..d70da20 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -30,6 +30,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
+#include <linux/ulpi/interface.h>
#include <linux/phy/phy.h>
@@ -661,6 +662,7 @@ struct dwc3_scratchpad_array {
* @usb3_phy: pointer to USB3 PHY
* @usb2_generic_phy: pointer to USB2 PHY
* @usb3_generic_phy: pointer to USB3 PHY
+ * @ulpi: pointer to ulpi interface
* @dcfg: saved contents of DCFG register
* @gctl: saved contents of GCTL register
* @isoch_delay: wValue from Set Isochronous Delay request;
@@ -749,6 +751,8 @@ struct dwc3 {
struct phy *usb2_generic_phy;
struct phy *usb3_generic_phy;
+ struct ulpi *ulpi;
+
void __iomem *regs;
size_t regs_size;
@@ -1047,4 +1051,14 @@ static inline int dwc3_gadget_resume(struct dwc3 *dwc)
}
#endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */
+#if IS_ENABLED(CONFIG_USB_DWC3_ULPI)
+int dwc3_ulpi_init(struct dwc3 *dwc);
+void dwc3_ulpi_exit(struct dwc3 *dwc);
+#else
+static inline int dwc3_ulpi_init(struct dwc3 *dwc)
+{ return 0; }
+static inline void dwc3_ulpi_exit(struct dwc3 *dwc)
+{ }
+#endif
+
#endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/ulpi.c b/drivers/usb/dwc3/ulpi.c
new file mode 100644
index 0000000..4dfcc81
--- /dev/null
+++ b/drivers/usb/dwc3/ulpi.c
@@ -0,0 +1,91 @@
+/**
+ * ulpi.c - DesignWare USB3 Controller's ULPI PHY interface
+ *
+ * Copyright (C) 2015 Intel Corporation
+ *
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/ulpi/regs.h>
+
+#include "core.h"
+#include "io.h"
+
+#define DWC3_ULPI_ADDR(a) \
+ ((a >= ULPI_EXT_VENDOR_SPECIFIC) ? \
+ DWC3_GUSB2PHYACC_ADDR(ULPI_ACCESS_EXTENDED) | \
+ DWC3_GUSB2PHYACC_EXTEND_ADDR(a) : DWC3_GUSB2PHYACC_ADDR(a))
+
+static int dwc3_ulpi_busyloop(struct dwc3 *dwc)
+{
+ unsigned count = 1000;
+ u32 reg;
+
+ while (count--) {
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
+ if (!(reg & DWC3_GUSB2PHYACC_BUSY))
+ return 0;
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int dwc3_ulpi_read(struct ulpi_ops *ops, u8 addr)
+{
+ struct dwc3 *dwc = dev_get_drvdata(ops->dev);
+ u32 reg;
+ int ret;
+
+ reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
+
+ ret = dwc3_ulpi_busyloop(dwc);
+ if (ret)
+ return ret;
+
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
+
+ return DWC3_GUSB2PHYACC_DATA(reg);
+}
+
+static int dwc3_ulpi_write(struct ulpi_ops *ops, u8 addr, u8 val)
+{
+ struct dwc3 *dwc = dev_get_drvdata(ops->dev);
+ u32 reg;
+
+ reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
+ reg |= DWC3_GUSB2PHYACC_WRITE | val;
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
+
+ return dwc3_ulpi_busyloop(dwc);
+}
+
+static struct ulpi_ops dwc3_ulpi = {
+ .read = dwc3_ulpi_read,
+ .write = dwc3_ulpi_write,
+};
+
+int dwc3_ulpi_init(struct dwc3 *dwc)
+{
+ /* Register the interface */
+ dwc->ulpi = ulpi_register_interface(dwc->dev, &dwc3_ulpi);
+ if (IS_ERR(dwc->ulpi)) {
+ dev_err(dwc->dev, "failed to register ULPI interface");
+ return PTR_ERR(dwc->ulpi);
+ }
+
+ return 0;
+}
+
+void dwc3_ulpi_exit(struct dwc3 *dwc)
+{
+ if (dwc->ulpi) {
+ ulpi_unregister_interface(dwc->ulpi);
+ dwc->ulpi = NULL;
+ }
+}
--
2.1.4
next prev parent reply other threads:[~2015-03-18 12:43 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-18 12:40 [PATCHv2 00/12] usb: ulpi bus Heikki Krogerus
2015-03-18 12:40 ` [PATCHv2 01/12] usb: add bus type for USB ULPI Heikki Krogerus
2015-03-18 23:26 ` Paul Bolle
2015-03-19 11:44 ` Heikki Krogerus
2015-03-20 12:20 ` [PATCHv3 " Heikki Krogerus
2015-03-26 14:02 ` [PATCHv4 " Heikki Krogerus
2015-03-23 7:16 ` [PATCHv2 " Lu, Baolu
2015-03-23 10:57 ` Heikki Krogerus
2015-03-18 12:40 ` [PATCHv2 02/12] usb: dwc3: USB2 PHY register access bits Heikki Krogerus
2015-03-18 12:40 ` [PATCHv2 03/12] usb: dwc3: ULPI or UTMI+ select Heikki Krogerus
2015-03-18 12:40 ` [PATCHv2 04/12] usb: dwc3: store driver data earlier Heikki Krogerus
2015-03-18 12:40 ` [PATCHv2 05/12] usb: dwc3: cache hwparams earlier Heikki Krogerus
2015-03-18 12:40 ` [PATCHv2 06/12] usb: dwc3: soft reset to it's own function Heikki Krogerus
2015-03-18 12:40 ` [PATCHv2 07/12] usb: dwc3: setup phys earlier Heikki Krogerus
2015-03-18 12:40 ` [PATCHv2 08/12] usb: dwc3: add hsphy_interface property Heikki Krogerus
2015-03-18 12:40 ` [PATCHv2 09/12] usb: dwc3: pci: add quirk for Baytrails Heikki Krogerus
2015-03-18 17:08 ` David Cohen
2015-03-19 11:51 ` Heikki Krogerus
2015-03-20 12:20 ` [PATCHv3 " Heikki Krogerus
2015-03-18 12:40 ` Heikki Krogerus [this message]
2015-03-18 22:53 ` [PATCHv2 10/12] usb: dwc3: add ULPI interface support Paul Bolle
2015-03-19 11:48 ` Heikki Krogerus
2015-03-20 12:20 ` [PATCHv3 " Heikki Krogerus
2015-03-18 12:40 ` [PATCHv2 11/12] phy: helpers for USB ULPI PHY registering Heikki Krogerus
2015-03-18 14:46 ` Sergei Shtylyov
2015-03-18 16:54 ` David Cohen
2015-03-18 18:02 ` Sergei Shtylyov
2015-03-18 12:40 ` [PATCHv2 12/12] phy: add driver for TI TUSB1210 ULPI PHY Heikki Krogerus
2015-03-18 17:12 ` [PATCHv2 00/12] usb: ulpi bus David Cohen
2015-03-18 17:19 ` David Cohen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1426682433-133813-11-git-send-email-heikki.krogerus@linux.intel.com \
--to=heikki.krogerus@linux.intel.com \
--cc=balbi@ti.com \
--cc=baolu.lu@linux.intel.com \
--cc=david.a.cohen@linux.intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=sboyd@codeaurora.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).