All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rob Herring <robh@kernel.org>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Alan Stern <stern@rowland.harvard.edu>,
	Kishon Vijay Abraham I <kishon@ti.com>
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	linux-usb@vger.kernel.org, Rob Herring <robh@kernel.org>
Subject: [PATCH 5/5] usb: add pxa1928 ehci support
Date: Wed, 13 May 2015 17:49:00 -0500	[thread overview]
Message-ID: <1431557340-5421-6-git-send-email-robh@kernel.org> (raw)
In-Reply-To: <1431557340-5421-1-git-send-email-robh@kernel.org>

Add platform driver for Marvell PXA1928 SOC. This is different from the
mv-ehci driver in that it uses the generic phy framework, uses DT, does
not use platform_data, is host only, and has a specific HSIC PHY and
controller initialization handshake.

Signed-off-by: Rob Herring <robh@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: linux-usb@vger.kernel.org
---
 drivers/usb/host/Kconfig      |  15 ++-
 drivers/usb/host/Makefile     |   1 +
 drivers/usb/host/ehci-mv-of.c | 243 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 258 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/host/ehci-mv-of.c

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 197a6a3..4d8cfbc 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -251,6 +251,19 @@ config USB_EHCI_MV
 	  Dova, Armada 370 and Armada XP. See "Support for Marvell EBU
 	  on-chip EHCI USB controller" for those.
 
+config USB_EHCI_MV_OF
+	bool "EHCI OF support for Marvell PXA/MMP USB controller"
+	depends on (ARCH_PXA || ARCH_MMP)
+	select USB_EHCI_ROOT_HUB_TT
+	---help---
+	  Enables support for Marvell (including PXA and MMP series) on-chip
+	  USB SPH and OTG controller. SPH is a single port host, and it can
+	  only be EHCI host. OTG is controller that can switch to host mode.
+	  Note that this driver will not work on Marvell's other EHCI
+	  controller used by the EBU-type SoCs including Orion, Kirkwood,
+	  Dova, Armada 370 and Armada XP. See "Support for Marvell EBU
+	  on-chip EHCI USB controller" for those.
+
 config USB_W90X900_EHCI
 	tristate "W90X900(W90P910) EHCI support"
 	depends on ARCH_W90X900
@@ -663,7 +676,7 @@ config USB_SL811_HCD
 	help
 	  The SL811HS is a single-port USB controller that supports either
 	  host side or peripheral side roles.  Enable this option if your
-	  board has this chip, and you want to use it as a host controller. 
+	  board has this chip, and you want to use it as a host controller.
 	  If unsure, say N.
 
 	  To compile this driver as a module, choose M here: the
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 65b0b6a..5ed93ff 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
 obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
 obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)	+= ehci-platform.o
+obj-$(CONFIG_USB_EHCI_MV_OF)	+= ehci-mv-of.o
 obj-$(CONFIG_USB_EHCI_MXC)	+= ehci-mxc.o
 obj-$(CONFIG_USB_EHCI_HCD_OMAP)	+= ehci-omap.o
 obj-$(CONFIG_USB_EHCI_HCD_ORION)	+= ehci-orion.o
