linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] ARM: Berlin: USB support
@ 2014-06-05 15:48 Antoine Ténart
  2014-06-05 15:48 ` [PATCH 1/9] reset: add the Berlin reset controller driver Antoine Ténart
                   ` (9 more replies)
  0 siblings, 10 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

This series adds the support for the Marvell Berlin USB controllers,
the USB PHYs and also adds a reset controller.

The reset controller is used by the USB PHY driver and shares the
existing chip controller node with the clocks and one pin controller.

The Marvell Berlin USB controllers are host only on the BG2Q and are
compatible with USB ChipIdea. We here add a glue to use the available
common functions for this kind of controllers. A USB PHY driver is also
added to control the PHY.

Antoine T?nart (9):
  reset: add the Berlin reset controller driver
  ARM: Berlin: select the reset controller
  ARM: dts: berlin: add a required reset property in the chip controller
    node
  usb: phy: add the Berlin USB PHY driver
  Documentation: bindings: add doc for the Berlin USB PHY
  usb: chipidea: add Berlin USB support
  Documentation: bindings: add doc for the Berlin ChipIdea USB driver
  ARM: dts: berlin: add BG2Q nodes for USB support
  ARM: dts: Berlin: enable USB on the BG2Q DMP

 .../devicetree/bindings/usb/berlin-usbphy.txt      |  18 ++
 .../devicetree/bindings/usb/ci-hdrc-berlin.txt     |  18 ++
 arch/arm/boot/dts/berlin2.dtsi                     |   1 +
 arch/arm/boot/dts/berlin2cd.dtsi                   |   1 +
 arch/arm/boot/dts/berlin2q-marvell-dmp.dts         |  20 ++
 arch/arm/boot/dts/berlin2q.dtsi                    |  52 +++++
 arch/arm/mach-berlin/Kconfig                       |   2 +
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-berlin.c                       | 113 +++++++++++
 drivers/usb/chipidea/Makefile                      |   1 +
 drivers/usb/chipidea/ci_hdrc_berlin.c              | 108 ++++++++++
 drivers/usb/phy/Kconfig                            |   9 +
 drivers/usb/phy/Makefile                           |   1 +
 drivers/usb/phy/phy-berlin-usb.c                   | 223 +++++++++++++++++++++
 14 files changed, 568 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/berlin-usbphy.txt
 create mode 100644 Documentation/devicetree/bindings/usb/ci-hdrc-berlin.txt
 create mode 100644 drivers/reset/reset-berlin.c
 create mode 100644 drivers/usb/chipidea/ci_hdrc_berlin.c
 create mode 100644 drivers/usb/phy/phy-berlin-usb.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/9] reset: add the Berlin reset controller driver
  2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
@ 2014-06-05 15:48 ` Antoine Ténart
  2014-06-05 16:36   ` Philipp Zabel
  2014-06-09 10:32   ` Sebastian Hesselbarth
  2014-06-05 15:48 ` [PATCH 2/9] ARM: Berlin: select the reset controller Antoine Ténart
                   ` (8 subsequent siblings)
  9 siblings, 2 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

Add a reset controller for Marvell Berlin SoCs which is used by the
USB PHYs drivers (for now).

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 drivers/reset/Makefile       |   1 +
 drivers/reset/reset-berlin.c | 113 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)
 create mode 100644 drivers/reset/reset-berlin.c

diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 4f60caf750ce..fffe2a3dd255 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_RESET_CONTROLLER) += core.o
+obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
 obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_ARCH_STI) += sti/
diff --git a/drivers/reset/reset-berlin.c b/drivers/reset/reset-berlin.c
new file mode 100644
index 000000000000..78b42c882cb2
--- /dev/null
+++ b/drivers/reset/reset-berlin.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine T?nart <antoine.tenart@free-electrons.com>
+ *
+ * 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/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#define BERLIN_RESET_REGISTER		0x104
+
+#define to_berlin_reset_priv(p)		\
+	container_of((p), struct berlin_reset_priv, rcdev)
+
+struct berlin_reset_priv {
+	spinlock_t			lock;
+	void __iomem			*base;
+	struct reset_controller_dev	rcdev;
+};
+
+static int berlin_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct berlin_reset_priv *priv = to_berlin_reset_priv(rcdev);
+	unsigned long flags;
+	int bank = id / BITS_PER_LONG;
+	int offset = id % BITS_PER_LONG;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	writel(BIT(offset), priv->base + bank * 4);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* let the reset be effective */
+	udelay(10);
+
+	return 0;
+}
+
+static struct reset_control_ops berlin_reset_ops = {
+	.reset	= berlin_reset_reset,
+};
+
+static int __berlin_reset_init(struct device_node *np)
+{
+	struct berlin_reset_priv *priv;
+	struct resource res;
+	resource_size_t size;
+	int ret;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	ret = of_address_to_resource(np, 0, &res);
+	if (ret)
+		goto err;
+
+	size = resource_size(&res);
+
+	priv->base = ioremap(res.start, size);
+	if (!priv->base) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	priv->base += BERLIN_RESET_REGISTER;
+
+	priv->rcdev.owner = THIS_MODULE;
+	priv->rcdev.nr_resets = size * 32;
+	priv->rcdev.ops = &berlin_reset_ops;
+	priv->rcdev.of_node = np;
+
+	reset_controller_register(&priv->rcdev);
+
+	return 0;
+
+err:
+	kfree(priv);
+	return ret;
+}
+
+static const struct of_device_id berlin_reset_of_match[] __initdata = {
+	{ .compatible = "marvell,berlin2q-chip-ctrl" },
+	{ },
+};
+
+static int __init berlin_reset_init(void)
+{
+	struct device_node *np;
+	int ret;
+
+	for_each_matching_node(np, berlin_reset_of_match) {
+		ret = __berlin_reset_init(np);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+arch_initcall(berlin_reset_init);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 2/9] ARM: Berlin: select the reset controller
  2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
  2014-06-05 15:48 ` [PATCH 1/9] reset: add the Berlin reset controller driver Antoine Ténart
@ 2014-06-05 15:48 ` Antoine Ténart
  2014-06-05 15:48 ` [PATCH 3/9] ARM: dts: berlin: add a required reset property in the chip controller node Antoine Ténart
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

The Marvell Berlin SoCs now has a reset controller. Add the needed
configuration.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 arch/arm/mach-berlin/Kconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-berlin/Kconfig b/arch/arm/mach-berlin/Kconfig
index 101e0f356730..d61b336951b5 100644
--- a/arch/arm/mach-berlin/Kconfig
+++ b/arch/arm/mach-berlin/Kconfig
@@ -1,11 +1,13 @@
 config ARCH_BERLIN
 	bool "Marvell Berlin SoCs" if ARCH_MULTI_V7
+	select ARCH_HAS_RESET_CONTROLLER
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_GIC
 	select GENERIC_IRQ_CHIP
 	select DW_APB_ICTL
 	select DW_APB_TIMER_OF
 	select PINCTRL
+	select RESET_CONTROLLER
 
 if ARCH_BERLIN
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 3/9] ARM: dts: berlin: add a required reset property in the chip controller node
  2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
  2014-06-05 15:48 ` [PATCH 1/9] reset: add the Berlin reset controller driver Antoine Ténart
  2014-06-05 15:48 ` [PATCH 2/9] ARM: Berlin: select the reset controller Antoine Ténart
@ 2014-06-05 15:48 ` Antoine Ténart
  2014-06-05 16:39   ` Philipp Zabel
  2014-06-05 15:48 ` [PATCH 4/9] usb: phy: add the Berlin USB PHY driver Antoine Ténart
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

The chip controller node now also describes the Marvell Berlin reset
controller. Add the required 'reset-cells' property.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2.dtsi   | 1 +
 arch/arm/boot/dts/berlin2cd.dtsi | 1 +
 arch/arm/boot/dts/berlin2q.dtsi  | 1 +
 3 files changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi
index 2477dac4d643..379ff1a38377 100644
--- a/arch/arm/boot/dts/berlin2.dtsi
+++ b/arch/arm/boot/dts/berlin2.dtsi
@@ -243,6 +243,7 @@
 		chip: chip-control at ea0000 {
 			compatible = "marvell,berlin2-chip-ctrl";
 			#clock-cells = <1>;
+			#reset-cells = <1>;
 			reg = <0xea0000 0x400>;
 			clocks = <&refclk>;
 			clock-names = "refclk";
diff --git a/arch/arm/boot/dts/berlin2cd.dtsi b/arch/arm/boot/dts/berlin2cd.dtsi
index cc1df65da504..50d6518b5744 100644
--- a/arch/arm/boot/dts/berlin2cd.dtsi
+++ b/arch/arm/boot/dts/berlin2cd.dtsi
@@ -231,6 +231,7 @@
 		chip: chip-control at ea0000 {
 			compatible = "marvell,berlin2cd-chip-ctrl";
 			#clock-cells = <1>;
+			#reset-cells = <1>;
 			reg = <0xea0000 0x400>;
 			clocks = <&refclk>;
 			clock-names = "refclk";
diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index 81712f5954ef..b74e5ec66354 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -274,6 +274,7 @@
 		chip: chip-control at ea0000 {
 			compatible = "marvell,berlin2q-chip-ctrl";
 			#clock-cells = <1>;
+			#reset-cells = <1>;
 			reg = <0xea0000 0x400>, <0xdd0170 0x10>;
 			clocks = <&refclk>;
 			clock-names = "refclk";
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 4/9] usb: phy: add the Berlin USB PHY driver
  2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
                   ` (2 preceding siblings ...)
  2014-06-05 15:48 ` [PATCH 3/9] ARM: dts: berlin: add a required reset property in the chip controller node Antoine Ténart
@ 2014-06-05 15:48 ` Antoine Ténart
  2014-06-06  6:39   ` Vivek Gautam
  2014-06-06 10:54   ` Sebastian Hesselbarth
  2014-06-05 15:48 ` [PATCH 5/9] Documentation: bindings: add doc for the Berlin USB PHY Antoine Ténart
                   ` (5 subsequent siblings)
  9 siblings, 2 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

Add the driver driving the Marvell Berlin USB PHY. This allows to
initialize the PHY and to use it from the USB driver later.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 drivers/usb/phy/Kconfig          |   9 ++
 drivers/usb/phy/Makefile         |   1 +
 drivers/usb/phy/phy-berlin-usb.c | 223 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 233 insertions(+)
 create mode 100644 drivers/usb/phy/phy-berlin-usb.c

diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 416e0c8cf6ff..8be8d4afc428 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -27,6 +27,15 @@ config AB8500_USB
 	  This transceiver supports high and full speed devices plus,
 	  in host mode, low speed.
 
+config BERLIN_USBPHY
+	tristate "Marvell Berlin USB Transceiver Driver"
+	depends on ARCH_BERLIN
+	select USB_PHY
+	help
+	  Enable this to support the USB tranceiver on Marvell Berlin
+	  SoCs.
+
+
 config FSL_USB2_OTG
 	bool "Freescale USB OTG Transceiver Driver"
 	depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM_RUNTIME
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index f8fa719a31b9..9253f59cf82a 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_OTG_FSM)		+= phy-fsm-usb.o
 # transceiver drivers, keep the list sorted
 
 obj-$(CONFIG_AB8500_USB)		+= phy-ab8500-usb.o
+obj-$(CONFIG_BERLIN_USBPHY)		+= phy-berlin-usb.o
 obj-$(CONFIG_FSL_USB2_OTG)		+= phy-fsl-usb.o
 obj-$(CONFIG_ISP1301_OMAP)		+= phy-isp1301-omap.o
 obj-$(CONFIG_MV_U3D_PHY)		+= phy-mv-u3d-usb.o
