2014-04-18 10:23:26

by Gregory CLEMENT

[permalink] [raw]
Subject: [PATCH 0/8] USB3 support for Armada 38x

Hello,

This patch set adds the USB3 support for the Armada 38x and also
prepares the support for Armada 375. These SoCs use an xHCI but still
need specific initialization, mainly to setup the windows memory on
the mbus.

The first patch extend the the xhci-plat driver to allow to register
platform specific functions.

The second patch use it to setup the windows memory on the mbus for
Armada 38x.

Then the 3rd patch update he binding documentation.

This first 3 patches should go through the xhci subsystem, I really
would like to have a feedback on the 1st patch from the USB
maintainers.

The rest of the series is more platform specific and should go through
the mvebu tree, except the last patch that should be taken directly by
the arm-soc maintainer.

The support for Armada 375 is coming soon.

Thanks,

Gregory

Gregory CLEMENT (8):
usb: host: xhci-plat: Allow to register glue code using the device
tree
usb: host: xhci-plat: Add support for the Armada 38x glue code
xhci-platform: Add a new controller using xhci: Armada 38x
ARM: mvebu: Add USB3 UTMI support
ARM: mvebu: Add Device Tree description of xHCI hosts on Armada 38x
ARM: mvebu: Add USB3 support for Armada 38x
ARM: configs: Add usb_xhci_mvebu to mvebu_v7_defconfig
ARM: configs: Add usb_xhci_mvebu to multi_v7_defconfig

Documentation/devicetree/bindings/usb/usb-xhci.txt | 3 +-
arch/arm/boot/dts/armada-385-db.dts | 8 ++
arch/arm/boot/dts/armada-385-rd.dts | 4 +
arch/arm/boot/dts/armada-38x.dtsi | 17 ++++
arch/arm/configs/multi_v7_defconfig | 1 +
arch/arm/configs/mvebu_v7_defconfig | 1 +
arch/arm/mach-mvebu/Kconfig | 1 +
arch/arm/mach-mvebu/Makefile | 2 +-
arch/arm/mach-mvebu/usb-utmi.c | 64 +++++++++++++
drivers/usb/host/Kconfig | 7 ++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/xhci-mvebu.c | 105 +++++++++++++++++++++
drivers/usb/host/xhci-mvebu.h | 21 +++++
drivers/usb/host/xhci-plat.c | 82 +++++++++++++++-
drivers/usb/host/xhci.h | 4 +
15 files changed, 315 insertions(+), 6 deletions(-)
create mode 100644 arch/arm/mach-mvebu/usb-utmi.c
create mode 100644 drivers/usb/host/xhci-mvebu.c
create mode 100644 drivers/usb/host/xhci-mvebu.h

--
1.8.1.2


2014-04-18 10:23:54

by Gregory CLEMENT

[permalink] [raw]
Subject: [PATCH 8/8] ARM: configs: Add usb_xhci_mvebu to multi_v7_defconfig

The Marvell Armada 38x platform needs the xhci_mvebu driver enabled
for the xHCI USB hosts, so this commit enables the corresponding
Kconfig option in multi_v7_defconfig.

Signed-off-by: Gregory CLEMENT <[email protected]>
---
arch/arm/configs/multi_v7_defconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index d4e8a47a2f7c..820cc35d40cf 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -254,6 +254,7 @@ CONFIG_SND_SOC_TEGRA_ALC5632=y
CONFIG_SND_SOC_TEGRA_MAX98090=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_MVEBU=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_TEGRA=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
--
1.8.1.2

2014-04-18 10:23:49

by Gregory CLEMENT

[permalink] [raw]
Subject: [PATCH 7/8] ARM: configs: Add usb_xhci_mvebu to mvebu_v7_defconfig

The Marvell Armada 38x platform needs the xhci_mvebu driver enabled
for the xHCI USB hosts, so this commit enables the corresponding
Kconfig option in mvebu_v7_defconfig.

Signed-off-by: Gregory CLEMENT <[email protected]>
---
arch/arm/configs/mvebu_v7_defconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/mvebu_v7_defconfig b/arch/arm/configs/mvebu_v7_defconfig
index a34713d8db9f..e8811066b8e4 100644
--- a/arch/arm/configs/mvebu_v7_defconfig
+++ b/arch/arm/configs/mvebu_v7_defconfig
@@ -78,6 +78,7 @@ CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_STORAGE=y
CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_MVEBU=y
CONFIG_MMC=y
CONFIG_MMC_MVSDIO=y
CONFIG_NEW_LEDS=y
--
1.8.1.2

2014-04-18 10:23:43

by Gregory CLEMENT

[permalink] [raw]
Subject: [PATCH 6/8] ARM: mvebu: Add USB3 support for Armada 38x

This patch add the selection of the config symbol to build the USB3
support for Armada 38x.

Signed-off-by: Gregory CLEMENT <[email protected]>
---
arch/arm/mach-mvebu/Kconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 3f73eecbcfb0..7960f218702b 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -54,6 +54,7 @@ config MACH_ARMADA_38X
select CPU_V7
select MACH_MVEBU_V7
select PINCTRL_ARMADA_38X
+ select USB_ARCH_HAS_XHCI
help
Say 'Y' here if you want your kernel to support boards based
on the Marvell Armada 380/385 SoC with device tree.
--
1.8.1.2

2014-04-18 10:23:39

by Gregory CLEMENT

[permalink] [raw]
Subject: [PATCH 5/8] ARM: mvebu: Add Device Tree description of xHCI hosts on Armada 38x

The Marvell Armada 38x SoCs contain two xHCI host. This commit adds
the Device Tree description of those interfaces at the SoC level, and
also enables the two USB3 ports on the Armada 385 DB platform and one
USB3 port on the Armada 385 RD platforms.

Signed-off-by: Gregory CLEMENT <[email protected]>
---
arch/arm/boot/dts/armada-385-db.dts | 8 ++++++++
arch/arm/boot/dts/armada-385-rd.dts | 4 ++++
arch/arm/boot/dts/armada-38x.dtsi | 17 +++++++++++++++++
3 files changed, 29 insertions(+)

diff --git a/arch/arm/boot/dts/armada-385-db.dts b/arch/arm/boot/dts/armada-385-db.dts
index 6828d77696a6..d5db1466da82 100644
--- a/arch/arm/boot/dts/armada-385-db.dts
+++ b/arch/arm/boot/dts/armada-385-db.dts
@@ -101,6 +101,14 @@
reg = <0x1000000 0x3f000000>;
};
};
+
+ usb3@f0000 {
+ status = "okay";
+ };
+
+ usb3@f8000 {
+ status = "okay";
+ };
};

pcie-controller {
diff --git a/arch/arm/boot/dts/armada-385-rd.dts b/arch/arm/boot/dts/armada-385-rd.dts
index 45250c88814b..a505fe94ff37 100644
--- a/arch/arm/boot/dts/armada-385-rd.dts
+++ b/arch/arm/boot/dts/armada-385-rd.dts
@@ -77,6 +77,10 @@
reg = <1>;
};
};
+
+ usb3@f0000 {
+ status = "okay";
+ };
};

pcie-controller {
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
index a064f59da02d..4f117e66aa1a 100644
--- a/arch/arm/boot/dts/armada-38x.dtsi
+++ b/arch/arm/boot/dts/armada-38x.dtsi
@@ -355,6 +355,23 @@
clocks = <&coredivclk 0>;
status = "disabled";
};
+
+ usb3@f0000 {
+ compatible = "marvell,xhci-armada-380";
+ reg = <0xf0000 0x3fff>,<0xf4000 0x3fff>;
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gateclk 9>;
+ status = "disabled";
+ };
+
+ usb3@f8000 {
+ compatible = "marvell,xhci-armada-380";
+ reg = <0xf8000 0x3fff>,<0xfc000 0x3fff>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gateclk 10>;
+ status = "disabled";
+ };
+
};
};

--
1.8.1.2

2014-04-18 10:23:35

by Gregory CLEMENT

[permalink] [raw]
Subject: [PATCH 2/8] usb: host: xhci-plat: Add support for the Armada 38x glue code

For the armada 38x SoCs which come with an xhci controller, specific
initialization must be done during probe, especially in relation with
the MBus windows initialization. This patch adds this support.

Signed-off-by: Gregory CLEMENT <[email protected]>
---
drivers/usb/host/Kconfig | 7 +++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/xhci-mvebu.c | 105 ++++++++++++++++++++++++++++++++++++++++++
drivers/usb/host/xhci-mvebu.h | 21 +++++++++
drivers/usb/host/xhci-plat.c | 10 ++++
5 files changed, 144 insertions(+)
create mode 100644 drivers/usb/host/xhci-mvebu.c
create mode 100644 drivers/usb/host/xhci-mvebu.h

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3d9e54062d62..e70943fac4a1 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -29,6 +29,13 @@ if USB_XHCI_HCD
config USB_XHCI_PLATFORM
tristate

+config USB_XHCI_MVEBU
+ tristate "xHCI support for Marvell Armada 38x"
+ select USB_XHCI_PLATFORM
+ ---help---
+ Say 'Y' to enable the support for the xHCI host controller
+ found in Marvell Armada 38x ARM SOCs.
+
endif # USB_XHCI_HCD