diff --git a/drivers/usb/host/ehci-mv-of.c b/drivers/usb/host/ehci-mv-of.c
new file mode 100644
index 0000000..3783299
--- /dev/null
+++ b/drivers/usb/host/ehci-mv-of.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2015 Linaro, Ltd.
+ * Rob Herring <robh@kernel.org>
+ *
+ * Based on vendor driver modifications to ehci-mv.c:
+ * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
+ * Author: Chao Xie <chao.xie@marvell.com>
+ *        Neil Zhang <zhangwm@marvell.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/err.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
+
+struct ehci_hcd_mv {
+	struct usb_hcd *hcd;
+	struct phy *phy;
+	struct clk *clk;
+};
+
+#define hcd_to_mv_priv(h) ((struct ehci_hcd_mv *)hcd_to_ehci(h)->priv)
+
+static struct hc_driver ehci_mv_hc_driver;
+
+static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout)
+{
+	timeout += jiffies;
+	while (time_is_after_eq_jiffies(timeout)) {
+		if ((readl(reg) & mask) == mask)
+			return true;
+		msleep(1);
+	}
+	return false;
+}
+
+static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(ehci_mv->hcd);
+	struct ehci_regs *ehci_regs = ehci->regs;
+	int retval;
+	u32 status;
+
+	/* enable port power and reserved bit 25 */
+	status = __raw_readl(&ehci_regs->port_status[0]);
+	status |= (PORT_POWER) | (1 << 25);
+	/* Clear bits 30:31 for HSIC to be enabled */
+	status &= ~(0x3 << 30);
+	__raw_writel(status, &ehci_regs->port_status[0]);
+
+	/* test mode: force enable hs */
+	status = __raw_readl(&ehci_regs->port_status[0]);
+	status &= ~(0xf << 16);
+	status |= (0x5 << 16);
+	__raw_writel(status, &ehci_regs->port_status[0]);
+
+	/* disable test mode */
+	status = __raw_readl(&ehci_regs->port_status[0]);
+	status &= ~(0xf << 16);
+	__raw_writel(status, &ehci_regs->port_status[0]);
+
+	retval =  phy_power_on(ehci_mv->hcd->phy);
+	if (retval)
+		return retval;
+
+	/* issue port reset */
+	status = __raw_readl(&ehci_regs->port_status[0]);
+	status |= PORT_RESET;
+	status &= ~PORT_PE;
+	__raw_writel(status, &ehci_regs->port_status[0]);
+
+	/* check reset done */
+	if (!wait_for_reg(&ehci_regs->port_status[0], PORT_RESET, HZ / 10)) {
+		pr_err("HSIC port reset not done: port_status 0x%x\n", status);
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int mv_ehci_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct ehci_hcd *ehci;
+	struct ehci_hcd_mv *ehci_mv;
+	struct resource *r;
+	int retval = -ENODEV;
+
+	hcd = usb_create_hcd(&ehci_mv_hc_driver, &pdev->dev, "mv ehci");
+	if (!hcd)
+		return -ENOMEM;
+	ehci = hcd_to_ehci(hcd);
+	ehci_mv = hcd_to_mv_priv(hcd);
+	ehci_mv->hcd = hcd;
+
+	platform_set_drvdata(pdev, ehci_mv);
+
+	ehci_mv->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(ehci_mv->clk)) {
+		dev_err(&pdev->dev, "error getting clock\n");
+		retval = PTR_ERR(ehci_mv->clk);
+		goto err_put_hcd;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ehci->caps = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(ehci->caps)) {
+		retval = PTR_ERR(ehci->caps);
+		goto err_put_hcd;
+	}
+
+	hcd->phy = devm_of_phy_get(&pdev->dev, pdev->dev.of_node, NULL);
+	if (IS_ERR_OR_NULL(hcd->phy)) {
+		retval = PTR_ERR(hcd->phy);
+		if (retval != -EPROBE_DEFER && retval != -ENODEV)
+			dev_err(&pdev->dev, "failed to get the phy\n");
+		else
+			return -EPROBE_DEFER;
+		goto err_put_hcd;
+	}
+
+	hcd->rsrc_start = r->start;
+	hcd->rsrc_len = resource_size(r);
+
+	hcd->irq = platform_get_irq(pdev, 0);
+	if (!hcd->irq) {
+		dev_err(&pdev->dev, "Cannot get irq.");
+		retval = -ENODEV;
+		goto err_put_hcd;
+	}
+
+	retval = phy_init(hcd->phy);
+	if (retval)
+		goto err_put_hcd;
+
+	clk_prepare(ehci_mv->clk);
+	clk_enable(ehci_mv->clk);
+
+	retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+	if (retval) {
+		dev_err(&pdev->dev,
+			"failed to add hcd with err %d\n", retval);
+		goto err_disable_clk;
+	}
+
+	retval = mv_ehci_enable(ehci_mv);
+	if (retval) {
+		dev_err(&pdev->dev,
+			"EHCI: private init failed with err %d\n", retval);
+		goto err_disable_clk;
+	}
+
+	device_wakeup_enable(hcd->self.controller);
+
+	return 0;
+
+err_disable_clk:
+	clk_disable(ehci_mv->clk);
+	clk_unprepare(ehci_mv->clk);
+	phy_exit(hcd->phy);
+err_put_hcd:
+	usb_put_hcd(hcd);
+	return retval;
+}
+
+static int mv_ehci_remove(struct platform_device *pdev)
+{
+	struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_mv->hcd;
+
+	phy_power_off(hcd->phy);
+	phy_exit(hcd->phy);
+	clk_disable(ehci_mv->clk);
+	clk_unprepare(ehci_mv->clk);
+
+	usb_remove_hcd(hcd);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+static const struct of_device_id mv_ehci_dt_match[] = {
+	{.compatible = "marvell,pxa1928-ehci"},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mv_ehci_dt_match);
+
+static void mv_ehci_shutdown(struct platform_device *pdev)
+{
+	struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_mv->hcd;
+
+	if (!hcd->rh_registered)
+		return;
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+}
+
+static const struct ehci_driver_overrides ehci_mv_overrides __initconst = {
+	.extra_priv_size =	sizeof(struct ehci_hcd_mv),
+};
+
+static struct platform_driver ehci_mv_driver = {
+	.probe = mv_ehci_probe,
+	.remove = mv_ehci_remove,
+	.shutdown = mv_ehci_shutdown,
+	.driver = {
+		   .name = "mv-ehci-of",
+		   .of_match_table = of_match_ptr(mv_ehci_dt_match),
+		   },
+};
+
+static int __init ehci_mv_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	ehci_init_driver(&ehci_mv_hc_driver, &ehci_mv_overrides);
+	return platform_driver_register(&ehci_mv_driver);
+}
+module_init(ehci_mv_init);
+
+static void __exit ehci_mv_cleanup(void)
+{
+	platform_driver_unregister(&ehci_mv_driver);
+}
+module_exit(ehci_mv_cleanup);
+
+MODULE_AUTHOR("Rob Herring <robh@kernel.org>");
+MODULE_LICENSE("GPL v2");
-- 
2.1.0

  parent reply	other threads:[~2015-05-13 22:49 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-13 22:48 [PATCH 0/5] Marvell PXA1928 USB support Rob Herring
2015-05-13 22:48 ` Rob Herring
2015-05-13 22:48 ` [PATCH 2/5] dt-bindings: Add Marvell PXA1928 USB EHCI controller binding Rob Herring
2015-05-13 22:48 ` [PATCH 4/5] phy: add Marvell HSIC 28nm PHY Rob Herring
2015-05-21 12:45   ` Kishon Vijay Abraham I
2015-05-21 12:45     ` Kishon Vijay Abraham I
2015-05-21 12:51     ` Kishon Vijay Abraham I
2015-05-21 12:51       ` Kishon Vijay Abraham I
     [not found]       ` <555DD4C2.80406-l0cyMroinI0@public.gmane.org>
2015-05-22 19:54         ` Rob Herring
2015-05-22 19:54           ` Rob Herring
2015-05-26  6:06           ` Kishon Vijay Abraham I
2015-05-13 22:49 ` Rob Herring [this message]
2015-05-14  8:24   ` [PATCH 5/5] usb: add pxa1928 ehci support Paul Bolle
2015-05-14 10:42     ` Arnd Bergmann
2015-05-14 13:25       ` Rob Herring
2015-05-14 13:25         ` Rob Herring
2015-05-14 10:43   ` Arnd Bergmann
     [not found]   ` <1431557340-5421-6-git-send-email-robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2015-05-14 14:56     ` Alan Stern
2015-05-14 14:56       ` Alan Stern
     [not found]       ` <Pine.LNX.4.44L0.1505141025280.1582-100000-IYeN2dnnYyZXsRXLowluHWD2FQJk+8+b@public.gmane.org>
2015-05-14 16:36         ` Rob Herring
2015-05-14 16:36           ` Rob Herring
     [not found]           ` <CAL_JsqLq0x47O4gSs_vnfNkaUsE9bp9M9W5SV0c7vJ6X6b5cdA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-05-14 17:06             ` Alan Stern
2015-05-14 17:06               ` Alan Stern
2015-05-14 15:55   ` Alan Stern
2015-05-14 15:55     ` Alan Stern
2015-05-15  9:32     ` Arnd Bergmann
     [not found] ` <1431557340-5421-1-git-send-email-robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2015-05-13 22:48   ` [PATCH 1/5] dt-bindings: Add Marvell PXA1928 USB and HSIC PHY bindings Rob Herring
2015-05-13 22:48     ` Rob Herring
2015-05-13 22:48   ` [PATCH 3/5] phy: Add Marvell USB 2.0 OTG 28nm PHY Rob Herring
2015-05-13 22:48     ` Rob Herring
     [not found]     ` <1431557340-5421-4-git-send-email-robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2015-05-21 12:33       ` Kishon Vijay Abraham I
2015-05-21 12:33         ` Kishon Vijay Abraham I
2015-05-15  9:55   ` [PATCH 0/5] Marvell PXA1928 USB support Sebastian Hesselbarth
2015-05-15  9:55     ` Sebastian Hesselbarth
     [not found]     ` <5555C2A5.8010509-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-05-15 12:48       ` Rob Herring
2015-05-15 12:48         ` Rob Herring
2015-05-15 14:11         ` Arnd Bergmann
2015-05-15 16:04           ` Rob Herring
2015-05-15 16:04             ` Rob Herring

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=1431557340-5421-6-git-send-email-robh@kernel.org \
    --to=robh@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=kishon@ti.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=stern@rowland.harvard.edu \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.