diff --git a/drivers/usb/phy/phy-berlin-usb.c b/drivers/usb/phy/phy-berlin-usb.c
new file mode 100644
index 000000000000..79416668a71b
--- /dev/null
+++ b/drivers/usb/phy/phy-berlin-usb.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine T?nart <antoine.tenart@free-electrons.com>
+ * Jisheng Zhang <jszhang@marvell.com>
+ *
+ * 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/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/usb/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#define USB_PHY_PLL		0x04
+#define USB_PHY_PLL_CONTROL	0x08
+#define USB_PHY_TX_CTRL0	0x10
+#define USB_PHY_TX_CTRL1	0x14
+#define USB_PHY_TX_CTRL2	0x18
+#define USB_PHY_RX_CTRL		0x20
+#define USB_PHY_ANALOG		0x34
+
+/* USB_PHY_PLL */
+#define CLK_REF_DIV(x)		((x) << 4)
+#define FEEDBACK_CLK_DIV(x)	((x) << 8)
+
+/* USB_PHY_PLL_CONTROL */
+#define CLK_STABLE		(0x1 << 0)
+#define PLL_CTRL_PIN		(0x1 << 1)
+#define PLL_CTRL_REG		(0x1 << 2)
+#define PLL_ON			(0x1 << 3)
+#define PHASE_OFF_TOL_125	(0x0 << 5)
+#define PHASE_OFF_TOL_250	(0x1 << 5)
+#define KVC0_CALIB		(0x0 << 9)
+#define KVC0_REG_CTRL		(0x1 << 9)
+#define KVC0_HIGH		(0x0 << 10)
+#define KVC0_LOW		(0x3 << 10)
+#define CLK_BLK_EN		(0x1 << 13)
+
+/* USB_PHY_TX_CTRL0 */
+#define EXT_HS_RCAL_EN		(0x1 << 3)
+#define EXT_FS_RCAL_EN		(0x1 << 4)
+#define IMPCAL_VTH_DIV(x)	((x) << 5)
+#define EXT_RS_RCAL_DIV(x)	((x) << 8)
+#define EXT_FS_RCAL_DIV(x)	((x) << 12)
+
+/* USB_PHY_TX_CTRL1 */
+#define TX_VDD15_14		(0x0 << 4)
+#define TX_VDD15_15		(0x1 << 4)
+#define TX_VDD15_16		(0x2 << 4)
+#define TX_VDD15_17		(0x3 << 4)
+#define TX_VDD12_VDD		(0x0 << 6)
+#define TX_VDD12_11		(0x1 << 6)
+#define TX_VDD12_12		(0x2 << 6)
+#define TX_VDD12_13		(0x3 << 6)
+#define LOW_VDD_EN		(0x1 << 8)
+#define TX_OUT_AMP(x)		((x) << 9)
+
+/* USB_PHY_TX_CTRL2 */
+#define TX_CHAN_CTRL_REG(x)	((x) << 0)
+#define DRV_SLEWRATE(x)		((x) << 4)
+#define IMP_CAL_FS_HS_DLY_0	(0x0 << 6)
+#define IMP_CAL_FS_HS_DLY_1	(0x1 << 6)
+#define IMP_CAL_FS_HS_DLY_2	(0x2 << 6)
+#define IMP_CAL_FS_HS_DLY_3	(0x3 << 6)
+#define FS_DRV_EN_MASK(x)	((x) << 8)
+#define HS_DRV_EN_MASK(x)	((x) << 12)
+
+/* USB_PHY_RX_CTRL */
+#define PHASE_FREEZE_DLY_2_CL	(0x0 << 0)
+#define PHASE_FREEZE_DLY_4_CL	(0x1 << 0)
+#define ACK_LENGTH_8_CL		(0x0 << 2)
+#define ACK_LENGTH_12_CL	(0x1 << 2)
+#define ACK_LENGTH_16_CL	(0x2 << 2)
+#define ACK_LENGTH_20_CL	(0x3 << 2)
+#define SQ_LENGTH_3		(0x0 << 4)
+#define SQ_LENGTH_6		(0x1 << 4)
+#define SQ_LENGTH_9		(0x2 << 4)
+#define SQ_LENGTH_12		(0x3 << 4)
+#define DISCON_THRESHOLD_260	(0x0 << 6)
+#define DISCON_THRESHOLD_270	(0x1 << 6)
+#define DISCON_THRESHOLD_280	(0x2 << 6)
+#define DISCON_THRESHOLD_290	(0x3 << 6)
+#define SQ_THRESHOLD(x)		((x) << 8)
+#define LPF_COEF(x)		((x) << 12)
+#define INTPL_CUR_10		(0x0 << 14)
+#define INTPL_CUR_20		(0x1 << 14)
+#define INTPL_CUR_30		(0x2 << 14)
+#define INTPL_CUR_40		(0x3 << 14)
+
+/* USB_PHY_ANALOG */
+#define ANA_PWR_UP		(0x1 << 1)
+#define ANA_PWR_DOWN		(0x1 << 2)
+#define V2I_VCO_RATIO(x)	((x) << 7)
+#define R_ROTATE_90		(0x0 << 10)
+#define R_ROTATE_0		(0x1 << 10)
+#define MODE_TEST_EN		(0x1 << 11)
+#define ANA_TEST_DC_CTRL(x)	((x) << 12)
+
+#define to_berlin_phy_priv(p)	container_of((p), struct berlin_phy_priv, phy)
+
+struct berlin_phy_priv {
+	void __iomem		*base;
+	struct usb_phy		phy;
+	struct reset_control	*rst_ctrl;
+	int			pwr_gpio;
+};
+
+static int berlin_phy_init(struct usb_phy *phy)
+{
+	struct berlin_phy_priv *priv = to_berlin_phy_priv(phy);
+	int ret;
+
+	reset_control_reset(priv->rst_ctrl);
+
+	writel(CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
+	       priv->base + USB_PHY_PLL);
+	writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 | KVC0_REG_CTRL |
+	       CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL);
+	writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5),
+	       priv->base + USB_PHY_ANALOG);
+	writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 |
+	       DISCON_THRESHOLD_260 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) |
+	       INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL);
+
+	writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base + USB_PHY_TX_CTRL1);
+	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
+	       priv->base + USB_PHY_TX_CTRL0);
+
+	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4) |
+	       EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0);
+
+	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
+	       priv->base + USB_PHY_TX_CTRL0);
+	writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) | IMP_CAL_FS_HS_DLY_3 |
+	       FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2);
+
+	ret = gpio_direction_output(priv->pwr_gpio, 0);
+	if (ret)
+		return ret;
+
+	gpio_set_value(priv->pwr_gpio, 1);
+
+	return 0;
+}
+
+static void berlin_phy_shutdown(struct usb_phy *phy)
+{
+	struct berlin_phy_priv *priv = to_berlin_phy_priv(phy);
+
+	gpio_set_value(priv->pwr_gpio, 0);
+}
+
+static int berlin_phy_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct berlin_phy_priv *priv;
+	struct resource *res;
+	int ret, gpio;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(priv->rst_ctrl)) {
+		ret = PTR_ERR(priv->rst_ctrl);
+		dev_err(&pdev->dev, "cannot get reset controller: %d\n", ret);
+		return ret;
+	}
+
+	gpio = of_get_named_gpio(np, "power-gpio", 0);
+	if (!gpio_is_valid(gpio))
+		return gpio;
+
+	ret = gpio_request(gpio, "power-gpio");
+	if (ret) {
+		dev_err(&pdev->dev, "cannot request GPIO %d", gpio);
+		return ret;
+	}
+	priv->pwr_gpio = gpio;
+
+	priv->phy.io_priv = priv->base;
+	priv->phy.dev = &pdev->dev;
+	priv->phy.label = "phy-berlin-usb";
+	priv->phy.init = berlin_phy_init;
+	priv->phy.shutdown = berlin_phy_shutdown;
+	priv->phy.type = USB_PHY_TYPE_USB2;
+
+	platform_set_drvdata(pdev, priv);
+
+	return usb_add_phy_dev(&priv->phy);
+}
+
+static const struct of_device_id phy_berlin_sata_of_match[] = {
+	{ .compatible = "marvell,berlin-usbphy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
+
+static struct platform_driver phy_berlin_usb_driver = {
+	.probe	= berlin_phy_probe,
+	.driver	= {
+		.name		= "phy-berlin-usb",
+		.owner		= THIS_MODULE,
+		.of_match_table	= phy_berlin_sata_of_match,
+	 },
+};
+module_platform_driver(phy_berlin_usb_driver);
+
+MODULE_AUTHOR("Antoine T?nart <antoine.tenart@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Berlin USB PHY driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 5/9] Documentation: bindings: add doc for the Berlin USB PHY
  2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
                   ` (3 preceding siblings ...)
  2014-06-05 15:48 ` [PATCH 4/9] usb: phy: add the Berlin USB PHY driver Antoine Ténart
@ 2014-06-05 15:48 ` Antoine Ténart
  2014-06-05 15:48 ` [PATCH 6/9] usb: chipidea: add Berlin USB support Antoine Ténart
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

Document the bindings of the Marvell Berlin USB PHY driver.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 .../devicetree/bindings/usb/berlin-usbphy.txt          | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/berlin-usbphy.txt

diff --git a/Documentation/devicetree/bindings/usb/berlin-usbphy.txt b/Documentation/devicetree/bindings/usb/berlin-usbphy.txt
new file mode 100644
index 000000000000..d97eb1f9d53f
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/berlin-usbphy.txt
@@ -0,0 +1,18 @@
+* Marvell Berlin USB PHY
+
+Required properties:
+- compatible: should be "marvell,berlin-usbphy"
+- reg: base address and length of the registers
+- #phys-cells: should be 0
+- reset: reference to the reset controller
+- power-gpio: reference the GPIO pin to power the PHY
+
+Example:
+
+	usbphy at f774000 {
+		compatible = "marvell,berlin-usbphy";
+		reg = <0xf774000 0x128>;
+		#phy-cells = <0>;
+		resets = <&chip 14>;
+		power-gpio = <&portb 8 GPIO_ACTIVE_HIGH>;
+	};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 6/9] usb: chipidea: add Berlin USB support
  2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
                   ` (4 preceding siblings ...)
  2014-06-05 15:48 ` [PATCH 5/9] Documentation: bindings: add doc for the Berlin USB PHY Antoine Ténart
@ 2014-06-05 15:48 ` Antoine Ténart
  2014-06-06 10:55   ` Sebastian Hesselbarth
  2014-06-05 15:48 ` [PATCH 7/9] Documentation: bindings: add doc for the Berlin ChipIdea USB driver Antoine Ténart
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

The Marvell Berlin USB controllers are compatible with ChipIdea. Add a
driver using the ChipIdea common functions to support them.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 drivers/usb/chipidea/Makefile         |   1 +
 drivers/usb/chipidea/ci_hdrc_berlin.c | 108 ++++++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)
 create mode 100644 drivers/usb/chipidea/ci_hdrc_berlin.c

diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
index 480bd4d5710a..b3a1b0b3b7a9 100644
--- a/drivers/usb/chipidea/Makefile
+++ b/drivers/usb/chipidea/Makefile
@@ -19,4 +19,5 @@ endif
 
 ifneq ($(CONFIG_OF),)
 	obj-$(CONFIG_USB_CHIPIDEA)	+= usbmisc_imx.o ci_hdrc_imx.o
+	obj-$(CONFIG_USB_CHIPIDEA)	+= ci_hdrc_berlin.o
 endif
diff --git a/drivers/usb/chipidea/ci_hdrc_berlin.c b/drivers/usb/chipidea/ci_hdrc_berlin.c
new file mode 100644
index 000000000000..567d83039e3e
--- /dev/null
+++ b/drivers/usb/chipidea/ci_hdrc_berlin.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine T?nart <antoine.tenart@free-electrons.com>
+ *
+ * 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/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/usb/chipidea.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/ulpi.h>
+
+#include "ci.h"
+
+struct ci_hdrc_berlin_priv {
+	struct platform_device	*ci_pdev;
+	struct clk		*clk;
+};
+
+static int ci_hdrc_berlin_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ci_hdrc_berlin_priv *priv;
+	struct ci_hdrc_platform_data ci_pdata = {
+		.name		= "ci_hdrc_berlin",
+		.capoffset	= DEF_CAPOFFSET,
+		.flags		= CI_HDRC_REQUIRE_TRANSCEIVER |
+				  CI_HDRC_DISABLE_STREAMING,
+	};
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(priv->clk));
+		return PTR_ERR(priv->clk);
+	}
+
+	ret = clk_prepare_enable(priv->clk);
+	if (ret)
+		return ret;
+
+	ci_pdata.phy = devm_usb_get_phy_by_phandle(dev, "marvell,usbphy", 0);
+	if (IS_ERR(ci_pdata.phy)) {
+		ret = PTR_ERR(ci_pdata.phy);
+		goto clk_err;
+	}
+
+	priv->ci_pdev = ci_hdrc_add_device(dev, pdev->resource,
+				     pdev->num_resources, &ci_pdata);
+	if (IS_ERR(priv->ci_pdev)) {
+		ret = PTR_ERR(priv->ci_pdev);
+		dev_err(dev,
+			"failed to register ci_hdrc platform device: %d\n",
+			ret);
+		goto clk_err;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	pm_runtime_no_callbacks(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+
+clk_err:
+	clk_disable_unprepare(priv->clk);
+	return ret;
+}
+
+static int ci_hdrc_berlin_remove(struct platform_device *pdev)
+{
+	struct ci_hdrc_berlin_priv *priv = platform_get_drvdata(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+	ci_hdrc_remove_device(priv->ci_pdev);
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static const struct of_device_id ci_hdrc_berlin_of_match[] = {
+	{ .compatible = "marvell,berlin-usb" },
+	{ }
+};
+
+static struct platform_driver ci_hdrc_berlin_driver = {
+	.probe	= ci_hdrc_berlin_probe,
+	.remove	= ci_hdrc_berlin_remove,
+	.driver	= {
+		.name		= "berlin-usb",
+		.owner		= THIS_MODULE,
+		.of_match_table	= ci_hdrc_berlin_of_match,
+	},
+};
+module_platform_driver(ci_hdrc_berlin_driver);
+
+MODULE_DESCRIPTION("ChipIdea HDRC Berlin USB binding");
+MODULE_AUTHOR("Antoine T?nart <antoine.tenart@free-electrons.com>");
+MODULE_LICENSE("GPL");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 7/9] Documentation: bindings: add doc for the Berlin ChipIdea USB driver
  2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
                   ` (5 preceding siblings ...)
  2014-06-05 15:48 ` [PATCH 6/9] usb: chipidea: add Berlin USB support Antoine Ténart
@ 2014-06-05 15:48 ` Antoine Ténart
  2014-06-05 15:48 ` [PATCH 8/9] ARM: dts: berlin: add BG2Q nodes for USB support Antoine Ténart
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

Document the Marvell Berlin USB driver bindings.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 .../devicetree/bindings/usb/ci-hdrc-berlin.txt         | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/ci-hdrc-berlin.txt

diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-berlin.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-berlin.txt
new file mode 100644
index 000000000000..a3fc9054b830
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-berlin.txt
@@ -0,0 +1,18 @@
+* Marvell Berlin usb controllers
+
+Required properties:
+- compatible: should be "marvell,berlin-usb"
+- reg: base address and length of the registers
+- interrupts: interrupt for the USB controller
+- clocks: reference to the USB clock
+- marvell,usbphy: reference to the USB PHY
+
+Example:
+
+	usb at f7ed0000 {
+		compatible = "marvell,berlin-usb";
+		reg = <0xf7ed0000 0x10000>;
+		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&chip CLKID_USB0>;
+		marvell,usbphy = <&usb_phy0>;
+	};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 8/9] ARM: dts: berlin: add BG2Q nodes for USB support
  2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
                   ` (6 preceding siblings ...)
  2014-06-05 15:48 ` [PATCH 7/9] Documentation: bindings: add doc for the Berlin ChipIdea USB driver Antoine Ténart
@ 2014-06-05 15:48 ` Antoine Ténart
  2014-06-05 15:48 ` [PATCH 9/9] ARM: dts: Berlin: enable USB on the BG2Q DMP Antoine Ténart
  2014-06-09  4:30 ` [PATCH 0/9] ARM: Berlin: USB support Peter Chen
  9 siblings, 0 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

Adds nodes describing the Marvell Berlin BG2Q USB PHY and USB. The BG2Q
SoC has 3 USB host controller, compatible with ChipIdea.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2q.dtsi | 51 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index b74e5ec66354..a6902ea5580c 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -87,6 +87,39 @@
 			#interrupt-cells = <3>;
 		};
 
+		usb_phy2: usbphy at a2f400 {
+			compatible = "marvell,berlin-usbphy";
+			reg = <0xa2f400 0x128>;
+			#phy-cells = <0>;
+			resets = <&chip 14>;
+			status = "disabled";
+		};
+
+		usb2: usb at a30000 {
+			compatible = "marvell,berlin-usb";
+			reg = <0xa30000 0x10000>;
+			interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&chip CLKID_USB2>;
+			marvell,usbphy = <&usb_phy2>;
+			status = "disabled";
+		};
+
+		usb_phy0: usbphy at b74000 {
+			compatible = "marvell,berlin-usbphy";
+			reg = <0xb74000 0x128>;
+			#phy-cells = <0>;
+			resets = <&chip 12>;
+			status = "disabled";
+		};
+
+		usb_phy1: usbphy at b78000 {
+			compatible = "marvell,berlin-usbphy";
+			reg = <0xb78000 0x128>;
+			#phy-cells = <0>;
+			resets = <&chip 13>;
+			status = "disabled";
+		};
+
 		apb at e80000 {
 			compatible = "simple-bus";
 			#address-cells = <1>;
@@ -280,6 +313,24 @@
 			clock-names = "refclk";
 		};
 
+		usb0: usb at ed0000 {
+			compatible = "marvell,berlin-usb";
+			reg = <0xed0000 0x10000>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&chip CLKID_USB0>;
+			marvell,usbphy = <&usb_phy0>;
+			status = "disabled";
+		};
+
+		usb1: usb at ee0000 {
+			compatible = "marvell,berlin-usb";
+			reg = <0xee0000 0x10000>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&chip CLKID_USB1>;
+			marvell,usbphy = <&usb_phy1>;
+			status = "disabled";
+		};
+
 		apb at fc0000 {
 			compatible = "simple-bus";
 			#address-cells = <1>;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 9/9] ARM: dts: Berlin: enable USB on the BG2Q DMP
  2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
                   ` (7 preceding siblings ...)
  2014-06-05 15:48 ` [PATCH 8/9] ARM: dts: berlin: add BG2Q nodes for USB support Antoine Ténart
@ 2014-06-05 15:48 ` Antoine Ténart
  2014-06-09  4:30 ` [PATCH 0/9] ARM: Berlin: USB support Peter Chen
  9 siblings, 0 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

Enable the 2 available USB PHY and USB nodes on the Marvell Berlin BG2Q
DMP.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2q-marvell-dmp.dts | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
index 2da9c41e29d8..4195874b9bed 100644
--- a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
+++ b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
@@ -7,6 +7,8 @@
  */
 
 /dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
 #include "berlin2q.dtsi"
 
 / {
@@ -26,3 +28,21 @@
 &uart0 {
 	status = "okay";
 };
+
+&usb_phy0 {
+	power-gpio = <&portb 8 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&usb_phy2 {
+	power-gpio = <&portb 12 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb2 {
+	status = "okay";
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 1/9] reset: add the Berlin reset controller driver
  2014-06-05 15:48 ` [PATCH 1/9] reset: add the Berlin reset controller driver Antoine Ténart
@ 2014-06-05 16:36   ` Philipp Zabel
  2014-06-05 16:56     ` Antoine Ténart
  2014-06-06 10:44     ` Sebastian Hesselbarth
  2014-06-09 10:32   ` Sebastian Hesselbarth
  1 sibling, 2 replies; 31+ messages in thread
From: Philipp Zabel @ 2014-06-05 16:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Antoine,

thank you for the patch. I have a few comments below.

Am Donnerstag, den 05.06.2014, 17:48 +0200 schrieb Antoine T?nart:
> Add a reset controller for Marvell Berlin SoCs which is used by the
> USB PHYs drivers (for now).
> 
> Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
> ---
>  drivers/reset/Makefile       |   1 +
>  drivers/reset/reset-berlin.c | 113 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 114 insertions(+)
>  create mode 100644 drivers/reset/reset-berlin.c
> 
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 4f60caf750ce..fffe2a3dd255 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_RESET_CONTROLLER) += core.o
> +obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
>  obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
>  obj-$(CONFIG_ARCH_STI) += sti/
> diff --git a/drivers/reset/reset-berlin.c b/drivers/reset/reset-berlin.c
> new file mode 100644
> index 000000000000..78b42c882cb2
> --- /dev/null
> +++ b/drivers/reset/reset-berlin.c
> @@ -0,0 +1,113 @@
> +/*
> + * Copyright (C) 2014 Marvell Technology Group Ltd.
> + *
> + * Antoine T?nart <antoine.tenart@free-electrons.com>
> + *
> + * 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/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>

Is there a reason this is not actually implemented as platform device?

> +#include <linux/reset-controller.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/types.h>
> +
> +#define BERLIN_RESET_REGISTER		0x104

How many reset registers are there? (See below).

> +#define to_berlin_reset_priv(p)		\
> +	container_of((p), struct berlin_reset_priv, rcdev)
> +
> +struct berlin_reset_priv {
> +	spinlock_t			lock;
> +	void __iomem			*base;
> +	struct reset_controller_dev	rcdev;
> +};
> +
> +static int berlin_reset_reset(struct reset_controller_dev *rcdev,
> +			      unsigned long id)
> +{
> +	struct berlin_reset_priv *priv = to_berlin_reset_priv(rcdev);
> +	unsigned long flags;
> +	int bank = id / BITS_PER_LONG;
> +	int offset = id % BITS_PER_LONG;
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +
> +	writel(BIT(offset), priv->base + bank * 4);
> +
> +	spin_unlock_irqrestore(&priv->lock, flags);

Since this is a single write into an apparently self-clearing
register, I see no need for the spinlock here.

> +	/* let the reset be effective */
> +	udelay(10);
> +
> +	return 0;
> +}
> +
> +static struct reset_control_ops berlin_reset_ops = {
> +	.reset	= berlin_reset_reset,
> +};
> +
> +static int __berlin_reset_init(struct device_node *np)
> +{
> +	struct berlin_reset_priv *priv;
> +	struct resource res;
> +	resource_size_t size;
> +	int ret;
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	ret = of_address_to_resource(np, 0, &res);
> +	if (ret)
> +		goto err;
> +
> +	size = resource_size(&res);
> +
> +	priv->base = ioremap(res.start, size);
> +	if (!priv->base) {
> +		ret = -ENOMEM;
> +		goto err;
> +	}

A platform driver could use devm_kzalloc, platform_get_resource,
and devm_ioremap_resource here.

> +	priv->base += BERLIN_RESET_REGISTER;
> +
> +	priv->rcdev.owner = THIS_MODULE;
> +	priv->rcdev.nr_resets = size * 32;

This doesn't seem right. The device tree patch shows that
size = 0x400.

> +	priv->rcdev.ops = &berlin_reset_ops;
> +	priv->rcdev.of_node = np;
> +
> +	reset_controller_register(&priv->rcdev);
> +
> +	return 0;
> +
> +err:
> +	kfree(priv);
> +	return ret;
> +}
> +
> +static const struct of_device_id berlin_reset_of_match[] __initdata = {
> +	{ .compatible = "marvell,berlin2q-chip-ctrl" },
> +	{ },
> +};
> +
> +static int __init berlin_reset_init(void)
> +{
> +	struct device_node *np;
> +	int ret;
> +
> +	for_each_matching_node(np, berlin_reset_of_match) {
> +		ret = __berlin_reset_init(np);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +arch_initcall(berlin_reset_init);

regards
Philipp

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 3/9] ARM: dts: berlin: add a required reset property in the chip controller node
  2014-06-05 15:48 ` [PATCH 3/9] ARM: dts: berlin: add a required reset property in the chip controller node Antoine Ténart
@ 2014-06-05 16:39   ` Philipp Zabel
  2014-06-05 16:44     ` Antoine Ténart
  0 siblings, 1 reply; 31+ messages in thread
From: Philipp Zabel @ 2014-06-05 16:39 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, den 05.06.2014, 17:48 +0200 schrieb Antoine T?nart:
> The chip controller node now also describes the Marvell Berlin reset
> controller. Add the required 'reset-cells' property.
> 
> Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
> ---
>  arch/arm/boot/dts/berlin2.dtsi   | 1 +
>  arch/arm/boot/dts/berlin2cd.dtsi | 1 +
>  arch/arm/boot/dts/berlin2q.dtsi  | 1 +
>  3 files changed, 3 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi
> index 2477dac4d643..379ff1a38377 100644
> --- a/arch/arm/boot/dts/berlin2.dtsi
> +++ b/arch/arm/boot/dts/berlin2.dtsi
> @@ -243,6 +243,7 @@
>  		chip: chip-control at ea0000 {
>  			compatible = "marvell,berlin2-chip-ctrl";
>  			#clock-cells = <1>;
> +			#reset-cells = <1>;

Are the marvell,berlin2q-chip-ctrl bindings already documented? This
should also be added to the documentation.

regards
Philipp

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 3/9] ARM: dts: berlin: add a required reset property in the chip controller node
  2014-06-05 16:39   ` Philipp Zabel
@ 2014-06-05 16:44     ` Antoine Ténart
  0 siblings, 0 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 16:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 05, 2014 at 06:39:07PM +0200, Philipp Zabel wrote:
> Am Donnerstag, den 05.06.2014, 17:48 +0200 schrieb Antoine T?nart:
> > The chip controller node now also describes the Marvell Berlin reset
> > controller. Add the required 'reset-cells' property.
> > 
> > Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
> > ---
> >  arch/arm/boot/dts/berlin2.dtsi   | 1 +
> >  arch/arm/boot/dts/berlin2cd.dtsi | 1 +
> >  arch/arm/boot/dts/berlin2q.dtsi  | 1 +
> >  3 files changed, 3 insertions(+)
> > 
> > diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi
> > index 2477dac4d643..379ff1a38377 100644
> > --- a/arch/arm/boot/dts/berlin2.dtsi
> > +++ b/arch/arm/boot/dts/berlin2.dtsi
> > @@ -243,6 +243,7 @@
> >  		chip: chip-control at ea0000 {
> >  			compatible = "marvell,berlin2-chip-ctrl";
> >  			#clock-cells = <1>;
> > +			#reset-cells = <1>;
> 
> Are the marvell,berlin2q-chip-ctrl bindings already documented? This
> should also be added to the documentation.

It is, I'll add information about its reset function.

Antoine

-- 
Antoine T?nart, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/9] reset: add the Berlin reset controller driver
  2014-06-05 16:36   ` Philipp Zabel
@ 2014-06-05 16:56     ` Antoine Ténart
  2014-06-06 10:44     ` Sebastian Hesselbarth
  1 sibling, 0 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-05 16:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Philipp,

On Thu, Jun 05, 2014 at 06:36:45PM +0200, Philipp Zabel wrote:
> > +#include <linux/platform_device.h>
> 
> Is there a reason this is not actually implemented as platform device?

The node describing this driver is shared with a pin controller and a
clock driver. The pin controller is implemented as a platform device. I
don't think we can have two platform device drivers using the device
tree for the same node. Or I'm maybe missing something.

> 
> > +#include <linux/reset-controller.h>
> > +#include <linux/slab.h>
> > +#include <linux/spinlock.h>
> > +#include <linux/types.h>
> > +
> > +#define BERLIN_RESET_REGISTER		0x104
> 
> How many reset registers are there? (See below).

I don't have lots of information about this. For now only the one used
to reset the USB PHY but others may come later.

> > +
> > +static int berlin_reset_reset(struct reset_controller_dev *rcdev,
> > +			      unsigned long id)
> > +{
> > +	struct berlin_reset_priv *priv = to_berlin_reset_priv(rcdev);
> > +	unsigned long flags;
> > +	int bank = id / BITS_PER_LONG;
> > +	int offset = id % BITS_PER_LONG;
> > +
> > +	spin_lock_irqsave(&priv->lock, flags);
> > +
> > +	writel(BIT(offset), priv->base + bank * 4);
> > +
> > +	spin_unlock_irqrestore(&priv->lock, flags);
> 
> Since this is a single write into an apparently self-clearing
> register, I see no need for the spinlock here.

Sure.

> 
> > +	/* let the reset be effective */
> > +	udelay(10);
> > +
> > +	return 0;
> > +}
> > +
> > +static struct reset_control_ops berlin_reset_ops = {
> > +	.reset	= berlin_reset_reset,
> > +};
> > +
> > +static int __berlin_reset_init(struct device_node *np)
> > +{
> > +	struct berlin_reset_priv *priv;
> > +	struct resource res;
> > +	resource_size_t size;
> > +	int ret;
> > +
> > +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	ret = of_address_to_resource(np, 0, &res);
> > +	if (ret)
> > +		goto err;
> > +
> > +	size = resource_size(&res);
> > +
> > +	priv->base = ioremap(res.start, size);
> > +	if (!priv->base) {
> > +		ret = -ENOMEM;
> > +		goto err;
> > +	}
> 
> A platform driver could use devm_kzalloc, platform_get_resource,
> and devm_ioremap_resource here.
> 
> > +	priv->base += BERLIN_RESET_REGISTER;
> > +
> > +	priv->rcdev.owner = THIS_MODULE;
> > +	priv->rcdev.nr_resets = size * 32;
> 
> This doesn't seem right. The device tree patch shows that
> size = 0x400.

The reg property is shared between drivers using the common chip
controller node. I do not know how many registers are actually used
to reset.

We then could hardcode the size, with the registers actually used here?


Thanks for the review!

Antoine

-- 
Antoine T?nart, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 4/9] usb: phy: add the Berlin USB PHY driver
  2014-06-05 15:48 ` [PATCH 4/9] usb: phy: add the Berlin USB PHY driver Antoine Ténart
@ 2014-06-06  6:39   ` Vivek Gautam
  2014-06-06  7:11     ` Antoine Ténart
  2014-06-06 10:54   ` Sebastian Hesselbarth
  1 sibling, 1 reply; 31+ messages in thread
From: Vivek Gautam @ 2014-06-06  6:39 UTC (permalink / raw)
  To: linux-arm-kernel

+ Kishon.


Hi,

On Thu, Jun 5, 2014 at 9:18 PM, Antoine T?nart
<antoine.tenart@free-electrons.com> wrote:
> Add the driver driving the Marvell Berlin USB PHY. This allows to
> initialize the PHY and to use it from the USB driver later.

Just out of curiosity, going forward we would like to have phy drivers based on
generic phy framework (drivers/phy).
Any particular reason that we are still adding phy drivers in usb-phy layer ?

Looking at it, seems like it can very well be written based on phy framework.

>
> Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
> ---
>  drivers/usb/phy/Kconfig          |   9 ++
>  drivers/usb/phy/Makefile         |   1 +
>  drivers/usb/phy/phy-berlin-usb.c | 223 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 233 insertions(+)
>  create mode 100644 drivers/usb/phy/phy-berlin-usb.c
>
> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
> index 416e0c8cf6ff..8be8d4afc428 100644
> --- a/drivers/usb/phy/Kconfig
> +++ b/drivers/usb/phy/Kconfig
> @@ -27,6 +27,15 @@ config AB8500_USB
>           This transceiver supports high and full speed devices plus,
>           in host mode, low speed.
>
> +config BERLIN_USBPHY
> +       tristate "Marvell Berlin USB Transceiver Driver"
> +       depends on ARCH_BERLIN
> +       select USB_PHY
> +       help
> +         Enable this to support the USB tranceiver on Marvell Berlin
> +         SoCs.
> +
> +
>  config FSL_USB2_OTG
>         bool "Freescale USB OTG Transceiver Driver"
>         depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM_RUNTIME
> diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
> index f8fa719a31b9..9253f59cf82a 100644
> --- a/drivers/usb/phy/Makefile
> +++ b/drivers/usb/phy/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_USB_OTG_FSM)               += phy-fsm-usb.o
>  # transceiver drivers, keep the list sorted
>
>  obj-$(CONFIG_AB8500_USB)               += phy-ab8500-usb.o
> +obj-$(CONFIG_BERLIN_USBPHY)            += phy-berlin-usb.o
>  obj-$(CONFIG_FSL_USB2_OTG)             += phy-fsl-usb.o
>  obj-$(CONFIG_ISP1301_OMAP)             += phy-isp1301-omap.o
>  obj-$(CONFIG_MV_U3D_PHY)               += phy-mv-u3d-usb.o
> diff --git a/drivers/usb/phy/phy-berlin-usb.c b/drivers/usb/phy/phy-berlin-usb.c
> new file mode 100644
> index 000000000000..79416668a71b
> --- /dev/null
> +++ b/drivers/usb/phy/phy-berlin-usb.c
> @@ -0,0 +1,223 @@
> +/*
> + * Copyright (C) 2014 Marvell Technology Group Ltd.
> + *
> + * Antoine T?nart <antoine.tenart@free-electrons.com>
> + * Jisheng Zhang <jszhang@marvell.com>
> + *
> + * 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/gpio.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_gpio.h>
> +#include <linux/usb/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +
> +#define USB_PHY_PLL            0x04
> +#define USB_PHY_PLL_CONTROL    0x08
> +#define USB_PHY_TX_CTRL0       0x10
> +#define USB_PHY_TX_CTRL1       0x14
> +#define USB_PHY_TX_CTRL2       0x18
> +#define USB_PHY_RX_CTRL                0x20
> +#define USB_PHY_ANALOG         0x34
> +
> +/* USB_PHY_PLL */
> +#define CLK_REF_DIV(x)         ((x) << 4)
> +#define FEEDBACK_CLK_DIV(x)    ((x) << 8)
> +
> +/* USB_PHY_PLL_CONTROL */
> +#define CLK_STABLE             (0x1 << 0)
> +#define PLL_CTRL_PIN           (0x1 << 1)
> +#define PLL_CTRL_REG           (0x1 << 2)
> +#define PLL_ON                 (0x1 << 3)
> +#define PHASE_OFF_TOL_125      (0x0 << 5)
> +#define PHASE_OFF_TOL_250      (0x1 << 5)
> +#define KVC0_CALIB             (0x0 << 9)
> +#define KVC0_REG_CTRL          (0x1 << 9)
> +#define KVC0_HIGH              (0x0 << 10)
> +#define KVC0_LOW               (0x3 << 10)
> +#define CLK_BLK_EN             (0x1 << 13)
> +
> +/* USB_PHY_TX_CTRL0 */
> +#define EXT_HS_RCAL_EN         (0x1 << 3)
> +#define EXT_FS_RCAL_EN         (0x1 << 4)
> +#define IMPCAL_VTH_DIV(x)      ((x) << 5)
> +#define EXT_RS_RCAL_DIV(x)     ((x) << 8)
> +#define EXT_FS_RCAL_DIV(x)     ((x) << 12)
> +
> +/* USB_PHY_TX_CTRL1 */
> +#define TX_VDD15_14            (0x0 << 4)
> +#define TX_VDD15_15            (0x1 << 4)
> +#define TX_VDD15_16            (0x2 << 4)
> +#define TX_VDD15_17            (0x3 << 4)
> +#define TX_VDD12_VDD           (0x0 << 6)
> +#define TX_VDD12_11            (0x1 << 6)
> +#define TX_VDD12_12            (0x2 << 6)
> +#define TX_VDD12_13            (0x3 << 6)
> +#define LOW_VDD_EN             (0x1 << 8)
> +#define TX_OUT_AMP(x)          ((x) << 9)
> +
> +/* USB_PHY_TX_CTRL2 */
> +#define TX_CHAN_CTRL_REG(x)    ((x) << 0)
> +#define DRV_SLEWRATE(x)                ((x) << 4)
> +#define IMP_CAL_FS_HS_DLY_0    (0x0 << 6)
> +#define IMP_CAL_FS_HS_DLY_1    (0x1 << 6)
> +#define IMP_CAL_FS_HS_DLY_2    (0x2 << 6)
> +#define IMP_CAL_FS_HS_DLY_3    (0x3 << 6)
> +#define FS_DRV_EN_MASK(x)      ((x) << 8)
> +#define HS_DRV_EN_MASK(x)      ((x) << 12)
> +
> +/* USB_PHY_RX_CTRL */
> +#define PHASE_FREEZE_DLY_2_CL  (0x0 << 0)
> +#define PHASE_FREEZE_DLY_4_CL  (0x1 << 0)
> +#define ACK_LENGTH_8_CL                (0x0 << 2)
> +#define ACK_LENGTH_12_CL       (0x1 << 2)
> +#define ACK_LENGTH_16_CL       (0x2 << 2)
> +#define ACK_LENGTH_20_CL       (0x3 << 2)
> +#define SQ_LENGTH_3            (0x0 << 4)
> +#define SQ_LENGTH_6            (0x1 << 4)
> +#define SQ_LENGTH_9            (0x2 << 4)
> +#define SQ_LENGTH_12           (0x3 << 4)
> +#define DISCON_THRESHOLD_260   (0x0 << 6)
> +#define DISCON_THRESHOLD_270   (0x1 << 6)
> +#define DISCON_THRESHOLD_280   (0x2 << 6)
> +#define DISCON_THRESHOLD_290   (0x3 << 6)
> +#define SQ_THRESHOLD(x)                ((x) << 8)
> +#define LPF_COEF(x)            ((x) << 12)
> +#define INTPL_CUR_10           (0x0 << 14)
> +#define INTPL_CUR_20           (0x1 << 14)
> +#define INTPL_CUR_30           (0x2 << 14)
> +#define INTPL_CUR_40           (0x3 << 14)
> +
> +/* USB_PHY_ANALOG */
> +#define ANA_PWR_UP             (0x1 << 1)
> +#define ANA_PWR_DOWN           (0x1 << 2)
> +#define V2I_VCO_RATIO(x)       ((x) << 7)
> +#define R_ROTATE_90            (0x0 << 10)
> +#define R_ROTATE_0             (0x1 << 10)
> +#define MODE_TEST_EN           (0x1 << 11)
> +#define ANA_TEST_DC_CTRL(x)    ((x) << 12)
> +
> +#define to_berlin_phy_priv(p)  container_of((p), struct berlin_phy_priv, phy)
> +
> +struct berlin_phy_priv {
> +       void __iomem            *base;
> +       struct usb_phy          phy;
> +       struct reset_control    *rst_ctrl;
> +       int                     pwr_gpio;
> +};
> +
> +static int berlin_phy_init(struct usb_phy *phy)
> +{
> +       struct berlin_phy_priv *priv = to_berlin_phy_priv(phy);
> +       int ret;
> +
> +       reset_control_reset(priv->rst_ctrl);
> +
> +       writel(CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
> +              priv->base + USB_PHY_PLL);
> +       writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 | KVC0_REG_CTRL |
> +              CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL);
> +       writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5),
> +              priv->base + USB_PHY_ANALOG);
> +       writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 |
> +              DISCON_THRESHOLD_260 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) |
> +              INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL);
> +
> +       writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base + USB_PHY_TX_CTRL1);
> +       writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
> +              priv->base + USB_PHY_TX_CTRL0);
> +
> +       writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4) |
> +              EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0);
> +
> +       writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
> +              priv->base + USB_PHY_TX_CTRL0);
> +       writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) | IMP_CAL_FS_HS_DLY_3 |
> +              FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2);
> +
> +       ret = gpio_direction_output(priv->pwr_gpio, 0);
> +       if (ret)
> +               return ret;
> +
> +       gpio_set_value(priv->pwr_gpio, 1);
> +
> +       return 0;
> +}
> +
> +static void berlin_phy_shutdown(struct usb_phy *phy)
> +{
> +       struct berlin_phy_priv *priv = to_berlin_phy_priv(phy);
> +
> +       gpio_set_value(priv->pwr_gpio, 0);
> +}
> +
> +static int berlin_phy_probe(struct platform_device *pdev)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +       struct berlin_phy_priv *priv;
> +       struct resource *res;
> +       int ret, gpio;
> +
> +       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       priv->base = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR(priv->base))
> +               return PTR_ERR(priv->base);
> +
> +       priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
> +       if (IS_ERR(priv->rst_ctrl)) {
> +               ret = PTR_ERR(priv->rst_ctrl);
> +               dev_err(&pdev->dev, "cannot get reset controller: %d\n", ret);
> +               return ret;
> +       }
> +
> +       gpio = of_get_named_gpio(np, "power-gpio", 0);
> +       if (!gpio_is_valid(gpio))
> +               return gpio;
> +
> +       ret = gpio_request(gpio, "power-gpio");
> +       if (ret) {
> +               dev_err(&pdev->dev, "cannot request GPIO %d", gpio);
> +               return ret;
> +       }
> +       priv->pwr_gpio = gpio;
> +
> +       priv->phy.io_priv = priv->base;
> +       priv->phy.dev = &pdev->dev;
> +       priv->phy.label = "phy-berlin-usb";
> +       priv->phy.init = berlin_phy_init;
> +       priv->phy.shutdown = berlin_phy_shutdown;
> +       priv->phy.type = USB_PHY_TYPE_USB2;
> +
> +       platform_set_drvdata(pdev, priv);
> +
> +       return usb_add_phy_dev(&priv->phy);
> +}
> +
> +static const struct of_device_id phy_berlin_sata_of_match[] = {
> +       { .compatible = "marvell,berlin-usbphy" },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
> +
> +static struct platform_driver phy_berlin_usb_driver = {
> +       .probe  = berlin_phy_probe,
> +       .driver = {
> +               .name           = "phy-berlin-usb",
> +               .owner          = THIS_MODULE,
> +               .of_match_table = phy_berlin_sata_of_match,
> +        },
> +};
> +module_platform_driver(phy_berlin_usb_driver);
> +
> +MODULE_AUTHOR("Antoine T?nart <antoine.tenart@free-electrons.com>");
> +MODULE_DESCRIPTION("Marvell Berlin USB PHY driver");
> +MODULE_LICENSE("GPL");
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 4/9] usb: phy: add the Berlin USB PHY driver
  2014-06-06  6:39   ` Vivek Gautam
@ 2014-06-06  7:11     ` Antoine Ténart
  2014-06-06 11:02       ` Vivek Gautam
  0 siblings, 1 reply; 31+ messages in thread
From: Antoine Ténart @ 2014-06-06  7:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Fri, Jun 06, 2014 at 12:09:06PM +0530, Vivek Gautam wrote:
> On Thu, Jun 5, 2014 at 9:18 PM, Antoine T?nart
> <antoine.tenart@free-electrons.com> wrote:
> > Add the driver driving the Marvell Berlin USB PHY. This allows to
> > initialize the PHY and to use it from the USB driver later.
> 
> Just out of curiosity, going forward we would like to have phy drivers based on
> generic phy framework (drivers/phy).
> Any particular reason that we are still adding phy drivers in usb-phy layer ?
> 
> Looking at it, seems like it can very well be written based on phy framework.

This USB controller are ChipIdea compatible, and the ChipIdea common
functions use the usb_phy framework. That's why this PHY driver is
there.

Antoine

-- 
Antoine T?nart, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/9] reset: add the Berlin reset controller driver
  2014-06-05 16:36   ` Philipp Zabel
  2014-06-05 16:56     ` Antoine Ténart
@ 2014-06-06 10:44     ` Sebastian Hesselbarth
  1 sibling, 0 replies; 31+ messages in thread
From: Sebastian Hesselbarth @ 2014-06-06 10:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/05/2014 06:36 PM, Philipp Zabel wrote:
> Am Donnerstag, den 05.06.2014, 17:48 +0200 schrieb Antoine T?nart:
>> Add a reset controller for Marvell Berlin SoCs which is used by the
>> USB PHYs drivers (for now).
>>
>> Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
>> ---
>>   drivers/reset/Makefile       |   1 +
>>   drivers/reset/reset-berlin.c | 113 +++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 114 insertions(+)
>>   create mode 100644 drivers/reset/reset-berlin.c
>>
[...]
>>   obj-$(CONFIG_ARCH_STI) += sti/
>> diff --git a/drivers/reset/reset-berlin.c b/drivers/reset/reset-berlin.c
>> new file mode 100644
>> index 000000000000..78b42c882cb2
>> --- /dev/null
>> +++ b/drivers/reset/reset-berlin.c
>> @@ -0,0 +1,113 @@
>> +/*
>> + * Copyright (C) 2014 Marvell Technology Group Ltd.
>> + *
>> + * Antoine T?nart <antoine.tenart@free-electrons.com>
>> + *
>> + * 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/delay.h>
>> +#include <linux/io.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/platform_device.h>
>
> Is there a reason this is not actually implemented as platform device?
>
[...]
>> +static int __berlin_reset_init(struct device_node *np)
>> +{
>> +	struct berlin_reset_priv *priv;
>> +	struct resource res;
>> +	resource_size_t size;
>> +	int ret;
>> +
>> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
>> +	if (!priv)
>> +		return -ENOMEM;
>> +
>> +	ret = of_address_to_resource(np, 0, &res);
>> +	if (ret)
>> +		goto err;
>> +
>> +	size = resource_size(&res);
>> +
>> +	priv->base = ioremap(res.start, size);
>> +	if (!priv->base) {
>> +		ret = -ENOMEM;
>> +		goto err;
>> +	}
>
> A platform driver could use devm_kzalloc, platform_get_resource,
> and devm_ioremap_resource here.
>
>> +	priv->base += BERLIN_RESET_REGISTER;
>> +
>> +	priv->rcdev.owner = THIS_MODULE;
>> +	priv->rcdev.nr_resets = size * 32;
>
> This doesn't seem right. The device tree patch shows that
> size = 0x400.

Actually, not using a platform_device now is the outcome of
some late DT node rework we had for the clock driver. The reason
we only have one node for the whole register set providing
pinctrl, reset, clock, ... is that it would require tiny separate
register ranges spread over the whole register set.

Instead, the idea is to have a single DT node, register a
driver providing a mmio regmap, and registering individual
platform_devices for the non-early drivers using the regmap.
We also evaluated syscon, but it will require dummy nodes for
each proper platform_device and that is something we really
want to avoid here.

Of course, writing that driver is delayed on my side because
of other non-Linux stuff that has to be taken care of first.
As I cannot tell how much time I can spend on it now, I prefer
to take this as is and provide update patches as soon as I have
worked out the regset driver.

Sebastian

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 4/9] usb: phy: add the Berlin USB PHY driver
  2014-06-05 15:48 ` [PATCH 4/9] usb: phy: add the Berlin USB PHY driver Antoine Ténart
  2014-06-06  6:39   ` Vivek Gautam
@ 2014-06-06 10:54   ` Sebastian Hesselbarth
  2014-06-06 11:59     ` Antoine Ténart
  2014-06-09  8:26     ` Jisheng Zhang
  1 sibling, 2 replies; 31+ messages in thread
From: Sebastian Hesselbarth @ 2014-06-06 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/05/2014 05:48 PM, Antoine T?nart wrote:
> Add the driver driving the Marvell Berlin USB PHY. This allows to
> initialize the PHY and to use it from the USB driver later.
>
> Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
> ---
>   drivers/usb/phy/Kconfig          |   9 ++
>   drivers/usb/phy/Makefile         |   1 +
>   drivers/usb/phy/phy-berlin-usb.c | 223 +++++++++++++++++++++++++++++++++++++++
>   3 files changed, 233 insertions(+)
>   create mode 100644 drivers/usb/phy/phy-berlin-usb.c
>
[...]
> diff --git a/drivers/usb/phy/phy-berlin-usb.c b/drivers/usb/phy/phy-berlin-usb.c
> new file mode 100644
> index 000000000000..79416668a71b
> --- /dev/null
> +++ b/drivers/usb/phy/phy-berlin-usb.c
> @@ -0,0 +1,223 @@
> +/*
> + * Copyright (C) 2014 Marvell Technology Group Ltd.
> + *
> + * Antoine T?nart <antoine.tenart@free-electrons.com>
> + * Jisheng Zhang <jszhang@marvell.com>
> + *
> + * 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/gpio.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_gpio.h>
> +#include <linux/usb/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>

nit: keep above alphabetically sorted.

> +#define USB_PHY_PLL		0x04
> +#define USB_PHY_PLL_CONTROL	0x08
> +#define USB_PHY_TX_CTRL0	0x10
> +#define USB_PHY_TX_CTRL1	0x14
> +#define USB_PHY_TX_CTRL2	0x18
> +#define USB_PHY_RX_CTRL		0x20
> +#define USB_PHY_ANALOG		0x34
> +
> +/* USB_PHY_PLL */
> +#define CLK_REF_DIV(x)		((x) << 4)
> +#define FEEDBACK_CLK_DIV(x)	((x) << 8)
> +
> +/* USB_PHY_PLL_CONTROL */
> +#define CLK_STABLE		(0x1 << 0)
> +#define PLL_CTRL_PIN		(0x1 << 1)
> +#define PLL_CTRL_REG		(0x1 << 2)
> +#define PLL_ON			(0x1 << 3)
> +#define PHASE_OFF_TOL_125	(0x0 << 5)
> +#define PHASE_OFF_TOL_250	(0x1 << 5)
> +#define KVC0_CALIB		(0x0 << 9)
> +#define KVC0_REG_CTRL		(0x1 << 9)
> +#define KVC0_HIGH		(0x0 << 10)
> +#define KVC0_LOW		(0x3 << 10)
> +#define CLK_BLK_EN		(0x1 << 13)

BIT() for the single bit flags above and below.

> +/* USB_PHY_TX_CTRL0 */
> +#define EXT_HS_RCAL_EN		(0x1 << 3)
> +#define EXT_FS_RCAL_EN		(0x1 << 4)
> +#define IMPCAL_VTH_DIV(x)	((x) << 5)
> +#define EXT_RS_RCAL_DIV(x)	((x) << 8)
> +#define EXT_FS_RCAL_DIV(x)	((x) << 12)
> +
> +/* USB_PHY_TX_CTRL1 */
> +#define TX_VDD15_14		(0x0 << 4)
> +#define TX_VDD15_15		(0x1 << 4)
> +#define TX_VDD15_16		(0x2 << 4)
> +#define TX_VDD15_17		(0x3 << 4)
> +#define TX_VDD12_VDD		(0x0 << 6)
> +#define TX_VDD12_11		(0x1 << 6)
> +#define TX_VDD12_12		(0x2 << 6)
> +#define TX_VDD12_13		(0x3 << 6)
> +#define LOW_VDD_EN		(0x1 << 8)
> +#define TX_OUT_AMP(x)		((x) << 9)
> +
> +/* USB_PHY_TX_CTRL2 */
> +#define TX_CHAN_CTRL_REG(x)	((x) << 0)
> +#define DRV_SLEWRATE(x)		((x) << 4)
> +#define IMP_CAL_FS_HS_DLY_0	(0x0 << 6)
> +#define IMP_CAL_FS_HS_DLY_1	(0x1 << 6)
> +#define IMP_CAL_FS_HS_DLY_2	(0x2 << 6)
> +#define IMP_CAL_FS_HS_DLY_3	(0x3 << 6)
> +#define FS_DRV_EN_MASK(x)	((x) << 8)
> +#define HS_DRV_EN_MASK(x)	((x) << 12)
> +
> +/* USB_PHY_RX_CTRL */
> +#define PHASE_FREEZE_DLY_2_CL	(0x0 << 0)
> +#define PHASE_FREEZE_DLY_4_CL	(0x1 << 0)
> +#define ACK_LENGTH_8_CL		(0x0 << 2)
> +#define ACK_LENGTH_12_CL	(0x1 << 2)
> +#define ACK_LENGTH_16_CL	(0x2 << 2)
> +#define ACK_LENGTH_20_CL	(0x3 << 2)
> +#define SQ_LENGTH_3		(0x0 << 4)
> +#define SQ_LENGTH_6		(0x1 << 4)
> +#define SQ_LENGTH_9		(0x2 << 4)
> +#define SQ_LENGTH_12		(0x3 << 4)
> +#define DISCON_THRESHOLD_260	(0x0 << 6)
> +#define DISCON_THRESHOLD_270	(0x1 << 6)
> +#define DISCON_THRESHOLD_280	(0x2 << 6)
> +#define DISCON_THRESHOLD_290	(0x3 << 6)
> +#define SQ_THRESHOLD(x)		((x) << 8)
> +#define LPF_COEF(x)		((x) << 12)
> +#define INTPL_CUR_10		(0x0 << 14)
> +#define INTPL_CUR_20		(0x1 << 14)
> +#define INTPL_CUR_30		(0x2 << 14)
> +#define INTPL_CUR_40		(0x3 << 14)
> +
> +/* USB_PHY_ANALOG */
> +#define ANA_PWR_UP		(0x1 << 1)
> +#define ANA_PWR_DOWN		(0x1 << 2)
> +#define V2I_VCO_RATIO(x)	((x) << 7)
> +#define R_ROTATE_90		(0x0 << 10)
> +#define R_ROTATE_0		(0x1 << 10)
> +#define MODE_TEST_EN		(0x1 << 11)
> +#define ANA_TEST_DC_CTRL(x)	((x) << 12)
> +
> +#define to_berlin_phy_priv(p)	container_of((p), struct berlin_phy_priv, phy)
> +
> +struct berlin_phy_priv {
> +	void __iomem		*base;
> +	struct usb_phy		phy;
> +	struct reset_control	*rst_ctrl;
> +	int			pwr_gpio;

Is the GPIO used for USB power? If so, we should not rely on
GPIO at all but use regulator API. Thinking of Chromecast which
is externally powered over USB, there will be no regulator nor
GPIO at all.

> +};
> +
> +static int berlin_phy_init(struct usb_phy *phy)
> +{
> +	struct berlin_phy_priv *priv = to_berlin_phy_priv(phy);
> +	int ret;
> +
> +	reset_control_reset(priv->rst_ctrl);
> +
> +	writel(CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
> +	       priv->base + USB_PHY_PLL);

@Jisheng: IIRC the dividers above are different for BG2? Can you please
evaluate?

> +	writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 | KVC0_REG_CTRL |
> +	       CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL);
> +	writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5),
> +	       priv->base + USB_PHY_ANALOG);
> +	writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 |
> +	       DISCON_THRESHOLD_260 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) |
> +	       INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL);
> +
> +	writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base + USB_PHY_TX_CTRL1);
> +	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
> +	       priv->base + USB_PHY_TX_CTRL0);
> +
> +	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4) |
> +	       EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0);
> +
> +	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
> +	       priv->base + USB_PHY_TX_CTRL0);
> +	writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) | IMP_CAL_FS_HS_DLY_3 |
> +	       FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2);
> +
> +	ret = gpio_direction_output(priv->pwr_gpio, 0);