config USB_EHCI_HCD
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 7530468c9a4f..7a8db7f7dc01 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -19,6 +19,7 @@ xhci-hcd-$(CONFIG_PCI) += xhci-pci.o

ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
xhci-hcd-y += xhci-plat.o
+ xhci-hcd-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
endif

obj-$(CONFIG_USB_WHCI_HCD) += whci/
diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
new file mode 100644
index 000000000000..dc9c7648ab65
--- /dev/null
+++ b/drivers/usb/host/xhci-mvebu.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 Marvell
+ * Author: Gregory CLEMENT <[email protected]>
+ *
+ * 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/clk.h>
+#include <linux/io.h>
+#include <linux/mbus.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "xhci.h"
+
+#define USB3_MAX_WINDOWS 4
+#define USB3_WIN_CTRL(w) (0x0 + ((w) * 8))
+#define USB3_WIN_BASE(w) (0x4 + ((w) * 8))
+
+static void __init mv_usb3_conf_mbus_windows(void __iomem *base,
+ const struct mbus_dram_target_info *dram)
+{
+ int win;
+
+ /* Clear all existing windows */
+ for (win = 0; win < USB3_MAX_WINDOWS; win++) {
+ writel(0, base + USB3_WIN_CTRL(win));
+ writel(0, base + USB3_WIN_BASE(win));
+ }
+
+ /* Program each DRAM CS in a seperate window */
+ for (win = 0; win < dram->num_cs; win++) {
+ const struct mbus_dram_window *cs = dram->cs + win;
+
+ writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) |
+ (dram->mbus_dram_target_id << 4) | 1,
+ base + USB3_WIN_CTRL(win));
+
+ writel((cs->base & 0xffff0000), base + USB3_WIN_BASE(win));
+ }
+}
+
+int xhci_mvebu_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ void __iomem *base;
+ const struct mbus_dram_target_info *dram;
+ int ret;
+ struct clk *clk;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -ENODEV;
+
+ /*
+ * We don't use devm_ioremap() because this mapping should
+ * only exists for the duration of this probe function.
+ */
+ base = ioremap(res->start, resource_size(res));
+ if (!base)
+ return -ENODEV;
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ iounmap(base);
+ return PTR_ERR(clk);
+ }
+
+ ret = clk_prepare_enable(clk);
+ if (ret < 0) {
+ iounmap(base);
+ return ret;
+ }
+
+ dram = mv_mbus_dram_info();
+ mv_usb3_conf_mbus_windows(base, dram);
+
+ /*
+ * This memory area was only needed to configure the MBus
+ * windows, and is therefore no longer useful.
+ */
+ iounmap(base);
+
+ ret = common_xhci_plat_probe(pdev, clk);
+ if (ret < 0) {
+ clk_disable_unprepare(clk);
+ return ret;
+ }
+
+ return ret;
+}
+
+int xhci_mvebu_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct clk *clk = xhci->priv;
+
+ common_xhci_plat_remove(pdev);
+ clk_disable_unprepare(clk);
+
+ return 0;
+}
diff --git a/drivers/usb/host/xhci-mvebu.h b/drivers/usb/host/xhci-mvebu.h
new file mode 100644
index 000000000000..897ef298f22f
--- /dev/null
+++ b/drivers/usb/host/xhci-mvebu.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory Clement <[email protected]>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __LINUX_XHCI_MVEBU_H
+#define __LINUX_XHCI_MVEBU_H
+
+#ifdef CONFIG_USB_XHCI_MVEBU
+int xhci_mvebu_probe(struct platform_device *pdev);
+int xhci_mvebu_remove(struct platform_device *pdev);
+#else
+#define xhci_mvebu_probe NULL
+#define xhci_mvebu_remove NULL
+#endif
+#endif /* __LINUX_XHCI_MVEBU_H */
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 8029cc82edc4..f1261d3848a9 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -19,6 +19,7 @@
#include <linux/of_device.h>

#include "xhci.h"
+#include "xhci-mvebu.h"

static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
{
@@ -250,6 +251,11 @@ static const struct dev_pm_ops xhci_plat_pm_ops = {
#endif /* CONFIG_PM */

#ifdef CONFIG_OF
+struct xhci_plat_ops xhci_plat_mvebu = {
+ .probe = xhci_mvebu_probe,
+ .remove = xhci_mvebu_remove,
+};
+
static const struct of_device_id usb_xhci_of_match[] = {
{
.compatible = "generic-xhci",
@@ -259,6 +265,10 @@ static const struct of_device_id usb_xhci_of_match[] = {
.compatible = "xhci-platform",
.data = (void *) &xhci_plat_default,
},
+ {
+ .compatible = "marvell,xhci-armada-380",
+ .data = (void *) &xhci_plat_mvebu,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
--
1.8.1.2

2014-04-18 10:23:30

by Gregory CLEMENT

[permalink] [raw]
Subject: [PATCH 3/8] xhci-platform: Add a new controller using xhci: Armada 38x

Extend the compatible string list with xhci-armada-380. It is used to
describe xhci controller which is in the Armada 38x SoCs.

Signed-off-by: Gregory CLEMENT <[email protected]>
---
Documentation/devicetree/bindings/usb/usb-xhci.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt
index 90f8f607d125..c49c14037afe 100644
--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
@@ -1,7 +1,8 @@
USB xHCI controllers

Required properties:
- - compatible: should be "generic-xhci" (deprecated: "xhci-platform").
+ - compatible: should be on of "generic-xhci",
+ "marvell,xhci-armada-380" (deprecated: "xhci-platform").
- reg: should contain address and length of the standard XHCI
register set for the device.
- interrupts: one XHCI interrupt should be described here.
--
1.8.1.2

2014-04-18 10:26:49

by Gregory CLEMENT

[permalink] [raw]
Subject: [PATCH 4/8] ARM: mvebu: Add USB3 UTMI support

The usb3-utmi registers allow to configure the internal USB PHY of the
Armada 380/385 SoCs. A small initialization is needed to be able to use
the USB3 ports.

Signed-off-by: Gregory CLEMENT <[email protected]>
---
arch/arm/mach-mvebu/Makefile | 2 +-
arch/arm/mach-mvebu/usb-utmi.c | 64 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/mach-mvebu/usb-utmi.c

diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index a63e43b6b451..2d98a3eeecf6 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -4,7 +4,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
AFLAGS_coherency_ll.o := -Wa,-march=armv7-a

obj-y += system-controller.o mvebu-soc-id.o
-obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o
+obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o usb-utmi.o
obj-$(CONFIG_MACH_DOVE) += dove.o
obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
diff --git a/arch/arm/mach-mvebu/usb-utmi.c b/arch/arm/mach-mvebu/usb-utmi.c
new file mode 100644
index 000000000000..e91e86f85eb4
--- /dev/null
+++ b/arch/arm/mach-mvebu/usb-utmi.c
@@ -0,0 +1,64 @@
+/*
+ * USB UTMI support for Armada 38x platform.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <[email protected]>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#define USB_UTMI_PHY_CTRL_STATUS(i) (0x20+i*4)
+#define USB_UTMI_TX_BITSTUFF_EN BIT(1)
+#define USB_UTMI_PU_PHY BIT(5)
+#define USB_UTMI_VBUS_ON_PHY BIT(6)
+
+static struct of_device_id of_usb_utmi_table[] = {
+ { .compatible = "marvell,armada-380-usb-utmi", },
+ { /* end of list */ },
+};
+
+static int __init mvebu_usb_utmi_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, of_usb_utmi_table);
+ if (np) {
+ void __iomem *usb_utmi_base, *utmi_base;
+
+ usb_utmi_base = of_iomap(np, 0);
+ BUG_ON(!usb_utmi_base);
+
+ utmi_base = of_iomap(np, 1);
+ BUG_ON(!utmi_base);
+
+ writel(USB_UTMI_TX_BITSTUFF_EN |
+ USB_UTMI_PU_PHY |
+ USB_UTMI_VBUS_ON_PHY,
+ usb_utmi_base + USB_UTMI_PHY_CTRL_STATUS(0));
+
+ /*
+ * Magic init... the registers and their value are not
+ * documented
+ */
+ writel(0x40605205, utmi_base);
+ writel(0x409, utmi_base + 4);
+ writel(0x1be7f6f, utmi_base + 0xc);
+
+ of_node_put(np);
+ iounmap(utmi_base);
+ iounmap(usb_utmi_base);
+ }
+
+ return 0;
+}
+postcore_initcall(mvebu_usb_utmi_init);
--
1.8.1.2

2014-04-18 10:27:22

by Gregory CLEMENT

[permalink] [raw]
Subject: [PATCH 1/8] usb: host: xhci-plat: Allow to register glue code using the device tree

This patch allow to register specific glue code for xhci controller.
It creates a structure called xhci_plat_ops to register functions
specific to an SoC. Currently there are only probe() and remove() but
it can be extended later, it was the point to create such a structure.

Each compatible string can then be associated to an instance of this
structure. In the non device tree case a default structure is used.

Signed-off-by: Gregory CLEMENT <[email protected]>
---
drivers/usb/host/xhci-plat.c | 72 +++++++++++++++++++++++++++++++++++++++++---
drivers/usb/host/xhci.h | 4 +++
2 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 151901ce1ba9..8029cc82edc4 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/dma-mapping.h>
+#include <linux/of_device.h>

#include "xhci.h"

@@ -85,7 +86,7 @@ static const struct hc_driver xhci_plat_xhci_driver = {
.bus_resume = xhci_bus_resume,
};

-static int xhci_plat_probe(struct platform_device *pdev)
+int common_xhci_plat_probe(struct platform_device *pdev, void *priv)
{
const struct hc_driver *driver;
struct xhci_hcd *xhci;
@@ -145,6 +146,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
/* USB 2.0 roothub is stored in the platform_device now. */
hcd = platform_get_drvdata(pdev);
xhci = hcd_to_xhci(hcd);
+ xhci->priv = priv;
xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev,
dev_name(&pdev->dev), hcd);
if (!xhci->shared_hcd) {
@@ -185,7 +187,7 @@ put_hcd:
return ret;
}

-static int xhci_plat_remove(struct platform_device *dev)
+int common_xhci_plat_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -202,6 +204,26 @@ static int xhci_plat_remove(struct platform_device *dev)
return 0;
}