As mentioned above, this should be using regulator API. And also, if
there is no dummy regulator allowed, it should be optional.

> +	if (ret)
> +		return ret;
> +
> +	gpio_set_value(priv->pwr_gpio, 1);
> +
> +	return 0;
> +}
> +
> +static void berlin_phy_shutdown(struct usb_phy *phy)
> +{
> +	struct berlin_phy_priv *priv = to_berlin_phy_priv(phy);
> +
> +	gpio_set_value(priv->pwr_gpio, 0);
> +}
> +
> +static int berlin_phy_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct berlin_phy_priv *priv;
> +	struct resource *res;
> +	int ret, gpio;
> +
> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	priv->base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(priv->base))
> +		return PTR_ERR(priv->base);
> +
> +	priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
> +	if (IS_ERR(priv->rst_ctrl)) {
> +		ret = PTR_ERR(priv->rst_ctrl);
> +		dev_err(&pdev->dev, "cannot get reset controller: %d\n", ret);

Hmm, considering a non arch_init call registered reset driver, it does
also spit out an error for -EPROBE_DEFER, does it?

> +		return ret;
> +	}
> +
> +	gpio = of_get_named_gpio(np, "power-gpio", 0);
> +	if (!gpio_is_valid(gpio))
> +		return gpio;
> +
> +	ret = gpio_request(gpio, "power-gpio");
> +	if (ret) {
> +		dev_err(&pdev->dev, "cannot request GPIO %d", gpio);
> +		return ret;
> +	}
> +	priv->pwr_gpio = gpio;
> +
> +	priv->phy.io_priv = priv->base;
> +	priv->phy.dev = &pdev->dev;
> +	priv->phy.label = "phy-berlin-usb";
> +	priv->phy.init = berlin_phy_init;
> +	priv->phy.shutdown = berlin_phy_shutdown;
> +	priv->phy.type = USB_PHY_TYPE_USB2;
> +
> +	platform_set_drvdata(pdev, priv);
> +
> +	return usb_add_phy_dev(&priv->phy);
> +}
> +
> +static const struct of_device_id phy_berlin_sata_of_match[] = {
> +	{ .compatible = "marvell,berlin-usbphy" },

If we need to distinguish BG2 and later SoCs, we either need two
different compatibles. Or we just have a vendor specific property
describing the divider values above.

Sebastian

> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
> +
> +static struct platform_driver phy_berlin_usb_driver = {
> +	.probe	= berlin_phy_probe,
> +	.driver	= {
> +		.name		= "phy-berlin-usb",
> +		.owner		= THIS_MODULE,
> +		.of_match_table	= phy_berlin_sata_of_match,
> +	 },
> +};
> +module_platform_driver(phy_berlin_usb_driver);
> +
> +MODULE_AUTHOR("Antoine T?nart <antoine.tenart@free-electrons.com>");
> +MODULE_DESCRIPTION("Marvell Berlin USB PHY driver");
> +MODULE_LICENSE("GPL");
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 6/9] usb: chipidea: add Berlin USB support
  2014-06-05 15:48 ` [PATCH 6/9] usb: chipidea: add Berlin USB support Antoine Ténart
@ 2014-06-06 10:55   ` Sebastian Hesselbarth
  2014-06-06 12:01     ` Antoine Ténart
  0 siblings, 1 reply; 31+ messages in thread
From: Sebastian Hesselbarth @ 2014-06-06 10:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/05/2014 05:48 PM, Antoine T?nart wrote:
> The Marvell Berlin USB controllers are compatible with ChipIdea. Add a
> driver using the ChipIdea common functions to support them.
>
> Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
> ---
>   drivers/usb/chipidea/Makefile         |   1 +
>   drivers/usb/chipidea/ci_hdrc_berlin.c | 108 ++++++++++++++++++++++++++++++++++
>   2 files changed, 109 insertions(+)
>   create mode 100644 drivers/usb/chipidea/ci_hdrc_berlin.c
>
> diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
> index 480bd4d5710a..b3a1b0b3b7a9 100644
> --- a/drivers/usb/chipidea/Makefile
> +++ b/drivers/usb/chipidea/Makefile
> @@ -19,4 +19,5 @@ endif
>
>   ifneq ($(CONFIG_OF),)
>   	obj-$(CONFIG_USB_CHIPIDEA)	+= usbmisc_imx.o ci_hdrc_imx.o
> +	obj-$(CONFIG_USB_CHIPIDEA)	+= ci_hdrc_berlin.o
>   endif
> diff --git a/drivers/usb/chipidea/ci_hdrc_berlin.c b/drivers/usb/chipidea/ci_hdrc_berlin.c
> new file mode 100644
> index 000000000000..567d83039e3e
> --- /dev/null
> +++ b/drivers/usb/chipidea/ci_hdrc_berlin.c
> @@ -0,0 +1,108 @@
> +/*
> + * Copyright (C) 2014 Marvell Technology Group Ltd.
> + *
> + * Antoine T?nart <antoine.tenart@free-electrons.com>
> + *
> + * 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/clk.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/usb/chipidea.h>
> +#include <linux/usb/hcd.h>
> +#include <linux/usb/ulpi.h>
> +
> +#include "ci.h"
> +
> +struct ci_hdrc_berlin_priv {
> +	struct platform_device	*ci_pdev;
> +	struct clk		*clk;
> +};
> +
> +static int ci_hdrc_berlin_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct ci_hdrc_berlin_priv *priv;
> +	struct ci_hdrc_platform_data ci_pdata = {
> +		.name		= "ci_hdrc_berlin",
> +		.capoffset	= DEF_CAPOFFSET,
> +		.flags		= CI_HDRC_REQUIRE_TRANSCEIVER |
> +				  CI_HDRC_DISABLE_STREAMING,
> +	};
> +	int ret;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(priv->clk)) {
> +		dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(priv->clk));
> +		return PTR_ERR(priv->clk);
> +	}
> +
> +	ret = clk_prepare_enable(priv->clk);
> +	if (ret)
> +		return ret;
> +
> +	ci_pdata.phy = devm_usb_get_phy_by_phandle(dev, "marvell,usbphy", 0);
> +	if (IS_ERR(ci_pdata.phy)) {
> +		ret = PTR_ERR(ci_pdata.phy);
> +		goto clk_err;
> +	}
> +
> +	priv->ci_pdev = ci_hdrc_add_device(dev, pdev->resource,
> +				     pdev->num_resources, &ci_pdata);
> +	if (IS_ERR(priv->ci_pdev)) {
> +		ret = PTR_ERR(priv->ci_pdev);
> +		dev_err(dev,
> +			"failed to register ci_hdrc platform device: %d\n",
> +			ret);
> +		goto clk_err;
> +	}
> +
> +	platform_set_drvdata(pdev, priv);
> +
> +	pm_runtime_no_callbacks(dev);
> +	pm_runtime_enable(dev);
> +
> +	return 0;
> +
> +clk_err:
> +	clk_disable_unprepare(priv->clk);
> +	return ret;
> +}
> +
> +static int ci_hdrc_berlin_remove(struct platform_device *pdev)
> +{
> +	struct ci_hdrc_berlin_priv *priv = platform_get_drvdata(pdev);
> +
> +	pm_runtime_disable(&pdev->dev);
> +	ci_hdrc_remove_device(priv->ci_pdev);
> +	clk_disable_unprepare(priv->clk);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id ci_hdrc_berlin_of_match[] = {
> +	{ .compatible = "marvell,berlin-usb" },

Looking at the driver, I can see no Berlin-specific code at all. Maybe
we just take the chance and have a generic chipidea boiler plate driver
now?

Sebastian

> +	{ }
> +};
> +
> +static struct platform_driver ci_hdrc_berlin_driver = {
> +	.probe	= ci_hdrc_berlin_probe,
> +	.remove	= ci_hdrc_berlin_remove,
> +	.driver	= {
> +		.name		= "berlin-usb",
> +		.owner		= THIS_MODULE,
> +		.of_match_table	= ci_hdrc_berlin_of_match,
> +	},
> +};
> +module_platform_driver(ci_hdrc_berlin_driver);
> +
> +MODULE_DESCRIPTION("ChipIdea HDRC Berlin USB binding");
> +MODULE_AUTHOR("Antoine T?nart <antoine.tenart@free-electrons.com>");
> +MODULE_LICENSE("GPL");
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 4/9] usb: phy: add the Berlin USB PHY driver
  2014-06-06  7:11     ` Antoine Ténart