+static int default_xhci_plat_probe(struct platform_device *pdev)
+{
+ return common_xhci_plat_probe(pdev, NULL);
+}
+
+static int default_xhci_plat_remove(struct platform_device *pdev)
+{
+ return common_xhci_plat_remove(pdev);
+}
+
+struct xhci_plat_ops {
+ int (*probe)(struct platform_device *);
+ int (*remove)(struct platform_device *);
+};
+
+static struct xhci_plat_ops xhci_plat_default = {
+ .probe = default_xhci_plat_probe,
+ .remove = default_xhci_plat_remove,
+};
+
#ifdef CONFIG_PM
static int xhci_plat_suspend(struct device *dev)
{
@@ -229,13 +251,55 @@ static const struct dev_pm_ops xhci_plat_pm_ops = {

#ifdef CONFIG_OF
static const struct of_device_id usb_xhci_of_match[] = {
- { .compatible = "generic-xhci" },
- { .compatible = "xhci-platform" },
+ {
+ .compatible = "generic-xhci",
+ .data = (void *) &xhci_plat_default,
+ },
+ {
+ .compatible = "xhci-platform",
+ .data = (void *) &xhci_plat_default,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
#endif

+static int xhci_plat_probe(struct platform_device *pdev)
+{
+ const struct xhci_plat_ops *plat_of = &xhci_plat_default;
+
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match =
+ of_match_device(usb_xhci_of_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+ plat_of = match->data;
+ }
+
+ if (!plat_of || !plat_of->probe)
+ return -ENODEV;
+
+ return plat_of->probe(pdev);
+}
+
+static int xhci_plat_remove(struct platform_device *pdev)
+{
+ const struct xhci_plat_ops *plat_of = &xhci_plat_default;
+
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match =
+ of_match_device(usb_xhci_of_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+ plat_of = match->data;
+ }
+
+ if (!plat_of || !plat_of->remove)
+ return -ENODEV;
+
+ return plat_of->remove(pdev);
+}
+
static struct platform_driver usb_xhci_driver = {
.probe = xhci_plat_probe,
.remove = xhci_plat_remove,
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index d280e9213d08..96dd3df3dd8c 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1461,6 +1461,7 @@ struct xhci_hcd {
__u32 hcc_params;

spinlock_t lock;
+ void *priv;

/* packed release number */
u8 sbrn;
@@ -1597,6 +1598,9 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
return xhci->main_hcd;
}

+int common_xhci_plat_probe(struct platform_device *pdev, void *priv);
+int common_xhci_plat_remove(struct platform_device *dev);
+
#define xhci_dbg(xhci, fmt, args...) \
dev_dbg(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
#define xhci_err(xhci, fmt, args...) \
--
1.8.1.2

2014-04-18 11:13:52

by Sebastian Hesselbarth

[permalink] [raw]
Subject: Re: [PATCH 2/8] usb: host: xhci-plat: Add support for the Armada 38x glue code

On 04/18/2014 12:22 PM, Gregory CLEMENT wrote:
> For the armada 38x SoCs which come with an xhci controller, specific
> initialization must be done during probe, especially in relation with
> the MBus windows initialization. This patch adds this support.
>
> Signed-off-by: Gregory CLEMENT <[email protected]>
> ---
> drivers/usb/host/Kconfig | 7 +++
> drivers/usb/host/Makefile | 1 +
> drivers/usb/host/xhci-mvebu.c | 105 ++++++++++++++++++++++++++++++++++++++++++
> drivers/usb/host/xhci-mvebu.h | 21 +++++++++
> drivers/usb/host/xhci-plat.c | 10 ++++
> 5 files changed, 144 insertions(+)
> create mode 100644 drivers/usb/host/xhci-mvebu.c
> create mode 100644 drivers/usb/host/xhci-mvebu.h
>
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 3d9e54062d62..e70943fac4a1 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -29,6 +29,13 @@ if USB_XHCI_HCD
> config USB_XHCI_PLATFORM
> tristate
>
> +config USB_XHCI_MVEBU
> + tristate "xHCI support for Marvell Armada 38x"
> + select USB_XHCI_PLATFORM
> + ---help---
> + Say 'Y' to enable the support for the xHCI host controller
> + found in Marvell Armada 38x ARM SOCs.
> +
> endif # USB_XHCI_HCD
>
> config USB_EHCI_HCD
> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
> index 7530468c9a4f..7a8db7f7dc01 100644
> --- a/drivers/usb/host/Makefile
> +++ b/drivers/usb/host/Makefile
> @@ -19,6 +19,7 @@ xhci-hcd-$(CONFIG_PCI) += xhci-pci.o
>
> ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
> xhci-hcd-y += xhci-plat.o
> + xhci-hcd-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
> endif
>
> obj-$(CONFIG_USB_WHCI_HCD) += whci/
> diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
> new file mode 100644
> index 000000000000..dc9c7648ab65
> --- /dev/null
> +++ b/drivers/usb/host/xhci-mvebu.c
> @@ -0,0 +1,105 @@
> +/*
> + * Copyright (C) 2014 Marvell
> + * Author: Gregory CLEMENT <[email protected]>
> + *
> + * 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/clk.h>
> +#include <linux/io.h>
> +#include <linux/mbus.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +#include "xhci.h"
> +
> +#define USB3_MAX_WINDOWS 4
> +#define USB3_WIN_CTRL(w) (0x0 + ((w) * 8))
> +#define USB3_WIN_BASE(w) (0x4 + ((w) * 8))
> +
> +static void __init mv_usb3_conf_mbus_windows(void __iomem *base,
> + const struct mbus_dram_target_info *dram)
> +{
> + int win;
> +
> + /* Clear all existing windows */
> + for (win = 0; win < USB3_MAX_WINDOWS; win++) {
> + writel(0, base + USB3_WIN_CTRL(win));
> + writel(0, base + USB3_WIN_BASE(win));
> + }
> +
> + /* Program each DRAM CS in a seperate window */
> + for (win = 0; win < dram->num_cs; win++) {
> + const struct mbus_dram_window *cs = dram->cs + win;
> +
> + writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) |
> + (dram->mbus_dram_target_id << 4) | 1,
> + base + USB3_WIN_CTRL(win));
> +
> + writel((cs->base & 0xffff0000), base + USB3_WIN_BASE(win));
> + }
> +}
> +
> +int xhci_mvebu_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> + void __iomem *base;
> + const struct mbus_dram_target_info *dram;
> + int ret;
> + struct clk *clk;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> + if (!res)
> + return -ENODEV;
> +
> + /*
> + * We don't use devm_ioremap() because this mapping should
> + * only exists for the duration of this probe function.
> + */
> + base = ioremap(res->start, resource_size(res));
> + if (!base)
> + return -ENODEV;
> +
> + clk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(clk)) {
> + iounmap(base);
> + return PTR_ERR(clk);
> + }
> +
> + ret = clk_prepare_enable(clk);
> + if (ret < 0) {
> + iounmap(base);
> + return ret;
> + }
> +
> + dram = mv_mbus_dram_info();
> + mv_usb3_conf_mbus_windows(base, dram);
> +
> + /*
> + * This memory area was only needed to configure the MBus
> + * windows, and is therefore no longer useful.
> + */
> + iounmap(base);
> +
> + ret = common_xhci_plat_probe(pdev, clk);
> + if (ret < 0) {
> + clk_disable_unprepare(clk);
> + return ret;
> + }
> +
> + return ret;
> +}
> +
> +int xhci_mvebu_remove(struct platform_device *pdev)
> +{
> + struct usb_hcd *hcd = platform_get_drvdata(pdev);
> + struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> + struct clk *clk = xhci->priv;
> +
> + common_xhci_plat_remove(pdev);
> + clk_disable_unprepare(clk);
> +
> + return 0;
> +}
> diff --git a/drivers/usb/host/xhci-mvebu.h b/drivers/usb/host/xhci-mvebu.h
> new file mode 100644
> index 000000000000..897ef298f22f
> --- /dev/null
> +++ b/drivers/usb/host/xhci-mvebu.h
> @@ -0,0 +1,21 @@
> +/*
> + * Copyright (C) 2014 Marvell
> + *
> + * Gregory Clement <[email protected]>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef __LINUX_XHCI_MVEBU_H
> +#define __LINUX_XHCI_MVEBU_H
> +
> +#ifdef CONFIG_USB_XHCI_MVEBU
> +int xhci_mvebu_probe(struct platform_device *pdev);
> +int xhci_mvebu_remove(struct platform_device *pdev);
> +#else
> +#define xhci_mvebu_probe NULL
> +#define xhci_mvebu_remove NULL
> +#endif
> +#endif /* __LINUX_XHCI_MVEBU_H */
> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
> index 8029cc82edc4..f1261d3848a9 100644
> --- a/drivers/usb/host/xhci-plat.c
> +++ b/drivers/usb/host/xhci-plat.c
> @@ -19,6 +19,7 @@
> #include <linux/of_device.h>
>
> #include "xhci.h"
> +#include "xhci-mvebu.h"
>
> static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
> {
> @@ -250,6 +251,11 @@ static const struct dev_pm_ops xhci_plat_pm_ops = {
> #endif /* CONFIG_PM */
>
> #ifdef CONFIG_OF

Gregory,

either you should #ifndef CONFIG_USB_XHCI_MVEBU this and the one below -
or even better:

Can you put driver stub with its of_match_table right into xhci-mvebu?
That way platform specific probe wouldn't pollute the generic driver.

Greg will have a better opinion about it, but I remember some cleanup
in ehci, that basically removed platform specific references from the
generic code.

> +struct xhci_plat_ops xhci_plat_mvebu = {
> + .probe = xhci_mvebu_probe,
> + .remove = xhci_mvebu_remove,
> +};
> +
> static const struct of_device_id usb_xhci_of_match[] = {
> {
> .compatible = "generic-xhci",
> @@ -259,6 +265,10 @@ static const struct of_device_id usb_xhci_of_match[] = {
> .compatible = "xhci-platform",
> .data = (void *) &xhci_plat_default,
> },
> + {
> + .compatible = "marvell,xhci-armada-380",

nit: the ususal order we use on mvebu is "marvell,<soc>-<ip>", so this
should be "marvell,armada-380-xhci".

Sebastian

> + .data = (void *) &xhci_plat_mvebu,
> + },
> { },
> };
> MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
>

2014-04-18 11:19:52

by Sebastian Hesselbarth

[permalink] [raw]
Subject: Re: [PATCH 4/8] ARM: mvebu: Add USB3 UTMI support

On 04/18/2014 12:22 PM, Gregory CLEMENT wrote:
> The usb3-utmi registers allow to configure the internal USB PHY of the
> Armada 380/385 SoCs. A small initialization is needed to be able to use
> the USB3 ports.
>
> Signed-off-by: Gregory CLEMENT <[email protected]>
> ---
> arch/arm/mach-mvebu/Makefile | 2 +-
> arch/arm/mach-mvebu/usb-utmi.c | 64 ++++++++++++++++++++++++++++++++++++++++++

Gregory,

there is the generic PHY framework, that could possibly be used to
avoid adding more code to arch/arm/mach-mvebu.

> 2 files changed, 65 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm/mach-mvebu/usb-utmi.c
>
> diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
> index a63e43b6b451..2d98a3eeecf6 100644
> --- a/arch/arm/mach-mvebu/Makefile
> +++ b/arch/arm/mach-mvebu/Makefile
> @@ -4,7 +4,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
> AFLAGS_coherency_ll.o := -Wa,-march=armv7-a
>
> obj-y += system-controller.o mvebu-soc-id.o
> -obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o
> +obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o usb-utmi.o
> obj-$(CONFIG_MACH_DOVE) += dove.o
> obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o
> obj-$(CONFIG_SMP) += platsmp.o headsmp.o
> diff --git a/arch/arm/mach-mvebu/usb-utmi.c b/arch/arm/mach-mvebu/usb-utmi.c
> new file mode 100644
> index 000000000000..e91e86f85eb4
> --- /dev/null
> +++ b/arch/arm/mach-mvebu/usb-utmi.c
> @@ -0,0 +1,64 @@
> +/*
> + * USB UTMI support for Armada 38x platform.
> + *
> + * Copyright (C) 2014 Marvell
> + *
> + * Gregory CLEMENT <[email protected]>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/of_address.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>

nit: sort alphabetically

> +#define USB_UTMI_PHY_CTRL_STATUS(i) (0x20+i*4)
> +#define USB_UTMI_TX_BITSTUFF_EN BIT(1)
> +#define USB_UTMI_PU_PHY BIT(5)
> +#define USB_UTMI_VBUS_ON_PHY BIT(6)

nit: two TABs in front of the defines above.

> +static struct of_device_id of_usb_utmi_table[] = {
> + { .compatible = "marvell,armada-380-usb-utmi", },
> + { /* end of list */ },
> +};
> +
> +static int __init mvebu_usb_utmi_init(void)
> +{
> + struct device_node *np;
> +
> + np = of_find_matching_node(NULL, of_usb_utmi_table);
> + if (np) {
> + void __iomem *usb_utmi_base, *utmi_base;
> +
> + usb_utmi_base = of_iomap(np, 0);
> + BUG_ON(!usb_utmi_base);
> +
> + utmi_base = of_iomap(np, 1);
> + BUG_ON(!utmi_base);
> +
> + writel(USB_UTMI_TX_BITSTUFF_EN |
> + USB_UTMI_PU_PHY |
> + USB_UTMI_VBUS_ON_PHY,
> + usb_utmi_base + USB_UTMI_PHY_CTRL_STATUS(0));
> +
> + /*
> + * Magic init... the registers and their value are not
> + * documented
> + */
> + writel(0x40605205, utmi_base);
> + writel(0x409, utmi_base + 4);
> + writel(0x1be7f6f, utmi_base + 0xc);

nit: decimal/hexadecimal offsets, also IMHO filling the values
written with leading zeros improves readability of "magic init"
alot :)

Sebastian

> +
> + of_node_put(np);
> + iounmap(utmi_base);
> + iounmap(usb_utmi_base);
> + }
> +
> + return 0;
> +}
> +postcore_initcall(mvebu_usb_utmi_init);
>

2014-04-18 11:23:31

by Sebastian Hesselbarth

[permalink] [raw]
Subject: Re: [PATCH 5/8] ARM: mvebu: Add Device Tree description of xHCI hosts on Armada 38x

On 04/18/2014 12:22 PM, Gregory CLEMENT wrote:
> The Marvell Armada 38x SoCs contain two xHCI host. This commit adds
> the Device Tree description of those interfaces at the SoC level, and
> also enables the two USB3 ports on the Armada 385 DB platform and one
> USB3 port on the Armada 385 RD platforms.
>
> Signed-off-by: Gregory CLEMENT <[email protected]>
> ---
> arch/arm/boot/dts/armada-385-db.dts | 8 ++++++++
> arch/arm/boot/dts/armada-385-rd.dts | 4 ++++
> arch/arm/boot/dts/armada-38x.dtsi | 17 +++++++++++++++++
> 3 files changed, 29 insertions(+)
[...]
> diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
> index a064f59da02d..4f117e66aa1a 100644
> --- a/arch/arm/boot/dts/armada-38x.dtsi
> +++ b/arch/arm/boot/dts/armada-38x.dtsi
> @@ -355,6 +355,23 @@
> clocks = <&coredivclk 0>;
> status = "disabled";
> };
> +
> + usb3@f0000 {
> + compatible = "marvell,xhci-armada-380";
> + reg = <0xf0000 0x3fff>,<0xf4000 0x3fff>;
> + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&gateclk 9>;

Using generic PHY framework will allow you to reference the PHY nodes
with "usb-phy" here.

BTW, you added a "marvell,armada-380-usb-utmi" in the patch for PHY init
but I can see no corresponding node added.

Sebastian

> + status = "disabled";
> + };
> +
> + usb3@f8000 {
> + compatible = "marvell,xhci-armada-380";
> + reg = <0xf8000 0x3fff>,<0xfc000 0x3fff>;
> + interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&gateclk 10>;
> + status = "disabled";
> + };
> +
> };
> };
>
>

2014-04-18 11:43:51

by Gregory CLEMENT

[permalink] [raw]
Subject: Re: [PATCH 2/8] usb: host: xhci-plat: Add support for the Armada 38x glue code

Hi Sebastian,

[...]

>> @@ -0,0 +1,21 @@
>> +/*
>> + * Copyright (C) 2014 Marvell
>> + *
>> + * Gregory Clement <[email protected]>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +#ifndef __LINUX_XHCI_MVEBU_H
>> +#define __LINUX_XHCI_MVEBU_H
>> +
>> +#ifdef CONFIG_USB_XHCI_MVEBU
>> +int xhci_mvebu_probe(struct platform_device *pdev);
>> +int xhci_mvebu_remove(struct platform_device *pdev);
>> +#else
>> +#define xhci_mvebu_probe NULL
>> +#define xhci_mvebu_remove NULL
>> +#endif
>> +#endif /* __LINUX_XHCI_MVEBU_H */
>> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
>> index 8029cc82edc4..f1261d3848a9 100644
>> --- a/drivers/usb/host/xhci-plat.c
>> +++ b/drivers/usb/host/xhci-plat.c
>> @@ -19,6 +19,7 @@
>> #include <linux/of_device.h>
>>
>> #include "xhci.h"
>> +#include "xhci-mvebu.h"
>>
>> static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
>> {
>> @@ -250,6 +251,11 @@ static const struct dev_pm_ops xhci_plat_pm_ops = {
>> #endif /* CONFIG_PM */
>>
>> #ifdef CONFIG_OF
>
> Gregory,
>
> either you should #ifndef CONFIG_USB_XHCI_MVEBU this and the one below -
> or even better:

With the current code we don't need to add this, see xhci-mvebu.h: xhci_mvebu_*
are set to NULL if CONFIG_USB_XHCI_MVEBU is not define. Then the driver
is more multiplatform friendly.

>
> Can you put driver stub with its of_match_table right into xhci-mvebu?
> That way platform specific probe wouldn't pollute the generic driver.

This sound more interesting. However the only "pollution" is to extend
the compatible list, the platform specific code is in is own file. Moreover
it could make sens to have all the compatible strings at the same place.

I wait for the opinion of the USB maintainers for this point.

Thanks,

Gregory

>
> Greg will have a better opinion about it, but I remember some cleanup
> in ehci, that basically removed platform specific references from the
> generic code.
>
>> +struct xhci_plat_ops xhci_plat_mvebu = {
>> + .probe = xhci_mvebu_probe,
>> + .remove = xhci_mvebu_remove,
>> +};
>> +
>> static const struct of_device_id usb_xhci_of_match[] = {
>> {
>> .compatible = "generic-xhci",
>> @@ -259,6 +265,10 @@ static const struct of_device_id usb_xhci_of_match[] = {
>> .compatible = "xhci-platform",
>> .data = (void *) &xhci_plat_default,
>> },
>> + {
>> + .compatible = "marvell,xhci-armada-380",
>
> nit: the ususal order we use on mvebu is "marvell,<soc>-<ip>", so this
> should be "marvell,armada-380-xhci".
>
> Sebastian
>
>> + .data = (void *) &xhci_plat_mvebu,
>> + },
>> { },
>> };
>> MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
>>
>


--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

2014-04-18 11:45:18

by Gregory CLEMENT

[permalink] [raw]
Subject: Re: [PATCH 5/8] ARM: mvebu: Add Device Tree description of xHCI hosts on Armada 38x

Hi Sebastian,
On 18/04/2014 13:23, Sebastian Hesselbarth wrote:
> On 04/18/2014 12:22 PM, Gregory CLEMENT wrote:
>> The Marvell Armada 38x SoCs contain two xHCI host. This commit adds
>> the Device Tree description of those interfaces at the SoC level, and
>> also enables the two USB3 ports on the Armada 385 DB platform and one
>> USB3 port on the Armada 385 RD platforms.
>>
>> Signed-off-by: Gregory CLEMENT <[email protected]>
>> ---
>> arch/arm/boot/dts/armada-385-db.dts | 8 ++++++++
>> arch/arm/boot/dts/armada-385-rd.dts | 4 ++++
>> arch/arm/boot/dts/armada-38x.dtsi | 17 +++++++++++++++++
>> 3 files changed, 29 insertions(+)
> [...]
>> diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
>> index a064f59da02d..4f117e66aa1a 100644
>> --- a/arch/arm/boot/dts/armada-38x.dtsi
>> +++ b/arch/arm/boot/dts/armada-38x.dtsi
>> @@ -355,6 +355,23 @@
>> clocks = <&coredivclk 0>;
>> status = "disabled";
>> };
>> +
>> + usb3@f0000 {
>> + compatible = "marvell,xhci-armada-380";
>> + reg = <0xf0000 0x3fff>,<0xf4000 0x3fff>;
>> + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
>> + clocks = <&gateclk 9>;
>
> Using generic PHY framework will allow you to reference the PHY nodes
> with "usb-phy" here.
>
> BTW, you added a "marvell,armada-380-usb-utmi" in the patch for PHY init
> but I can see no corresponding node added.

Yes a commit was lost during one of my rebase!
Thanks to git reflog, I found it.
Thanks,

Gregory


>
> Sebastian
>
>> + status = "disabled";
>> + };
>> +
>> + usb3@f8000 {
>> + compatible = "marvell,xhci-armada-380";
>> + reg = <0xf8000 0x3fff>,<0xfc000 0x3fff>;
>> + interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
>> + clocks = <&gateclk 10>;
>> + status = "disabled";
>> + };
>> +
>> };
>> };
>>
>>
>