@ 2014-06-06 11:02       ` Vivek Gautam
  2014-06-19 13:45         ` Felipe Balbi
  0 siblings, 1 reply; 31+ messages in thread
From: Vivek Gautam @ 2014-06-06 11:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Fri, Jun 6, 2014 at 12:41 PM, Antoine T?nart
<antoine.tenart@free-electrons.com> wrote:
> Hi,
>
> On Fri, Jun 06, 2014 at 12:09:06PM +0530, Vivek Gautam wrote:
>> On Thu, Jun 5, 2014 at 9:18 PM, Antoine T?nart
>> <antoine.tenart@free-electrons.com> wrote:
>> > Add the driver driving the Marvell Berlin USB PHY. This allows to
>> > initialize the PHY and to use it from the USB driver later.
>>
>> Just out of curiosity, going forward we would like to have phy drivers based on
>> generic phy framework (drivers/phy).
>> Any particular reason that we are still adding phy drivers in usb-phy layer ?
>>
>> Looking at it, seems like it can very well be written based on phy framework.
>
> This USB controller are ChipIdea compatible, and the ChipIdea common
> functions use the usb_phy framework. That's why this PHY driver is
> there.

Ok, i see that now. In that case shouldn't we be moving even the chipidea
drivers to use the generic phy functions to get the phy and init/exit it.