--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

2014-04-18 11:47:48

by Sebastian Hesselbarth

[permalink] [raw]
Subject: Re: [PATCH 2/8] usb: host: xhci-plat: Add support for the Armada 38x glue code

On 04/18/2014 01:43 PM, Gregory CLEMENT wrote:
>>> @@ -0,0 +1,21 @@
>>> +/*
>>> + * Copyright (C) 2014 Marvell
>>> + *
>>> + * Gregory Clement <[email protected]>
>>> + *
>>> + * This file is licensed under the terms of the GNU General Public
>>> + * License version 2. This program is licensed "as is" without any
>>> + * warranty of any kind, whether express or implied.
>>> + */
>>> +
>>> +#ifndef __LINUX_XHCI_MVEBU_H
>>> +#define __LINUX_XHCI_MVEBU_H
>>> +
>>> +#ifdef CONFIG_USB_XHCI_MVEBU
>>> +int xhci_mvebu_probe(struct platform_device *pdev);
>>> +int xhci_mvebu_remove(struct platform_device *pdev);
>>> +#else
>>> +#define xhci_mvebu_probe NULL
>>> +#define xhci_mvebu_remove NULL
>>> +#endif
>>> +#endif /* __LINUX_XHCI_MVEBU_H */
>>> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
>>> index 8029cc82edc4..f1261d3848a9 100644
>>> --- a/drivers/usb/host/xhci-plat.c
>>> +++ b/drivers/usb/host/xhci-plat.c
>>> @@ -19,6 +19,7 @@
>>> #include <linux/of_device.h>
>>>
>>> #include "xhci.h"
>>> +#include "xhci-mvebu.h"
>>>
>>> static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
>>> {
>>> @@ -250,6 +251,11 @@ static const struct dev_pm_ops xhci_plat_pm_ops = {
>>> #endif /* CONFIG_PM */
>>>
>>> #ifdef CONFIG_OF
>>
>> Gregory,
>>
>> either you should #ifndef CONFIG_USB_XHCI_MVEBU this and the one below -
>> or even better:
>
> With the current code we don't need to add this, see xhci-mvebu.h: xhci_mvebu_*
> are set to NULL if CONFIG_USB_XHCI_MVEBU is not define. Then the driver
> is more multiplatform friendly.

Ok, but strictly speaking, the compatible should be #ifndef'd at least.

>>
>> Can you put driver stub with its of_match_table right into xhci-mvebu?
>> That way platform specific probe wouldn't pollute the generic driver.
>
> This sound more interesting. However the only "pollution" is to extend
> the compatible list, the platform specific code is in is own file. Moreover
> it could make sens to have all the compatible strings at the same place.

"pollute" wasn't meant for just your patch, but you can expect others
the hop in as soon as one adds platform specific code ;)

> I wait for the opinion of the USB maintainers for this point.

Agreed.

Sebastian

>> Greg will have a better opinion about it, but I remember some cleanup
>> in ehci, that basically removed platform specific references from the
>> generic code.
>>
>>> +struct xhci_plat_ops xhci_plat_mvebu = {
>>> + .probe = xhci_mvebu_probe,
>>> + .remove = xhci_mvebu_remove,
>>> +};
>>> +
>>> static const struct of_device_id usb_xhci_of_match[] = {
>>> {
>>> .compatible = "generic-xhci",
>>> @@ -259,6 +265,10 @@ static const struct of_device_id usb_xhci_of_match[] = {
>>> .compatible = "xhci-platform",
>>> .data = (void *) &xhci_plat_default,
>>> },
>>> + {
>>> + .compatible = "marvell,xhci-armada-380",
>>
>> nit: the ususal order we use on mvebu is "marvell,<soc>-<ip>", so this
>> should be "marvell,armada-380-xhci".
>>
>> Sebastian
>>
>>> + .data = (void *) &xhci_plat_mvebu,
>>> + },
>>> { },
>>> };
>>> MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
>>>
>>
>
>

2014-04-18 12:20:00

by Gregory CLEMENT

[permalink] [raw]
Subject: Re: [PATCH 4/8] ARM: mvebu: Add USB3 UTMI support

Hi Sebastian,

On 18/04/2014 13:19, Sebastian Hesselbarth wrote:
> On 04/18/2014 12:22 PM, Gregory CLEMENT wrote:
>> The usb3-utmi registers allow to configure the internal USB PHY of the
>> Armada 380/385 SoCs. A small initialization is needed to be able to use
>> the USB3 ports.
>>
>> Signed-off-by: Gregory CLEMENT <[email protected]>
>> ---
>> arch/arm/mach-mvebu/Makefile | 2 +-
>> arch/arm/mach-mvebu/usb-utmi.c | 64 ++++++++++++++++++++++++++++++++++++++++++
>
> Gregory,
>
> there is the generic PHY framework, that could possibly be used to
> avoid adding more code to arch/arm/mach-mvebu.

Given the very low information I have about UTMI I was a bit reluctant to
write a driver. This is, for me, more a platform specific initialization than
something which can be used for a driver. However I will have a look on it.

>
>> 2 files changed, 65 insertions(+), 1 deletion(-)
>> create mode 100644 arch/arm/mach-mvebu/usb-utmi.c
>>
>> diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
>> index a63e43b6b451..2d98a3eeecf6 100644
>> --- a/arch/arm/mach-mvebu/Makefile
>> +++ b/arch/arm/mach-mvebu/Makefile
>> @@ -4,7 +4,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
>> AFLAGS_coherency_ll.o := -Wa,-march=armv7-a
>>
>> obj-y += system-controller.o mvebu-soc-id.o
>> -obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o
>> +obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o usb-utmi.o
>> obj-$(CONFIG_MACH_DOVE) += dove.o
>> obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o
>> obj-$(CONFIG_SMP) += platsmp.o headsmp.o
>> diff --git a/arch/arm/mach-mvebu/usb-utmi.c b/arch/arm/mach-mvebu/usb-utmi.c
>> new file mode 100644
>> index 000000000000..e91e86f85eb4
>> --- /dev/null
>> +++ b/arch/arm/mach-mvebu/usb-utmi.c
>> @@ -0,0 +1,64 @@
>> +/*
>> + * USB UTMI support for Armada 38x platform.
>> + *
>> + * Copyright (C) 2014 Marvell
>> + *
>> + * Gregory CLEMENT <[email protected]>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + *
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/init.h>
>> +#include <linux/of_address.h>
>> +#include <linux/io.h>
>> +#include <linux/slab.h>
>
> nit: sort alphabetically

Right

>
>> +#define USB_UTMI_PHY_CTRL_STATUS(i) (0x20+i*4)
>> +#define USB_UTMI_TX_BITSTUFF_EN BIT(1)
>> +#define USB_UTMI_PU_PHY BIT(5)
>> +#define USB_UTMI_VBUS_ON_PHY BIT(6)
>
> nit: two TABs in front of the defines above.

Right

>
>> +static struct of_device_id of_usb_utmi_table[] = {
>> + { .compatible = "marvell,armada-380-usb-utmi", },
>> + { /* end of list */ },
>> +};
>> +
>> +static int __init mvebu_usb_utmi_init(void)
>> +{
>> + struct device_node *np;
>> +
>> + np = of_find_matching_node(NULL, of_usb_utmi_table);
>> + if (np) {
>> + void __iomem *usb_utmi_base, *utmi_base;
>> +
>> + usb_utmi_base = of_iomap(np, 0);
>> + BUG_ON(!usb_utmi_base);
>> +
>> + utmi_base = of_iomap(np, 1);
>> + BUG_ON(!utmi_base);
>> +
>> + writel(USB_UTMI_TX_BITSTUFF_EN |
>> + USB_UTMI_PU_PHY |
>> + USB_UTMI_VBUS_ON_PHY,
>> + usb_utmi_base + USB_UTMI_PHY_CTRL_STATUS(0));
>> +
>> + /*
>> + * Magic init... the registers and their value are not
>> + * documented
>> + */
>> + writel(0x40605205, utmi_base);
>> + writel(0x409, utmi_base + 4);
>> + writel(0x1be7f6f, utmi_base + 0xc);
>
> nit: decimal/hexadecimal offsets, also IMHO filling the values

OK

> written with leading zeros improves readability of "magic init"
> alot :)

Well it still remains magic! But I will do it.

Thanks,

Gregory


--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

2014-04-20 03:18:16

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 1/8] usb: host: xhci-plat: Allow to register glue code using the device tree