I think Felipe and Kishon can comment on this better, and tell how
things should be. :-)

[snip]


-- 
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 4/9] usb: phy: add the Berlin USB PHY driver
  2014-06-06 10:54   ` Sebastian Hesselbarth
@ 2014-06-06 11:59     ` Antoine Ténart
  2014-06-09  8:26     ` Jisheng Zhang
  1 sibling, 0 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-06 11:59 UTC (permalink / raw)
  To: linux-arm-kernel

Sebastian,

On Fri, Jun 06, 2014 at 12:54:06PM +0200, Sebastian Hesselbarth wrote:
> On 06/05/2014 05:48 PM, Antoine T?nart wrote:
> >+
> >+#include <linux/gpio.h>
> >+#include <linux/io.h>
> >+#include <linux/module.h>
> >+#include <linux/of_gpio.h>
> >+#include <linux/usb/phy.h>
> >+#include <linux/platform_device.h>
> >+#include <linux/reset.h>
> 
> nit: keep above alphabetically sorted.

Oops. Sure.

> >+
> >+/* USB_PHY_PLL */
> >+#define CLK_REF_DIV(x)		((x) << 4)
> >+#define FEEDBACK_CLK_DIV(x)	((x) << 8)
> >+
> >+/* USB_PHY_PLL_CONTROL */
> >+#define CLK_STABLE		(0x1 << 0)
> >+#define PLL_CTRL_PIN		(0x1 << 1)
> >+#define PLL_CTRL_REG		(0x1 << 2)
> >+#define PLL_ON			(0x1 << 3)
> >+#define PHASE_OFF_TOL_125	(0x0 << 5)
> >+#define PHASE_OFF_TOL_250	(0x1 << 5)
> >+#define KVC0_CALIB		(0x0 << 9)
> >+#define KVC0_REG_CTRL		(0x1 << 9)
> >+#define KVC0_HIGH		(0x0 << 10)
> >+#define KVC0_LOW		(0x3 << 10)
> >+#define CLK_BLK_EN		(0x1 << 13)
> 
> BIT() for the single bit flags above and below.

I'll update with BIT().

> >+
> >+struct berlin_phy_priv {
> >+	void __iomem		*base;
> >+	struct usb_phy		phy;
> >+	struct reset_control	*rst_ctrl;
> >+	int			pwr_gpio;
> 
> Is the GPIO used for USB power? If so, we should not rely on
> GPIO at all but use regulator API. Thinking of Chromecast which
> is externally powered over USB, there will be no regulator nor
> GPIO at all.

[?]

> 
> As mentioned above, this should be using regulator API. And also, if
> there is no dummy regulator allowed, it should be optional.

I'll make this optional.

> 
> >+static int berlin_phy_probe(struct platform_device *pdev)
> >+{
> >+	struct device_node *np = pdev->dev.of_node;
> >+	struct berlin_phy_priv *priv;
> >+	struct resource *res;
> >+	int ret, gpio;
> >+
> >+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> >+	if (!priv)
> >+		return -ENOMEM;
> >+
> >+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >+	priv->base = devm_ioremap_resource(&pdev->dev, res);
> >+	if (IS_ERR(priv->base))
> >+		return PTR_ERR(priv->base);
> >+
> >+	priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
> >+	if (IS_ERR(priv->rst_ctrl)) {
> >+		ret = PTR_ERR(priv->rst_ctrl);
> >+		dev_err(&pdev->dev, "cannot get reset controller: %d\n", ret);
> 
> Hmm, considering a non arch_init call registered reset driver, it does
> also spit out an error for -EPROBE_DEFER, does it?

Yes, it does.


Antoine

-- 
Antoine T?nart, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 6/9] usb: chipidea: add Berlin USB support
  2014-06-06 10:55   ` Sebastian Hesselbarth
@ 2014-06-06 12:01     ` Antoine Ténart
  0 siblings, 0 replies; 31+ messages in thread
From: Antoine Ténart @ 2014-06-06 12:01 UTC (permalink / raw)
  To: linux-arm-kernel

Sebastian,

On Fri, Jun 06, 2014 at 12:55:54PM +0200, Sebastian Hesselbarth wrote:
> On 06/05/2014 05:48 PM, Antoine T?nart wrote:
> >+
> >+static const struct of_device_id ci_hdrc_berlin_of_match[] = {
> >+	{ .compatible = "marvell,berlin-usb" },
> 
> Looking at the driver, I can see no Berlin-specific code at all. Maybe
> we just take the chance and have a generic chipidea boiler plate driver
> now?

This driver does nothing special. If we define the PHY and the clock
properties as optional, we can do a generic driver here.


Antoine

-- 
Antoine T?nart, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 0/9] ARM: Berlin: USB support
  2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
                   ` (8 preceding siblings ...)
  2014-06-05 15:48 ` [PATCH 9/9] ARM: dts: Berlin: enable USB on the BG2Q DMP Antoine Ténart
@ 2014-06-09  4:30 ` Peter Chen
  2014-06-09 10:14   ` Sebastian Hesselbarth
  9 siblings, 1 reply; 31+ messages in thread
From: Peter Chen @ 2014-06-09  4:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 05, 2014 at 05:48:37PM +0200, Antoine T?nart wrote:
> This series adds the support for the Marvell Berlin USB controllers,
> the USB PHYs and also adds a reset controller.
> 
> The reset controller is used by the USB PHY driver and shares the
> existing chip controller node with the clocks and one pin controller.
> 
> The Marvell Berlin USB controllers are host only on the BG2Q and are
> compatible with USB ChipIdea. We here add a glue to use the available
> common functions for this kind of controllers. A USB PHY driver is also
> added to control the PHY.
> 
> Antoine T?nart (9):
>   reset: add the Berlin reset controller driver
>   ARM: Berlin: select the reset controller
>   ARM: dts: berlin: add a required reset property in the chip controller
>     node
>   usb: phy: add the Berlin USB PHY driver
>   Documentation: bindings: add doc for the Berlin USB PHY
>   usb: chipidea: add Berlin USB support
>   Documentation: bindings: add doc for the Berlin ChipIdea USB driver
>   ARM: dts: berlin: add BG2Q nodes for USB support
>   ARM: dts: Berlin: enable USB on the BG2Q DMP
> 
>  .../devicetree/bindings/usb/berlin-usbphy.txt      |  18 ++
>  .../devicetree/bindings/usb/ci-hdrc-berlin.txt     |  18 ++
>  arch/arm/boot/dts/berlin2.dtsi                     |   1 +
>  arch/arm/boot/dts/berlin2cd.dtsi                   |   1 +
>  arch/arm/boot/dts/berlin2q-marvell-dmp.dts         |  20 ++
>  arch/arm/boot/dts/berlin2q.dtsi                    |  52 +++++
>  arch/arm/mach-berlin/Kconfig                       |   2 +
>  drivers/reset/Makefile                             |   1 +
>  drivers/reset/reset-berlin.c                       | 113 +++++++++++
>  drivers/usb/chipidea/Makefile                      |   1 +
>  drivers/usb/chipidea/ci_hdrc_berlin.c              | 108 ++++++++++
>  drivers/usb/phy/Kconfig                            |   9 +
>  drivers/usb/phy/Makefile                           |   1 +
>  drivers/usb/phy/phy-berlin-usb.c                   | 223 +++++++++++++++++++++
>  14 files changed, 568 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/usb/berlin-usbphy.txt
>  create mode 100644 Documentation/devicetree/bindings/usb/ci-hdrc-berlin.txt
>  create mode 100644 drivers/reset/reset-berlin.c
>  create mode 100644 drivers/usb/chipidea/ci_hdrc_berlin.c
>  create mode 100644 drivers/usb/phy/phy-berlin-usb.c
> 
> -- 
> 1.9.1
> 

I am fine with 6/9, 7/9, will queue them if no other objections.

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 4/9] usb: phy: add the Berlin USB PHY driver
  2014-06-06 10:54   ` Sebastian Hesselbarth
  2014-06-06 11:59     ` Antoine Ténart
@ 2014-06-09  8:26     ` Jisheng Zhang
  2014-06-09 10:11       ` Sebastian Hesselbarth
  1 sibling, 1 reply; 31+ messages in thread
From: Jisheng Zhang @ 2014-06-09  8:26 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Sebastian and Antoine,

On Fri, 6 Jun 2014 03:54:06 -0700
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> wrote:

> > +
> > +#define to_berlin_phy_priv(p)	container_of((p), struct
> > berlin_phy_priv, phy) +
> > +struct berlin_phy_priv {
> > +	void __iomem		*base;
> > +	struct usb_phy		phy;
> > +	struct reset_control	*rst_ctrl;
> > +	int			pwr_gpio;
> 
> Is the GPIO used for USB power? If so, we should not rely on

The GPIO is used for vbus. Sorry for using the confusing "pwr". Do we still
need to use regulator API?

> GPIO at all but use regulator API. Thinking of Chromecast which
> is externally powered over USB, there will be no regulator nor
> GPIO at all.
> 
> > +};
> > +
> > +static int berlin_phy_init(struct usb_phy *phy)
> > +{
> > +	struct berlin_phy_priv *priv = to_berlin_phy_priv(phy);
> > +	int ret;
> > +
> > +	reset_control_reset(priv->rst_ctrl);
> > +
> > +	writel(CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
> > +	       priv->base + USB_PHY_PLL);
> 
> @Jisheng: IIRC the dividers above are different for BG2? Can you please
> evaluate?

Yes, BG2 uses different refdiv and fbdiv. Is there any suggestions about how to
handle this difference? The value is chosen after carefully tunning

> 
> > +	writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 |
> > KVC0_REG_CTRL |
> > +	       CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL);
> > +	writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5),
> > +	       priv->base + USB_PHY_ANALOG);
> > +	writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 |
> > +	       DISCON_THRESHOLD_260 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) |
> > +	       INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL);
> > +
> > +	writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base +
> > USB_PHY_TX_CTRL1);
> > +	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) |
> > EXT_RS_RCAL_DIV(0x4),
> > +	       priv->base + USB_PHY_TX_CTRL0);
> > +
> > +	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) |
> > EXT_RS_RCAL_DIV(0x4) |
> > +	       EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0);
> > +
> > +	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) |
> > EXT_RS_RCAL_DIV(0x4),
> > +	       priv->base + USB_PHY_TX_CTRL0);
> > +	writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) |
> > IMP_CAL_FS_HS_DLY_3 |
> > +	       FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2);
> > +
> > +	ret = gpio_direction_output(priv->pwr_gpio, 0);
> 
> As mentioned above, this should be using regulator API. And also, if
> there is no dummy regulator allowed, it should be optional.
> 
> > +	if (ret)
> > +		return ret;
> > +
> > +	gpio_set_value(priv->pwr_gpio, 1);
> > +
> > +	return 0;
> > +}
> > +
> > +static void berlin_phy_shutdown(struct usb_phy *phy)
> > +{
> > +	struct berlin_phy_priv *priv = to_berlin_phy_priv(phy);
> > +
> > +	gpio_set_value(priv->pwr_gpio, 0);
> > +}
> > +
> > +static int berlin_phy_probe(struct platform_device *pdev)
> > +{
> > +	struct device_node *np = pdev->dev.of_node;
> > +	struct berlin_phy_priv *priv;
> > +	struct resource *res;
> > +	int ret, gpio;
> > +
> > +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	priv->base = devm_ioremap_resource(&pdev->dev, res);
> > +	if (IS_ERR(priv->base))
> > +		return PTR_ERR(priv->base);
> > +
> > +	priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
> > +	if (IS_ERR(priv->rst_ctrl)) {
> > +		ret = PTR_ERR(priv->rst_ctrl);
> > +		dev_err(&pdev->dev, "cannot get reset controller: %d\n",
> > ret);
> 
> Hmm, considering a non arch_init call registered reset driver, it does
> also spit out an error for -EPROBE_DEFER, does it?
> 
> > +		return ret;
> > +	}
> > +
> > +	gpio = of_get_named_gpio(np, "power-gpio", 0);
> > +	if (!gpio_is_valid(gpio))
> > +		return gpio;

Some BG2Q boards hardwired the vbus to be always powered on, we should continue
the probe if vbus gpio is missing.

Thanks,
Jisheng

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 4/9] usb: phy: add the Berlin USB PHY driver
  2014-06-09  8:26     ` Jisheng Zhang