Hi,

On Fri, Apr 18, 2014 at 12:22:36PM +0200, Gregory CLEMENT wrote:
> This patch allow to register specific glue code for xhci controller.
> It creates a structure called xhci_plat_ops to register functions
> specific to an SoC. Currently there are only probe() and remove() but

What SoC-specific code do you need ?

> it can be extended later, it was the point to create such a structure.
>
> Each compatible string can then be associated to an instance of this
> structure. In the non device tree case a default structure is used.
>
> Signed-off-by: Gregory CLEMENT <[email protected]>
> ---
> drivers/usb/host/xhci-plat.c | 72 +++++++++++++++++++++++++++++++++++++++++---
> drivers/usb/host/xhci.h | 4 +++
> 2 files changed, 72 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
> index 151901ce1ba9..8029cc82edc4 100644
> --- a/drivers/usb/host/xhci-plat.c
> +++ b/drivers/usb/host/xhci-plat.c
> @@ -16,6 +16,7 @@
> #include <linux/slab.h>
> #include <linux/of.h>
> #include <linux/dma-mapping.h>
> +#include <linux/of_device.h>
>
> #include "xhci.h"
>
> @@ -85,7 +86,7 @@ static const struct hc_driver xhci_plat_xhci_driver = {
> .bus_resume = xhci_bus_resume,
> };
>
> -static int xhci_plat_probe(struct platform_device *pdev)
> +int common_xhci_plat_probe(struct platform_device *pdev, void *priv)

no, I rather not see this sort of hack.

--
balbi


Attachments:
(No filename) (1.42 kB)
signature.asc (819.00 B)
Digital signature
Download all attachments

2014-04-20 03:23:46

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 2/8] usb: host: xhci-plat: Add support for the Armada 38x glue code

On Fri, Apr 18, 2014 at 12:22:37PM +0200, Gregory CLEMENT wrote:
> For the armada 38x SoCs which come with an xhci controller, specific
> initialization must be done during probe, especially in relation with
> the MBus windows initialization. This patch adds this support.
>
> Signed-off-by: Gregory CLEMENT <[email protected]>
> ---
> drivers/usb/host/Kconfig | 7 +++
> drivers/usb/host/Makefile | 1 +
> drivers/usb/host/xhci-mvebu.c | 105 ++++++++++++++++++++++++++++++++++++++++++
> drivers/usb/host/xhci-mvebu.h | 21 +++++++++
> drivers/usb/host/xhci-plat.c | 10 ++++
> 5 files changed, 144 insertions(+)
> create mode 100644 drivers/usb/host/xhci-mvebu.c
> create mode 100644 drivers/usb/host/xhci-mvebu.h
>
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 3d9e54062d62..e70943fac4a1 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -29,6 +29,13 @@ if USB_XHCI_HCD
> config USB_XHCI_PLATFORM
> tristate
>
> +config USB_XHCI_MVEBU
> + tristate "xHCI support for Marvell Armada 38x"
> + select USB_XHCI_PLATFORM
> + ---help---
> + Say 'Y' to enable the support for the xHCI host controller
> + found in Marvell Armada 38x ARM SOCs.
> +
> endif # USB_XHCI_HCD
>
> config USB_EHCI_HCD
> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
> index 7530468c9a4f..7a8db7f7dc01 100644
> --- a/drivers/usb/host/Makefile
> +++ b/drivers/usb/host/Makefile
> @@ -19,6 +19,7 @@ xhci-hcd-$(CONFIG_PCI) += xhci-pci.o
>
> ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
> xhci-hcd-y += xhci-plat.o
> + xhci-hcd-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
> endif
>
> obj-$(CONFIG_USB_WHCI_HCD) += whci/
> diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
> new file mode 100644
> index 000000000000..dc9c7648ab65
> --- /dev/null
> +++ b/drivers/usb/host/xhci-mvebu.c
> @@ -0,0 +1,105 @@
> +/*
> + * Copyright (C) 2014 Marvell
> + * Author: Gregory CLEMENT <[email protected]>
> + *
> + * 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/clk.h>
> +#include <linux/io.h>
> +#include <linux/mbus.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +#include "xhci.h"
> +
> +#define USB3_MAX_WINDOWS 4
> +#define USB3_WIN_CTRL(w) (0x0 + ((w) * 8))
> +#define USB3_WIN_BASE(w) (0x4 + ((w) * 8))
> +
> +static void __init mv_usb3_conf_mbus_windows(void __iomem *base,
> + const struct mbus_dram_target_info *dram)
> +{
> + int win;
> +
> + /* Clear all existing windows */
> + for (win = 0; win < USB3_MAX_WINDOWS; win++) {
> + writel(0, base + USB3_WIN_CTRL(win));
> + writel(0, base + USB3_WIN_BASE(win));
> + }
> +
> + /* Program each DRAM CS in a seperate window */
> + for (win = 0; win < dram->num_cs; win++) {
> + const struct mbus_dram_window *cs = dram->cs + win;
> +
> + writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) |
> + (dram->mbus_dram_target_id << 4) | 1,
> + base + USB3_WIN_CTRL(win));
> +
> + writel((cs->base & 0xffff0000), base + USB3_WIN_BASE(win));
> + }
> +}
> +
> +int xhci_mvebu_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> + void __iomem *base;
> + const struct mbus_dram_target_info *dram;
> + int ret;
> + struct clk *clk;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> + if (!res)
> + return -ENODEV;
> +
> + /*
> + * We don't use devm_ioremap() because this mapping should
> + * only exists for the duration of this probe function.
> + */
> + base = ioremap(res->start, resource_size(res));
> + if (!base)
> + return -ENODEV;
> +
> + clk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(clk)) {
> + iounmap(base);
> + return PTR_ERR(clk);
> + }
> +
> + ret = clk_prepare_enable(clk);
> + if (ret < 0) {
> + iounmap(base);
> + return ret;
> + }

it's best to teach generic xhci-plat about clocks, just make it
optional.

> + dram = mv_mbus_dram_info();
> + mv_usb3_conf_mbus_windows(base, dram);
> +
> + /*
> + * This memory area was only needed to configure the MBus
> + * windows, and is therefore no longer useful.
> + */
> + iounmap(base);