@ 2014-06-09 10:11       ` Sebastian Hesselbarth
  2014-06-09 10:52         ` Alexandre Belloni
  0 siblings, 1 reply; 31+ messages in thread
From: Sebastian Hesselbarth @ 2014-06-09 10:11 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/09/2014 10:26 AM, Jisheng Zhang wrote:
> Dear Sebastian and Antoine,
> 
> On Fri, 6 Jun 2014 03:54:06 -0700
> Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> wrote:
> 
>>> +
>>> +#define to_berlin_phy_priv(p)	container_of((p), struct
>>> berlin_phy_priv, phy) +
>>> +struct berlin_phy_priv {
>>> +	void __iomem		*base;
>>> +	struct usb_phy		phy;
>>> +	struct reset_control	*rst_ctrl;
>>> +	int			pwr_gpio;
>>
>> Is the GPIO used for USB power? If so, we should not rely on
> 
> The GPIO is used for vbus. Sorry for using the confusing "pwr". Do we still
> need to use regulator API?

Yes, I guess using regulator is still the way to go. Also, I think
it should be up to the controller to power on/off the device. That
way, we could make use of the dual role controller features on BG2
and BG2CD.

>> GPIO at all but use regulator API. Thinking of Chromecast which
>> is externally powered over USB, there will be no regulator nor
>> GPIO at all.
>>
>>> +};
>>> +
>>> +static int berlin_phy_init(struct usb_phy *phy)
>>> +{
>>> +	struct berlin_phy_priv *priv = to_berlin_phy_priv(phy);
>>> +	int ret;
>>> +
>>> +	reset_control_reset(priv->rst_ctrl);
>>> +
>>> +	writel(CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
>>> +	       priv->base + USB_PHY_PLL);
>>
>> @Jisheng: IIRC the dividers above are different for BG2? Can you please
>> evaluate?
> 
> Yes, BG2 uses different refdiv and fbdiv. Is there any suggestions about how to
> handle this difference? The value is chosen after carefully tunning

I guess it depends on how many different div values you expect for
berlin2 usb PHYs. If it is just the two, we can go with different
compatibles for e.g. "berlin2-usb-phy" and "berlin2cd-usb-phy".

If you know of more PHYs with different div, a corresponding vendor-
specific property should do the trick, e.g.
marvell,pll-divider = <0x54c0>;

I am fine with both.

>>
>>> +	writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 |
>>> KVC0_REG_CTRL |
>>> +	       CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL);
>>> +	writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5),
>>> +	       priv->base + USB_PHY_ANALOG);
>>> +	writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 |
>>> +	       DISCON_THRESHOLD_260 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) |
>>> +	       INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL);
>>> +
>>> +	writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base +
>>> USB_PHY_TX_CTRL1);
>>> +	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) |
>>> EXT_RS_RCAL_DIV(0x4),
>>> +	       priv->base + USB_PHY_TX_CTRL0);
>>> +
>>> +	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) |
>>> EXT_RS_RCAL_DIV(0x4) |
>>> +	       EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0);
>>> +
>>> +	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) |
>>> EXT_RS_RCAL_DIV(0x4),
>>> +	       priv->base + USB_PHY_TX_CTRL0);
>>> +	writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) |
>>> IMP_CAL_FS_HS_DLY_3 |
>>> +	       FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2);
>>> +
>>> +	ret = gpio_direction_output(priv->pwr_gpio, 0);
>>
>> As mentioned above, this should be using regulator API. And also, if
>> there is no dummy regulator allowed, it should be optional.
>>
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	gpio_set_value(priv->pwr_gpio, 1);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void berlin_phy_shutdown(struct usb_phy *phy)
>>> +{
>>> +	struct berlin_phy_priv *priv = to_berlin_phy_priv(phy);
>>> +
>>> +	gpio_set_value(priv->pwr_gpio, 0);
>>> +}
>>> +
>>> +static int berlin_phy_probe(struct platform_device *pdev)
>>> +{
>>> +	struct device_node *np = pdev->dev.of_node;
>>> +	struct berlin_phy_priv *priv;
>>> +	struct resource *res;
>>> +	int ret, gpio;
>>> +
>>> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
>>> +	if (!priv)
>>> +		return -ENOMEM;
>>> +
>>> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +	priv->base = devm_ioremap_resource(&pdev->dev, res);
>>> +	if (IS_ERR(priv->base))
>>> +		return PTR_ERR(priv->base);
>>> +
>>> +	priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
>>> +	if (IS_ERR(priv->rst_ctrl)) {
>>> +		ret = PTR_ERR(priv->rst_ctrl);
>>> +		dev_err(&pdev->dev, "cannot get reset controller: %d\n",
>>> ret);
>>
>> Hmm, considering a non arch_init call registered reset driver, it does
>> also spit out an error for -EPROBE_DEFER, does it?
>>
>>> +		return ret;
>>> +	}
>>> +
>>> +	gpio = of_get_named_gpio(np, "power-gpio", 0);
>>> +	if (!gpio_is_valid(gpio))
>>> +		return gpio;
> 
> Some BG2Q boards hardwired the vbus to be always powered on, we should continue
> the probe if vbus gpio is missing.

Yeah, the same applies for regulators. But with the comments above, it
should move to the controller stub instead.

Sebastian

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 0/9] ARM: Berlin: USB support
  2014-06-09  4:30 ` [PATCH 0/9] ARM: Berlin: USB support Peter Chen
@ 2014-06-09 10:14   ` Sebastian Hesselbarth
  2014-06-10  1:16     ` Peter Chen
  0 siblings, 1 reply; 31+ messages in thread
From: Sebastian Hesselbarth @ 2014-06-09 10:14 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/09/2014 06:30 AM, Peter Chen wrote:
> On Thu, Jun 05, 2014 at 05:48:37PM +0200, Antoine T?nart wrote:
>> This series adds the support for the Marvell Berlin USB controllers,
>> the USB PHYs and also adds a reset controller.
>>
>> The reset controller is used by the USB PHY driver and shares the
>> existing chip controller node with the clocks and one pin controller.
>>
>> The Marvell Berlin USB controllers are host only on the BG2Q and are
>> compatible with USB ChipIdea. We here add a glue to use the available
>> common functions for this kind of controllers. A USB PHY driver is also
>> added to control the PHY.
[...]
> 
> I am fine with 6/9, 7/9, will queue them if no other objections.
> 

Thanks Peter,

we are early in the cycle and I feel there will be a v2 of the
chipidea stub. IMHO, controlling the vbus regulator should not
be business of the phy driver, so ci will have to deal with it.

Anyways, good to know you are fine with it already!

Sebastian

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/9] reset: add the Berlin reset controller driver
  2014-06-05 15:48 ` [PATCH 1/9] reset: add the Berlin reset controller driver Antoine Ténart
  2014-06-05 16:36   ` Philipp Zabel
@ 2014-06-09 10:32   ` Sebastian Hesselbarth
  2014-06-09 11:23     ` Philipp Zabel
  1 sibling, 1 reply; 31+ messages in thread
From: Sebastian Hesselbarth @ 2014-06-09 10:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/05/2014 05:48 PM, Antoine T?nart wrote:
> Add a reset controller for Marvell Berlin SoCs which is used by the
> USB PHYs drivers (for now).
> 
> Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
> ---
>  drivers/reset/Makefile       |   1 +
>  drivers/reset/reset-berlin.c | 113 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 114 insertions(+)
>  create mode 100644 drivers/reset/reset-berlin.c
> 
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 4f60caf750ce..fffe2a3dd255 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_RESET_CONTROLLER) += core.o
> +obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
>  obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
>  obj-$(CONFIG_ARCH_STI) += sti/
> diff --git a/drivers/reset/reset-berlin.c b/drivers/reset/reset-berlin.c
> new file mode 100644
> index 000000000000..78b42c882cb2
> --- /dev/null
> +++ b/drivers/reset/reset-berlin.c
> @@ -0,0 +1,113 @@
> +/*
> + * Copyright (C) 2014 Marvell Technology Group Ltd.
> + *
> + * Antoine T?nart <antoine.tenart@free-electrons.com>
> + *
> + * 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/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset-controller.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/types.h>
> +
> +#define BERLIN_RESET_REGISTER		0x104
> +
> +#define to_berlin_reset_priv(p)		\
> +	container_of((p), struct berlin_reset_priv, rcdev)
> +
> +struct berlin_reset_priv {
> +	spinlock_t			lock;
> +	void __iomem			*base;
> +	struct reset_controller_dev	rcdev;
> +};
> +
> +static int berlin_reset_reset(struct reset_controller_dev *rcdev,
> +			      unsigned long id)
> +{
> +	struct berlin_reset_priv *priv = to_berlin_reset_priv(rcdev);
> +	unsigned long flags;
> +	int bank = id / BITS_PER_LONG;
> +	int offset = id % BITS_PER_LONG;
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +
> +	writel(BIT(offset), priv->base + bank * 4);
> +
> +	spin_unlock_irqrestore(&priv->lock, flags);
> +
> +	/* let the reset be effective */
> +	udelay(10);
> +
> +	return 0;
> +}
> +
> +static struct reset_control_ops berlin_reset_ops = {
> +	.reset	= berlin_reset_reset,
> +};
> +
> +static int __berlin_reset_init(struct device_node *np)
> +{
> +	struct berlin_reset_priv *priv;
> +	struct resource res;
> +	resource_size_t size;
> +	int ret;
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	ret = of_address_to_resource(np, 0, &res);
> +	if (ret)
> +		goto err;
> +
> +	size = resource_size(&res);
> +
> +	priv->base = ioremap(res.start, size);
> +	if (!priv->base) {
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +	priv->base += BERLIN_RESET_REGISTER;

I currently have no way to look it up myself, but is reset API providing
a way to deal with phandle+specifier with more than one parameter?
Chip-ctrl has a bunch of other reset bits spread over the regset, having
the offset encoded in the specifier would save us some SoC specific
boiler plate, i.e.

reset = <&chip 0x104 14>;

Sebastian

> +	priv->rcdev.owner = THIS_MODULE;
> +	priv->rcdev.nr_resets = size * 32;
> +	priv->rcdev.ops = &berlin_reset_ops;
> +	priv->rcdev.of_node = np;
> +
> +	reset_controller_register(&priv->rcdev);
> +
> +	return 0;
> +
> +err:
> +	kfree(priv);
> +	return ret;
> +}
> +
> +static const struct of_device_id berlin_reset_of_match[] __initdata = {
> +	{ .compatible = "marvell,berlin2q-chip-ctrl" },
> +	{ },
> +};
> +
> +static int __init berlin_reset_init(void)
> +{
> +	struct device_node *np;
> +	int ret;
> +
> +	for_each_matching_node(np, berlin_reset_of_match) {
> +		ret = __berlin_reset_init(np);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +arch_initcall(berlin_reset_init);
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 4/9] usb: phy: add the Berlin USB PHY driver
  2014-06-09 10:11       ` Sebastian Hesselbarth