so I suppose MBus is the Marvell interconnect, am I right ? Wouldn't you
be duplicating this sort of initialization for most drivers ?

> + ret = common_xhci_plat_probe(pdev, clk);

I would much rather reverse this, instead of exposing xhci-plat's probe,
turn this mbus initialization into a quirk which will ioremap the extra
resource, initialize some registers and iounmap it.

> diff --git a/drivers/usb/host/xhci-mvebu.h b/drivers/usb/host/xhci-mvebu.h
> new file mode 100644
> index 000000000000..897ef298f22f
> --- /dev/null
> +++ b/drivers/usb/host/xhci-mvebu.h
> @@ -0,0 +1,21 @@
> +/*
> + * Copyright (C) 2014 Marvell
> + *
> + * Gregory Clement <[email protected]>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef __LINUX_XHCI_MVEBU_H
> +#define __LINUX_XHCI_MVEBU_H
> +
> +#ifdef CONFIG_USB_XHCI_MVEBU
> +int xhci_mvebu_probe(struct platform_device *pdev);
> +int xhci_mvebu_remove(struct platform_device *pdev);
> +#else
> +#define xhci_mvebu_probe NULL
> +#define xhci_mvebu_remove NULL
> +#endif
> +#endif /* __LINUX_XHCI_MVEBU_H */
> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
> index 8029cc82edc4..f1261d3848a9 100644
> --- a/drivers/usb/host/xhci-plat.c
> +++ b/drivers/usb/host/xhci-plat.c
> @@ -19,6 +19,7 @@
> #include <linux/of_device.h>
>
> #include "xhci.h"
> +#include "xhci-mvebu.h"
>
> static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
> {
> @@ -250,6 +251,11 @@ static const struct dev_pm_ops xhci_plat_pm_ops = {
> #endif /* CONFIG_PM */
>
> #ifdef CONFIG_OF
> +struct xhci_plat_ops xhci_plat_mvebu = {
> + .probe = xhci_mvebu_probe,
> + .remove = xhci_mvebu_remove,
> +};

instead, just pass a flag such as:

XHCI_PLAT_MVEBU_MBUS_INIT_QUIRK or something

--
balbi


Attachments:
(No filename) (6.11 kB)
signature.asc (819.00 B)
Digital signature
Download all attachments

2014-04-20 03:24:58

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 3/8] xhci-platform: Add a new controller using xhci: Armada 38x

On Fri, Apr 18, 2014 at 12:22:38PM +0200, Gregory CLEMENT wrote:
> Extend the compatible string list with xhci-armada-380. It is used to
> describe xhci controller which is in the Armada 38x SoCs.
>
> Signed-off-by: Gregory CLEMENT <[email protected]>
> ---
> Documentation/devicetree/bindings/usb/usb-xhci.txt | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt
> index 90f8f607d125..c49c14037afe 100644
> --- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
> +++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
> @@ -1,7 +1,8 @@
> USB xHCI controllers
>
> Required properties:
> - - compatible: should be "generic-xhci" (deprecated: "xhci-platform").
> + - compatible: should be on of "generic-xhci",

should be "one" of.

> + "marvell,xhci-armada-380" (deprecated: "xhci-platform").

and this gives me a better idea, instead of using the quirk I suggested
before, match against this compatible:

if (of_device_is_compatible(dev, "marvell,xhci-armada-380")
xhci_marvel_mbus_init_quirk(dev);

--
balbi


Attachments:
(No filename) (1.15 kB)
signature.asc (819.00 B)
Digital signature
Download all attachments

2014-04-20 03:25:52

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 4/8] ARM: mvebu: Add USB3 UTMI support

Hi,

On Fri, Apr 18, 2014 at 12:22:39PM +0200, Gregory CLEMENT wrote:
> The usb3-utmi registers allow to configure the internal USB PHY of the
> Armada 380/385 SoCs. A small initialization is needed to be able to use
> the USB3 ports.
>
> Signed-off-by: Gregory CLEMENT <[email protected]>

looks like this should be a generic drivers/phy/phy-utmi.c driver

--
balbi


Attachments:
(No filename) (386.00 B)
signature.asc (819.00 B)
Digital signature
Download all attachments

2014-04-23 07:45:07

by Gregory CLEMENT

[permalink] [raw]
Subject: Re: [PATCH 2/8] usb: host: xhci-plat: Add support for the Armada 38x glue code

Hi Felipe,


On 20/04/2014 05:20, Felipe Balbi wrote:
> On Fri, Apr 18, 2014 at 12:22:37PM +0200, Gregory CLEMENT wrote:
>> For the armada 38x SoCs which come with an xhci controller, specific
>> initialization must be done during probe, especially in relation with
>> the MBus windows initialization. This patch adds this support.
>>
>> Signed-off-by: Gregory CLEMENT <[email protected]>
>> ---
>> drivers/usb/host/Kconfig | 7 +++
>> drivers/usb/host/Makefile | 1 +
>> drivers/usb/host/xhci-mvebu.c | 105 ++++++++++++++++++++++++++++++++++++++++++
>> drivers/usb/host/xhci-mvebu.h | 21 +++++++++
>> drivers/usb/host/xhci-plat.c | 10 ++++
>> 5 files changed, 144 insertions(+)
>> create mode 100644 drivers/usb/host/xhci-mvebu.c
>> create mode 100644 drivers/usb/host/xhci-mvebu.h
>>
>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
>> index 3d9e54062d62..e70943fac4a1 100644
>> --- a/drivers/usb/host/Kconfig
>> +++ b/drivers/usb/host/Kconfig
>> @@ -29,6 +29,13 @@ if USB_XHCI_HCD
>> config USB_XHCI_PLATFORM
>> tristate
>>
>> +config USB_XHCI_MVEBU
>> + tristate "xHCI support for Marvell Armada 38x"
>> + select USB_XHCI_PLATFORM
>> + ---help---
>> + Say 'Y' to enable the support for the xHCI host controller
>> + found in Marvell Armada 38x ARM SOCs.
>> +
>> endif # USB_XHCI_HCD
>>
>> config USB_EHCI_HCD
>> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
>> index 7530468c9a4f..7a8db7f7dc01 100644
>> --- a/drivers/usb/host/Makefile
>> +++ b/drivers/usb/host/Makefile
>> @@ -19,6 +19,7 @@ xhci-hcd-$(CONFIG_PCI) += xhci-pci.o
>>
>> ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
>> xhci-hcd-y += xhci-plat.o
>> + xhci-hcd-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
>> endif
>>
>> obj-$(CONFIG_USB_WHCI_HCD) += whci/
>> diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
>> new file mode 100644
>> index 000000000000..dc9c7648ab65
>> --- /dev/null
>> +++ b/drivers/usb/host/xhci-mvebu.c
>> @@ -0,0 +1,105 @@
>> +/*
>> + * Copyright (C) 2014 Marvell
>> + * Author: Gregory CLEMENT <[email protected]>
>> + *
>> + * 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/clk.h>
>> +#include <linux/io.h>
>> +#include <linux/mbus.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +
>> +#include "xhci.h"
>> +
>> +#define USB3_MAX_WINDOWS 4
>> +#define USB3_WIN_CTRL(w) (0x0 + ((w) * 8))
>> +#define USB3_WIN_BASE(w) (0x4 + ((w) * 8))
>> +
>> +static void __init mv_usb3_conf_mbus_windows(void __iomem *base,
>> + const struct mbus_dram_target_info *dram)
>> +{
>> + int win;
>> +
>> + /* Clear all existing windows */
>> + for (win = 0; win < USB3_MAX_WINDOWS; win++) {
>> + writel(0, base + USB3_WIN_CTRL(win));
>> + writel(0, base + USB3_WIN_BASE(win));
>> + }
>> +
>> + /* Program each DRAM CS in a seperate window */
>> + for (win = 0; win < dram->num_cs; win++) {
>> + const struct mbus_dram_window *cs = dram->cs + win;
>> +
>> + writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) |
>> + (dram->mbus_dram_target_id << 4) | 1,
>> + base + USB3_WIN_CTRL(win));
>> +
>> + writel((cs->base & 0xffff0000), base + USB3_WIN_BASE(win));
>> + }
>> +}
>> +
>> +int xhci_mvebu_probe(struct platform_device *pdev)
>> +{
>> + struct resource *res;
>> + void __iomem *base;
>> + const struct mbus_dram_target_info *dram;
>> + int ret;
>> + struct clk *clk;
>> +
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>> + if (!res)
>> + return -ENODEV;
>> +
>> + /*
>> + * We don't use devm_ioremap() because this mapping should
>> + * only exists for the duration of this probe function.
>> + */
>> + base = ioremap(res->start, resource_size(res));
>> + if (!base)
>> + return -ENODEV;
>> +
>> + clk = devm_clk_get(&pdev->dev, NULL);
>> + if (IS_ERR(clk)) {
>> + iounmap(base);
>> + return PTR_ERR(clk);
>> + }
>> +
>> + ret = clk_prepare_enable(clk);
>> + if (ret < 0) {
>> + iounmap(base);
>> + return ret;
>> + }
>
> it's best to teach generic xhci-plat about clocks, just make it
> optional.

OK

>
>> + dram = mv_mbus_dram_info();
>> + mv_usb3_conf_mbus_windows(base, dram);
>> +
>> + /*
>> + * This memory area was only needed to configure the MBus
>> + * windows, and is therefore no longer useful.
>> + */
>> + iounmap(base);
>
> so I suppose MBus is the Marvell interconnect, am I right ? Wouldn't you
> be duplicating this sort of initialization for most drivers ?

Actually most of them don't need it.

>
>> + ret = common_xhci_plat_probe(pdev, clk);
>
> I would much rather reverse this, instead of exposing xhci-plat's probe,
> turn this mbus initialization into a quirk which will ioremap the extra
> resource, initialize some registers and iounmap it.

This approach have been inspired by what have been done for SDHCI and AHCI.
The infrastructure allowing adding platform code is in the generic file but
all the specific code is in the platform file.

But if for USB you think we should do it in a different way, I will do it.


Thanks for your review

Gregory


>
>> diff --git a/drivers/usb/host/xhci-mvebu.h b/drivers/usb/host/xhci-mvebu.h
>> new file mode 100644
>> index 000000000000..897ef298f22f
>> --- /dev/null
>> +++ b/drivers/usb/host/xhci-mvebu.h
>> @@ -0,0 +1,21 @@
>> +/*
>> + * Copyright (C) 2014 Marvell
>> + *
>> + * Gregory Clement <[email protected]>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +#ifndef __LINUX_XHCI_MVEBU_H
>> +#define __LINUX_XHCI_MVEBU_H
>> +
>> +#ifdef CONFIG_USB_XHCI_MVEBU
>> +int xhci_mvebu_probe(struct platform_device *pdev);
>> +int xhci_mvebu_remove(struct platform_device *pdev);
>> +#else
>> +#define xhci_mvebu_probe NULL
>> +#define xhci_mvebu_remove NULL
>> +#endif
>> +#endif /* __LINUX_XHCI_MVEBU_H */
>> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
>> index 8029cc82edc4..f1261d3848a9 100644
>> --- a/drivers/usb/host/xhci-plat.c
>> +++ b/drivers/usb/host/xhci-plat.c
>> @@ -19,6 +19,7 @@
>> #include <linux/of_device.h>
>>
>> #include "xhci.h"
>> +#include "xhci-mvebu.h"
>>
>> static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
>> {
>> @@ -250,6 +251,11 @@ static const struct dev_pm_ops xhci_plat_pm_ops = {
>> #endif /* CONFIG_PM */
>>
>> #ifdef CONFIG_OF
>> +struct xhci_plat_ops xhci_plat_mvebu = {
>> + .probe = xhci_mvebu_probe,
>> + .remove = xhci_mvebu_remove,
>> +};
>
> instead, just pass a flag such as:
>
> XHCI_PLAT_MVEBU_MBUS_INIT_QUIRK or something
>


--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

2014-04-23 15:25:42

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 2/8] usb: host: xhci-plat: Add support for the Armada 38x glue code

Hi,

On Wed, Apr 23, 2014 at 09:44:57AM +0200, Gregory CLEMENT wrote:
> > On Fri, Apr 18, 2014 at 12:22:37PM +0200, Gregory CLEMENT wrote:
> >> For the armada 38x SoCs which come with an xhci controller, specific
> >> initialization must be done during probe, especially in relation with
> >> the MBus windows initialization. This patch adds this support.
> >>
> >> Signed-off-by: Gregory CLEMENT <[email protected]>
> >> ---
> >> drivers/usb/host/Kconfig | 7 +++
> >> drivers/usb/host/Makefile | 1 +
> >> drivers/usb/host/xhci-mvebu.c | 105 ++++++++++++++++++++++++++++++++++++++++++
> >> drivers/usb/host/xhci-mvebu.h | 21 +++++++++
> >> drivers/usb/host/xhci-plat.c | 10 ++++
> >> 5 files changed, 144 insertions(+)
> >> create mode 100644 drivers/usb/host/xhci-mvebu.c
> >> create mode 100644 drivers/usb/host/xhci-mvebu.h
> >>
> >> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> >> index 3d9e54062d62..e70943fac4a1 100644
> >> --- a/drivers/usb/host/Kconfig
> >> +++ b/drivers/usb/host/Kconfig
> >> @@ -29,6 +29,13 @@ if USB_XHCI_HCD
> >> config USB_XHCI_PLATFORM
> >> tristate
> >>
> >> +config USB_XHCI_MVEBU
> >> + tristate "xHCI support for Marvell Armada 38x"
> >> + select USB_XHCI_PLATFORM
> >> + ---help---
> >> + Say 'Y' to enable the support for the xHCI host controller
> >> + found in Marvell Armada 38x ARM SOCs.
> >> +
> >> endif # USB_XHCI_HCD
> >>
> >> config USB_EHCI_HCD
> >> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
> >> index 7530468c9a4f..7a8db7f7dc01 100644
> >> --- a/drivers/usb/host/Makefile
> >> +++ b/drivers/usb/host/Makefile
> >> @@ -19,6 +19,7 @@ xhci-hcd-$(CONFIG_PCI) += xhci-pci.o
> >>
> >> ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
> >> xhci-hcd-y += xhci-plat.o
> >> + xhci-hcd-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
> >> endif
> >>
> >> obj-$(CONFIG_USB_WHCI_HCD) += whci/
> >> diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
> >> new file mode 100644
> >> index 000000000000..dc9c7648ab65
> >> --- /dev/null
> >> +++ b/drivers/usb/host/xhci-mvebu.c
> >> @@ -0,0 +1,105 @@
> >> +/*
> >> + * Copyright (C) 2014 Marvell
> >> + * Author: Gregory CLEMENT <[email protected]>
> >> + *
> >> + * 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/clk.h>
> >> +#include <linux/io.h>
> >> +#include <linux/mbus.h>
> >> +#include <linux/of.h>
> >> +#include <linux/platform_device.h>
> >> +
> >> +#include "xhci.h"
> >> +
> >> +#define USB3_MAX_WINDOWS 4
> >> +#define USB3_WIN_CTRL(w) (0x0 + ((w) * 8))
> >> +#define USB3_WIN_BASE(w) (0x4 + ((w) * 8))
> >> +
> >> +static void __init mv_usb3_conf_mbus_windows(void __iomem *base,
> >> + const struct mbus_dram_target_info *dram)
> >> +{
> >> + int win;
> >> +
> >> + /* Clear all existing windows */
> >> + for (win = 0; win < USB3_MAX_WINDOWS; win++) {
> >> + writel(0, base + USB3_WIN_CTRL(win));
> >> + writel(0, base + USB3_WIN_BASE(win));
> >> + }
> >> +
> >> + /* Program each DRAM CS in a seperate window */
> >> + for (win = 0; win < dram->num_cs; win++) {
> >> + const struct mbus_dram_window *cs = dram->cs + win;
> >> +
> >> + writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) |
> >> + (dram->mbus_dram_target_id << 4) | 1,
> >> + base + USB3_WIN_CTRL(win));
> >> +
> >> + writel((cs->base & 0xffff0000), base + USB3_WIN_BASE(win));
> >> + }
> >> +}
> >> +
> >> +int xhci_mvebu_probe(struct platform_device *pdev)
> >> +{
> >> + struct resource *res;
> >> + void __iomem *base;
> >> + const struct mbus_dram_target_info *dram;
> >> + int ret;
> >> + struct clk *clk;
> >> +
> >> + res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> >> + if (!res)
> >> + return -ENODEV;
> >> +
> >> + /*
> >> + * We don't use devm_ioremap() because this mapping should
> >> + * only exists for the duration of this probe function.
> >> + */
> >> + base = ioremap(res->start, resource_size(res));
> >> + if (!base)
> >> + return -ENODEV;
> >> +
> >> + clk = devm_clk_get(&pdev->dev, NULL);
> >> + if (IS_ERR(clk)) {
> >> + iounmap(base);
> >> + return PTR_ERR(clk);
> >> + }
> >> +
> >> + ret = clk_prepare_enable(clk);
> >> + if (ret < 0) {
> >> + iounmap(base);
> >> + return ret;
> >> + }
> >
> > it's best to teach generic xhci-plat about clocks, just make it
> > optional.
>
> OK
>
> >
> >> + dram = mv_mbus_dram_info();
> >> + mv_usb3_conf_mbus_windows(base, dram);
> >> +
> >> + /*
> >> + * This memory area was only needed to configure the MBus
> >> + * windows, and is therefore no longer useful.
> >> + */
> >> + iounmap(base);
> >
> > so I suppose MBus is the Marvell interconnect, am I right ? Wouldn't you
> > be duplicating this sort of initialization for most drivers ?
>
> Actually most of them don't need it.
>
> >
> >> + ret = common_xhci_plat_probe(pdev, clk);
> >
> > I would much rather reverse this, instead of exposing xhci-plat's probe,
> > turn this mbus initialization into a quirk which will ioremap the extra
> > resource, initialize some registers and iounmap it.
>
> This approach have been inspired by what have been done for SDHCI and AHCI.
> The infrastructure allowing adding platform code is in the generic file but
> all the specific code is in the platform file.
>
> But if for USB you think we should do it in a different way, I will do it.

Yeah, I think it'll look slightly cleaner to have quirks called from
xhci-plat rather than having the quirk call into xhci-plat. Just look at
what *hci do on PCI-based platforms.

--
balbi


Attachments:
(No filename) (5.61 kB)
signature.asc (819.00 B)
Digital signature
Download all attachments