@ 2014-06-09 10:52         ` Alexandre Belloni
  0 siblings, 0 replies; 31+ messages in thread
From: Alexandre Belloni @ 2014-06-09 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/06/2014 at 12:11:57 +0200, Sebastian Hesselbarth wrote :
> > Some BG2Q boards hardwired the vbus to be always powered on, we should continue
> > the probe if vbus gpio is missing.
> 
> Yeah, the same applies for regulators. But with the comments above, it
> should move to the controller stub instead.
> 

We should use a regulator and in the case it is hardwired, use a fixed
regulator. Then, we can stop if it is missing.

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/9] reset: add the Berlin reset controller driver
  2014-06-09 10:32   ` Sebastian Hesselbarth
@ 2014-06-09 11:23     ` Philipp Zabel
  0 siblings, 0 replies; 31+ messages in thread
From: Philipp Zabel @ 2014-06-09 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sebastian,

On Mon, Jun 09, 2014 at 12:32:50PM +0200, Sebastian Hesselbarth wrote:
> I currently have no way to look it up myself, but is reset API providing
> a way to deal with phandle+specifier with more than one parameter?

You could provide a custom rcdev->of_xlate callback and encode
multiple phandle args into the reset line "index".

static int of_reset_xlate(struct reset_controller_dev *rcdev,
                          const struct of_phandle_args *reset_spec)
{
	return reset_spec->args[0] * 32 + reset_spec->args[1];
}

> Chip-ctrl has a bunch of other reset bits spread over the regset, having
> the offset encoded in the specifier would save us some SoC specific
> boiler plate, i.e.
> 
> reset = <&chip 0x104 14>;

That should be possible.

regards
Philipp

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 0/9] ARM: Berlin: USB support
  2014-06-09 10:14   ` Sebastian Hesselbarth
@ 2014-06-10  1:16     ` Peter Chen
  0 siblings, 0 replies; 31+ messages in thread
From: Peter Chen @ 2014-06-10  1:16 UTC (permalink / raw)
  To: linux-arm-kernel

 
> 
> we are early in the cycle and I feel there will be a v2 of the chipidea
> stub. IMHO, controlling the vbus regulator should not be business of the
> phy driver, so ci will have to deal with it.
> 

vbus handling has already in chipidea common code, it treats vbus as a regulator.
So, the glue layer only needs to register and add vbus-supply to dts file, no source
code change is needed.

Peter

> Anyways, good to know you are fine with it already!
> 
> Sebastian

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 4/9] usb: phy: add the Berlin USB PHY driver
  2014-06-06 11:02       ` Vivek Gautam
@ 2014-06-19 13:45         ` Felipe Balbi
  0 siblings, 0 replies; 31+ messages in thread
From: Felipe Balbi @ 2014-06-19 13:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 06, 2014 at 04:32:03PM +0530, Vivek Gautam wrote:
> Hi,
> 
> On Fri, Jun 6, 2014 at 12:41 PM, Antoine T?nart
> <antoine.tenart@free-electrons.com> wrote:
> > Hi,
> >
> > On Fri, Jun 06, 2014 at 12:09:06PM +0530, Vivek Gautam wrote:
> >> On Thu, Jun 5, 2014 at 9:18 PM, Antoine T?nart
> >> <antoine.tenart@free-electrons.com> wrote:
> >> > Add the driver driving the Marvell Berlin USB PHY. This allows to
> >> > initialize the PHY and to use it from the USB driver later.
> >>
> >> Just out of curiosity, going forward we would like to have phy drivers based on
> >> generic phy framework (drivers/phy).
> >> Any particular reason that we are still adding phy drivers in usb-phy layer ?
> >>
> >> Looking at it, seems like it can very well be written based on phy framework.
> >
> > This USB controller are ChipIdea compatible, and the ChipIdea common
> > functions use the usb_phy framework. That's why this PHY driver is
> > there.
> 
> Ok, i see that now. In that case shouldn't we be moving even the chipidea
> drivers to use the generic phy functions to get the phy and init/exit it.

yes, we should :-)

> I think Felipe and Kishon can comment on this better, and tell how
> things should be. :-)

yeah, this will just make it a little more difficult to deprecate
current usb phy layer.

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140619/c28e2865/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2014-06-19 13:45 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-05 15:48 [PATCH 0/9] ARM: Berlin: USB support Antoine Ténart
2014-06-05 15:48 ` [PATCH 1/9] reset: add the Berlin reset controller driver Antoine Ténart
2014-06-05 16:36   ` Philipp Zabel
2014-06-05 16:56     ` Antoine Ténart
2014-06-06 10:44     ` Sebastian Hesselbarth
2014-06-09 10:32   ` Sebastian Hesselbarth
2014-06-09 11:23     ` Philipp Zabel
2014-06-05 15:48 ` [PATCH 2/9] ARM: Berlin: select the reset controller Antoine Ténart
2014-06-05 15:48 ` [PATCH 3/9] ARM: dts: berlin: add a required reset property in the chip controller node Antoine Ténart
2014-06-05 16:39   ` Philipp Zabel
2014-06-05 16:44     ` Antoine Ténart
2014-06-05 15:48 ` [PATCH 4/9] usb: phy: add the Berlin USB PHY driver Antoine Ténart
2014-06-06  6:39   ` Vivek Gautam
2014-06-06  7:11     ` Antoine Ténart
2014-06-06 11:02       ` Vivek Gautam
2014-06-19 13:45         ` Felipe Balbi
2014-06-06 10:54   ` Sebastian Hesselbarth
2014-06-06 11:59     ` Antoine Ténart
2014-06-09  8:26     ` Jisheng Zhang
2014-06-09 10:11       ` Sebastian Hesselbarth
2014-06-09 10:52         ` Alexandre Belloni
2014-06-05 15:48 ` [PATCH 5/9] Documentation: bindings: add doc for the Berlin USB PHY Antoine Ténart
2014-06-05 15:48 ` [PATCH 6/9] usb: chipidea: add Berlin USB support Antoine Ténart
2014-06-06 10:55   ` Sebastian Hesselbarth
2014-06-06 12:01     ` Antoine Ténart
2014-06-05 15:48 ` [PATCH 7/9] Documentation: bindings: add doc for the Berlin ChipIdea USB driver Antoine Ténart
2014-06-05 15:48 ` [PATCH 8/9] ARM: dts: berlin: add BG2Q nodes for USB support Antoine Ténart
2014-06-05 15:48 ` [PATCH 9/9] ARM: dts: Berlin: enable USB on the BG2Q DMP Antoine Ténart
2014-06-09  4:30 ` [PATCH 0/9] ARM: Berlin: USB support Peter Chen
2014-06-09 10:14   ` Sebastian Hesselbarth
2014-06-10  1:16     ` Peter Chen

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).