All of lore.kernel.org
 help / color / mirror / Atom feed
* Patches for Freescale MXC SoCs and direct ULPI communication [v3]
@ 2009-09-02 20:47 Daniel Mack
  2009-09-02 20:47 ` [PATCH 1/5] USB OTG: add support for ulpi connected external transceivers Daniel Mack
  2009-09-03 15:41 ` Patches for Freescale MXC SoCs and direct ULPI communication [v3] Valentin Longchamp
  0 siblings, 2 replies; 10+ messages in thread
From: Daniel Mack @ 2009-09-02 20:47 UTC (permalink / raw)
  To: linux-arm-kernel

Sorry for the long delay on this issue.

Here comes another round of four patches to support the EHCI ports on
Freescale's MX2/MX3 SoCs.

The difference to the last version I've sent is that the ISP1504
specific drivers has become a generic ULPI driver now with all the
defines renamed.

Also the driver does not set DRV_VBUS and DRV_VBUS_EXT blindly
anymore but uses a flags field in the otg_transceiver struct which can
be specified when creating the device. This allows the adaption of the
code to a wider variety of applications.

As a reference, I've added a patch to add board specific support code
for the lilly1131 module.

Let me know if that still works for other boards and if that version
looks better to you.

Again, #1, #2 and #4 are supposed to go thru the USB folks' channel,
while the rest might be picked by Sascha Hauer eventually.

Thanks,
Daniel

[PATCH 1/5] USB OTG: add support for ulpi connected external transceivers
[PATCH 2/5] USB OTG: Add generic driver for ULPI OTG transceiver
[PATCH 3/5] MXC: Add support for ULPI Viewports
[PATCH 4/5] USB: Add EHCI support for MX27 and MX31 based boards
[PATCH 5/5] MX3: add USB support for lilly1131

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

* [PATCH 1/5] USB OTG: add support for ulpi connected external transceivers
  2009-09-02 20:47 Patches for Freescale MXC SoCs and direct ULPI communication [v3] Daniel Mack
@ 2009-09-02 20:47 ` Daniel Mack
  2009-09-02 20:47   ` [PATCH 2/5] USB OTG: Add generic driver for ULPI OTG transceiver Daniel Mack
  2009-09-03 15:41 ` Patches for Freescale MXC SoCs and direct ULPI communication [v3] Valentin Longchamp
  1 sibling, 1 reply; 10+ messages in thread
From: Daniel Mack @ 2009-09-02 20:47 UTC (permalink / raw)
  To: linux-arm-kernel

This adds support for OTG transceivers directly connected to the ULPI
interface. In particular, the following details are added

- a struct for low level io functions (read/write)
- a priv field to be used as 'viewport' by low level access functions
- an (*init) and (*shutdown) callbacks, along with static inline helpers
- a (*set_vbus) callback to switch the port power on and off
- a flags field for per-transceiver settings
- some defines for the flags bitmask to configure platform specific
  details

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: linux-usb at vger.kernel.org
---
 include/linux/usb/otg.h |   68 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 67 insertions(+), 1 deletions(-)

diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 2443c0e..52bb917 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -33,6 +33,23 @@ enum usb_otg_state {
 	OTG_STATE_A_VBUS_ERR,
 };
 
+#define USB_OTG_PULLUP_ID		(1 << 0)
+#define USB_OTG_PULLDOWN_DP		(1 << 1)
+#define USB_OTG_PULLDOWN_DM		(1 << 2)
+#define USB_OTG_EXT_VBUS_INDICATOR	(1 << 3)
+#define USB_OTG_DRV_VBUS		(1 << 4)
+#define USB_OTG_DRV_VBUS_EXT		(1 << 5)
+
+struct otg_transceiver;
+
+/* for transceivers connected thru an ULPI interface, the user must
+ * provide access ops
+ */
+struct otg_io_access_ops {
+	int (*read)(struct otg_transceiver *otg, u32 reg);
+	int (*write)(struct otg_transceiver *otg, u32 val, u32 reg);
+};
+
 /*
  * the otg driver needs to interact with both device side and host side
  * usb controllers.  it decides which controller is active@a given
@@ -42,6 +59,7 @@ enum usb_otg_state {
 struct otg_transceiver {
 	struct device		*dev;
 	const char		*label;
+	unsigned int		 flags;
 
 	u8			default_a;
 	enum usb_otg_state	state;
@@ -49,10 +67,17 @@ struct otg_transceiver {
 	struct usb_bus		*host;
 	struct usb_gadget	*gadget;
 
+	struct otg_io_access_ops	*io_ops;
+	void __iomem			*io_priv;
+
 	/* to pass extra port status to the root hub */
 	u16			port_status;
 	u16			port_change;
 
+	/* initialize/shutdown the OTG controller */
+	int	(*init)(struct otg_transceiver *otg);
+	void	(*shutdown)(struct otg_transceiver *otg);
+
 	/* bind/unbind the host controller */
 	int	(*set_host)(struct otg_transceiver *otg,
 				struct usb_bus *host);
@@ -65,6 +90,10 @@ struct otg_transceiver {
 	int	(*set_power)(struct otg_transceiver *otg,
 				unsigned mA);
 
+	/* effective for A-peripheral, ignored for B devices */
+	int	(*set_vbus)(struct otg_transceiver *otg,
+				bool enabled);
+
 	/* for non-OTG B devices: set transceiver into suspend mode */
 	int	(*set_suspend)(struct otg_transceiver *otg,
 				int suspend);
@@ -85,6 +114,38 @@ extern int otg_set_transceiver(struct otg_transceiver *);
 extern void usb_nop_xceiv_register(void);
 extern void usb_nop_xceiv_unregister(void);
 
+/* helpers for direct access thru low-level io interface */
+static inline int otg_io_read(struct otg_transceiver *otg, u32 reg)
+{
+	if (otg->io_ops && otg->io_ops->read)
+		return otg->io_ops->read(otg, reg);
+
+	return -EINVAL;
+}
+
+static inline int otg_io_write(struct otg_transceiver *otg, u32 reg, u32 val)
+{
+	if (otg->io_ops && otg->io_ops->write)
+		return otg->io_ops->write(otg, reg, val);
+
+	return -EINVAL;
+}
+
+static inline int
+otg_init(struct otg_transceiver *otg)
+{
+	if (otg->init)
+		return otg->init(otg);
+
+	return 0;
+}
+
+static inline void
+otg_shutdown(struct otg_transceiver *otg)
+{
+	if (otg->shutdown)
+		otg->shutdown(otg);
+}
 
 /* for usb host and peripheral controller drivers */
 extern struct otg_transceiver *otg_get_transceiver(void);
@@ -97,6 +158,12 @@ otg_start_hnp(struct otg_transceiver *otg)
 	return otg->start_hnp(otg);
 }
 
+/* Context: can sleep */
+static inline int
+otg_set_vbus(struct otg_transceiver *otg, bool enabled)
+{
+	return otg->set_vbus(otg, enabled);
+}
 
 /* for HCDs */
 static inline int
@@ -105,7 +172,6 @@ otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
 	return otg->set_host(otg, host);
 }
 
-
 /* for usb peripheral controller drivers */
 
 /* Context: can sleep */
-- 
1.6.3.3

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

* [PATCH 2/5] USB OTG: Add generic driver for ULPI OTG transceiver
  2009-09-02 20:47 ` [PATCH 1/5] USB OTG: add support for ulpi connected external transceivers Daniel Mack
@ 2009-09-02 20:47   ` Daniel Mack
  2009-09-02 20:47     ` [PATCH 3/5] MXC: Add support for ULPI Viewports Daniel Mack
  0 siblings, 1 reply; 10+ messages in thread
From: Daniel Mack @ 2009-09-02 20:47 UTC (permalink / raw)
  To: linux-arm-kernel

This adds a minimal generic driver for ULPI connected transceivers,
using the OTG framework functions recently introduced.

The driver got a table to match the ULPI chips, which currently only has
one entry for NXP's ISP 1504 transceiver.

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: linux-usb at vger.kernel.org
---
 drivers/usb/Makefile     |    2 +
 drivers/usb/otg/Kconfig  |    9 +++
 drivers/usb/otg/Makefile |    1 +
 drivers/usb/otg/ulpi.c   |  136 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/usb/ulpi.h |    7 +++
 5 files changed, 155 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/otg/ulpi.c
 create mode 100644 include/linux/usb/ulpi.h

diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 19cb7d5..37797e3 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -42,3 +42,5 @@ obj-$(CONFIG_USB)		+= misc/
 
 obj-$(CONFIG_USB_ATM)		+= atm/
 obj-$(CONFIG_USB_SPEEDTOUCH)	+= atm/
+
+obj-$(CONFIG_USB_ULPI)		+= otg/
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index aa884d0..de56b3d 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -41,6 +41,15 @@ config ISP1301_OMAP
 	  This driver can also be built as a module.  If so, the module
 	  will be called isp1301_omap.
 
+config USB_ULPI
+	bool "Generic ULPI Transceiver Driver"
+	depends on ARM
+	help
+	  Enable this to support ULPI connected USB OTG transceivers which
+	  are likely found on embedded boards.
+
+	  The only chip currently supported is NXP's ISP1504
+
 config TWL4030_USB
 	tristate "TWL4030 USB Transceiver Driver"
 	depends on TWL4030_CORE && REGULATOR_TWL4030
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index 2081678..aeb49a8 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
+obj-$(CONFIG_USB_ULPI)		+= ulpi.o
 
 ccflags-$(CONFIG_USB_DEBUG)	+= -DDEBUG
 ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
new file mode 100644
index 0000000..8965274
--- /dev/null
+++ b/drivers/usb/otg/ulpi.c
@@ -0,0 +1,136 @@
+/*
+ * Generic ULPI USB transceiver support
+ *
+ * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * Based on sources from
+ *
+ *   Sascha Hauer <s.hauer@pengutronix.de>
+ *   Freescale Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+
+/* ULPI register addresses */
+#define ULPI_VID_LOW         0x00    /* Vendor ID low */
+#define ULPI_VID_HIGH        0x01    /* Vendor ID high */
+#define ULPI_PID_LOW         0x02    /* Product ID low */
+#define ULPI_PID_HIGH        0x03    /* Product ID high */
+#define ULPI_ITFCTL          0x07    /* Interface Control */
+#define ULPI_OTGCTL          0x0A    /* OTG Control */
+
+/* add to above register address to access Set/Clear functions */
+#define ULPI_REG_SET         0x01
+#define ULPI_REG_CLEAR       0x02
+
+/* ULPI OTG Control Register bits */
+#define ID_PULL_UP              (1 << 0)        /* enable ID Pull Up */
+#define DP_PULL_DOWN            (1 << 1)        /* enable DP Pull Down */
+#define DM_PULL_DOWN            (1 << 2)        /* enable DM Pull Down */
+#define DISCHRG_VBUS            (1 << 3)        /* Discharge Vbus */
+#define CHRG_VBUS               (1 << 4)        /* Charge Vbus */
+#define DRV_VBUS                (1 << 5)        /* Drive Vbus */
+#define DRV_VBUS_EXT            (1 << 6)        /* Drive Vbus external */
+#define USE_EXT_VBUS_IND        (1 << 7)        /* Use ext. Vbus indicator */
+
+#define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
+
+#define TR_FLAG(flags, a, b)	(((flags) & a) ? b : 0)
+
+/* ULPI hardcoded IDs, used for probing */
+static unsigned int ulpi_ids[] = {
+	ULPI_ID(0x04cc, 0x1504),	/* NXP ISP1504 */
+};
+
+static int ulpi_set_flags(struct otg_transceiver *otg)
+{
+	unsigned int flags = 0;
+
+	if (otg->flags & USB_OTG_PULLUP_ID)
+		flags |= ID_PULL_UP;
+
+	if (otg->flags & USB_OTG_PULLDOWN_DM)
+		flags |= DM_PULL_DOWN;
+
+	if (otg->flags & USB_OTG_PULLDOWN_DP)
+		flags |= DP_PULL_DOWN;
+
+	if (otg->flags & USB_OTG_EXT_VBUS_INDICATOR)
+		flags |= USE_EXT_VBUS_IND;
+
+	return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET);
+}
+
+static int ulpi_init(struct otg_transceiver *otg)
+{
+	int i, vid, pid;
+
+	vid = (otg_io_read(otg, ULPI_VID_HIGH) << 8) |
+	       otg_io_read(otg, ULPI_VID_LOW);
+	pid = (otg_io_read(otg, ULPI_PID_HIGH) << 8) |
+	       otg_io_read(otg, ULPI_PID_LOW);
+
+	pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
+
+	for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++)
+		if (ulpi_ids[i] == ULPI_ID(vid, pid))
+			return ulpi_set_flags(otg);
+
+	pr_err("ULPI ID does not match any known transceiver.\n");
+	return -ENODEV;
+}
+
+static int ulpi_set_vbus(struct otg_transceiver *otg, bool on)
+{
+	unsigned int flags = otg_io_read(otg, ULPI_OTGCTL);
+
+	flags &= ~(DRV_VBUS | DRV_VBUS_EXT);
+
+	if (on) {
+		if (otg->flags & USB_OTG_DRV_VBUS)
+			flags |= DRV_VBUS;
+
+		if (otg->flags & USB_OTG_DRV_VBUS_EXT)
+			flags |= DRV_VBUS_EXT;
+	}
+
+	return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET);
+}
+
+struct otg_transceiver *
+otg_ulpi_create(struct otg_io_access_ops *ops,
+		unsigned int flags)
+{
+	struct otg_transceiver *otg;
+
+	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
+	if (!otg)
+		return NULL;
+
+	otg->label	= "ULPI";
+	otg->flags	= flags;
+	otg->io_ops	= ops;
+	otg->init	= ulpi_init;
+	otg->set_vbus	= ulpi_set_vbus;
+
+	return otg;
+}
+EXPORT_SYMBOL_GPL(otg_ulpi_create);
+
diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h
new file mode 100644
index 0000000..20675c6
--- /dev/null
+++ b/include/linux/usb/ulpi.h
@@ -0,0 +1,7 @@
+#ifndef __LINUX_USB_ULPI_H
+#define __LINUX_USB_ULPI_H
+
+struct otg_transceiver *otg_ulpi_create(struct otg_io_access_ops *ops,
+					unsigned int flags);
+
+#endif /* __LINUX_USB_ULPI_H */
-- 
1.6.3.3

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

* [PATCH 3/5] MXC: Add support for ULPI Viewports
  2009-09-02 20:47   ` [PATCH 2/5] USB OTG: Add generic driver for ULPI OTG transceiver Daniel Mack
@ 2009-09-02 20:47     ` Daniel Mack
  2009-09-02 20:47       ` [PATCH 4/5] USB: Add EHCI support for MX27 and MX31 based boards Daniel Mack
  0 siblings, 1 reply; 10+ messages in thread
From: Daniel Mack @ 2009-09-02 20:47 UTC (permalink / raw)
  To: linux-arm-kernel

The ARC USB OTG Core has support for accessing ULPI tranceivers
through so called ULPI viewports. Export a set of function for use with
the USB OTG framework.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: linux-usb at vger.kernel.org
---
 arch/arm/plat-mxc/Kconfig             |    3 +
 arch/arm/plat-mxc/Makefile            |    1 +
 arch/arm/plat-mxc/include/mach/ulpi.h |    7 ++
 arch/arm/plat-mxc/ulpi.c              |  111 +++++++++++++++++++++++++++++++++
 4 files changed, 122 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-mxc/include/mach/ulpi.h
 create mode 100644 arch/arm/plat-mxc/ulpi.c

diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 0617c19..5254670 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -53,6 +53,9 @@ config MXC_PWM
 	help
 	  Enable support for the i.MX PWM controller(s).
 
+config MXC_ULPI
+	bool
+
 config ARCH_HAS_RNGA
 	bool
 	depends on ARCH_MXC
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index e3212c8..545412f 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o
 obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o
 obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
 obj-$(CONFIG_MXC_PWM)  += pwm.o
+obj-$(CONFIG_MXC_ULPI) += ulpi.o
diff --git a/arch/arm/plat-mxc/include/mach/ulpi.h b/arch/arm/plat-mxc/include/mach/ulpi.h
new file mode 100644
index 0000000..96b6ab4
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/ulpi.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_ULPI_H
+#define __MACH_ULPI_H
+
+extern struct otg_io_access_ops mxc_ulpi_access_ops;
+
+#endif /* __MACH_ULPI_H */
+
diff --git a/arch/arm/plat-mxc/ulpi.c b/arch/arm/plat-mxc/ulpi.c
new file mode 100644
index 0000000..911cceb
--- /dev/null
+++ b/arch/arm/plat-mxc/ulpi.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/usb/otg.h>
+
+#include <mach/ulpi.h>
+
+/* ULPIVIEW register bits */
+#define ULPIVW_WU		(1 << 31)	/* Wakeup */
+#define ULPIVW_RUN		(1 << 30)	/* read/write run */
+#define ULPIVW_WRITE		(1 << 29)	/* 0 = read  1 = write */
+#define ULPIVW_SS		(1 << 27)	/* SyncState */
+#define ULPIVW_PORT_MASK	0x07	/* Port field */
+#define ULPIVW_PORT_SHIFT	24
+#define ULPIVW_ADDR_MASK	0xff	/* data address field */
+#define ULPIVW_ADDR_SHIFT	16
+#define ULPIVW_RDATA_MASK	0xff	/* read data field */
+#define ULPIVW_RDATA_SHIFT	8
+#define ULPIVW_WDATA_MASK	0xff	/* write data field */
+#define ULPIVW_WDATA_SHIFT	0
+
+static int ulpi_poll(void __iomem *view, u32 bit)
+{
+	uint32_t data;
+	int timeout = 10000;
+
+	data = __raw_readl(view);
+	while (data & bit) {
+		if (!timeout--) {
+			printk(KERN_WARNING
+				"timeout polling for ULPI device\n");
+			return -ETIMEDOUT;
+		}
+
+		udelay(10);
+		data = __raw_readl(view);
+	}
+
+	return (data >> ULPIVW_RDATA_SHIFT) & ULPIVW_RDATA_MASK;
+}
+
+static int ulpi_read(struct otg_transceiver *otg, u32 reg)
+{
+	int ret;
+	void __iomem *view = otg->io_priv;
+
+	/* make sure interface is running */
+	if (!(__raw_readl(view) && ULPIVW_SS)) {
+		__raw_writel(ULPIVW_WU, view);
+
+		/* wait for wakeup */
+		ret = ulpi_poll(view, ULPIVW_WU);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* read the register */
+	__raw_writel((ULPIVW_RUN | (reg << ULPIVW_ADDR_SHIFT)), view);
+
+	/* wait for completion */
+	return ulpi_poll(view, ULPIVW_RUN);
+}
+
+static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
+{
+	int ret;
+	void __iomem *view = otg->io_priv;
+
+	/* make sure the interface is running */
+	if (!(__raw_readl(view) && ULPIVW_SS)) {
+		__raw_writel(ULPIVW_WU, view);
+		/* wait for wakeup */
+		ret = ulpi_poll(view, ULPIVW_WU);
+		if (ret < 0)
+			return ret;
+	}
+
+	__raw_writel((ULPIVW_RUN | ULPIVW_WRITE |
+		      (reg << ULPIVW_ADDR_SHIFT) |
+		      ((val & ULPIVW_WDATA_MASK) << ULPIVW_WDATA_SHIFT)), view);
+
+	/* wait for completion */
+	ret = ulpi_poll(view, ULPIVW_RUN);
+
+	return (ret < 0) ? ret : 0;
+}
+
+struct otg_io_access_ops mxc_ulpi_access_ops = {
+	.read	= ulpi_read,
+	.write	= ulpi_write,
+};
+
-- 
1.6.3.3

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

* [PATCH 4/5] USB: Add EHCI support for MX27 and MX31 based boards
  2009-09-02 20:47     ` [PATCH 3/5] MXC: Add support for ULPI Viewports Daniel Mack
@ 2009-09-02 20:47       ` Daniel Mack
  2009-09-02 20:47         ` [PATCH 5/5] MX3: add USB support for lilly1131 Daniel Mack
  0 siblings, 1 reply; 10+ messages in thread
From: Daniel Mack @ 2009-09-02 20:47 UTC (permalink / raw)
  To: linux-arm-kernel

The Freescale MX27 and MX31 SoCs have a EHCI controller onboard.
The controller is capable of USB on the go. This patch adds
a driver to support all three of them.

Users have to pass details about serial interface configuration in the
platform data.

The USB OTG core used here is the ARC core, so the driver should
be renamed and probably be merged with ehci-fsl.c eventually.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: linux-usb at vger.kernel.org
---
 arch/arm/plat-mxc/Makefile                |    2 +
 arch/arm/plat-mxc/ehci.c                  |   90 +++++++++
 arch/arm/plat-mxc/include/mach/mxc_ehci.h |   37 ++++
 drivers/usb/Kconfig                       |    1 +
 drivers/usb/host/Kconfig                  |    7 +
 drivers/usb/host/ehci-hcd.c               |    5 +
 drivers/usb/host/ehci-mxc.c               |  296 +++++++++++++++++++++++++++++
 7 files changed, 438 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-mxc/ehci.c
 create mode 100644 arch/arm/plat-mxc/include/mach/mxc_ehci.h
 create mode 100644 drivers/usb/host/ehci-mxc.c

diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 545412f..20a9dba 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -10,3 +10,5 @@ obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o
 obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
 obj-$(CONFIG_MXC_PWM)  += pwm.o
 obj-$(CONFIG_MXC_ULPI) += ulpi.o
+obj-$(CONFIG_USB_EHCI_MXC)	+= ehci.o
+
diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c
new file mode 100644
index 0000000..9bddb5a
--- /dev/null
+++ b/arch/arm/plat-mxc/ehci.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET	0x600
+
+#define MX31_OTG_SIC_SHIFT	29
+#define MX31_OTG_SIC_MASK	(0xf << MX31_OTG_SIC_SHIFT)
+#define MX31_OTG_PM_BIT		(1 << 24)
+
+#define MX31_H2_SIC_SHIFT	21
+#define MX31_H2_SIC_MASK	(0xf << MX31_H2_SIC_SHIFT)
+#define MX31_H2_PM_BIT		(1 << 16)
+#define MX31_H2_DT_BIT		(1 << 5)
+
+#define MX31_H1_SIC_SHIFT	13
+#define MX31_H1_SIC_MASK	(0xf << MX31_H1_SIC_SHIFT)
+#define MX31_H1_PM_BIT		(1 << 8)
+#define MX31_H1_DT_BIT		(1 << 4)
+
+int mxc_set_usbcontrol(int port, unsigned int flags)
+{
+	unsigned int v;
+
+	if (cpu_is_mx31()) {
+		v = readl(IO_ADDRESS(OTG_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+		switch (port) {
+		case 0:	/* OTG port */
+			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
+			v |= (flags & MXC_EHCI_INTERFACE_MASK)
+					<< MX31_OTG_SIC_SHIFT;
+			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+				v |= MX31_OTG_PM_BIT;
+
+			break;
+		case 1: /* H1 port */
+			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT);
+			v |= (flags & MXC_EHCI_INTERFACE_MASK)
+						<< MX31_H1_SIC_SHIFT;
+			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+				v |= MX31_H1_PM_BIT;
+
+			if (!(flags & MXC_EHCI_TTL_ENABLED))
+				v |= MX31_H1_DT_BIT;
+
+			break;
+		case 2:	/* H2 port */
+			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT);
+			v |= (flags & MXC_EHCI_INTERFACE_MASK)
+						<< MX31_H2_SIC_SHIFT;
+			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+				v |= MX31_H2_PM_BIT;
+
+			if (!(flags & MXC_EHCI_TTL_ENABLED))
+				v |= MX31_H2_DT_BIT;
+
+			break;
+		}
+
+		writel(v, IO_ADDRESS(OTG_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+		return 0;
+	}
+
+	printk(KERN_WARNING
+		"%s() unable to setup USBCONTROL for this CPU\n", __func__);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(mxc_set_usbcontrol);
+
diff --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
new file mode 100644
index 0000000..8f79623
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
@@ -0,0 +1,37 @@
+#ifndef __INCLUDE_ASM_ARCH_MXC_EHCI_H
+#define __INCLUDE_ASM_ARCH_MXC_EHCI_H
+
+/* values for portsc field */
+#define MXC_EHCI_PHY_LOW_POWER_SUSPEND	(1 << 23)
+#define MXC_EHCI_FORCE_FS		(1 << 24)
+#define MXC_EHCI_UTMI_8BIT		(0 << 28)
+#define MXC_EHCI_UTMI_16BIT		(1 << 28)
+#define MXC_EHCI_SERIAL			(1 << 29)
+#define MXC_EHCI_MODE_UTMI		(0 << 30)
+#define MXC_EHCI_MODE_PHILIPS		(1 << 30)
+#define MXC_EHCI_MODE_ULPI		(2 << 30)
+#define MXC_EHCI_MODE_SERIAL		(3 << 30)
+
+/* values for flags field */
+#define MXC_EHCI_INTERFACE_DIFF_UNI	(0 << 0)
+#define MXC_EHCI_INTERFACE_DIFF_BI	(1 << 0)
+#define MXC_EHCI_INTERFACE_SINGLE_UNI	(2 << 0)
+#define MXC_EHCI_INTERFACE_SINGLE_BI	(3 << 0)
+#define MXC_EHCI_INTERFACE_MASK		(0xf)
+
+#define MXC_EHCI_POWER_PINS_ENABLED	(1 << 5)
+#define MXC_EHCI_TTL_ENABLED		(1 << 6)
+
+struct mxc_usbh_platform_data {
+	int (*init)(struct platform_device *pdev);
+	int (*exit)(struct platform_device *pdev);
+
+	unsigned int		 portsc;
+	unsigned int		 flags;
+	struct otg_transceiver	*otg;
+};
+
+int mxc_set_usbcontrol(int port, unsigned int flags);
+
+#endif /* __INCLUDE_ASM_ARCH_MXC_EHCI_H */
+
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index dcd49f1..3ffaed5 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -58,6 +58,7 @@ config USB_ARCH_HAS_EHCI
 	default y if PPC_83xx
 	default y if SOC_AU1200
 	default y if ARCH_IXP4XX
+	default y if ARCH_MXC
 	default PCI
 
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 1a920c7..923b8d8 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -105,6 +105,13 @@ config USB_EHCI_FSL
 	---help---
 	  Variation of ARC USB block used in some Freescale chips.
 
+config USB_EHCI_MXC
+	bool "Support for Freescale on-chip EHCI USB controller"
+	depends on USB_EHCI_HCD && ARCH_MXC
+	select USB_EHCI_ROOT_HUB_TT
+	---help---
+	  Variation of ARC USB block used in some Freescale chips.
+
 config USB_EHCI_HCD_PPC_OF
 	bool "EHCI support for PPC USB controller on OF platform bus"
 	depends on USB_EHCI_HCD && PPC_OF
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 7d03549..a7dff61 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1091,6 +1091,11 @@ MODULE_LICENSE ("GPL");
 #define	PLATFORM_DRIVER		ehci_fsl_driver
 #endif
 
+#ifdef CONFIG_USB_EHCI_MXC
+#include "ehci-mxc.c"
+#define PLATFORM_DRIVER		ehci_mxc_driver
+#endif
+
 #ifdef CONFIG_SOC_AU1200
 #include "ehci-au1xxx.c"
 #define	PLATFORM_DRIVER		ehci_hcd_au1xxx_driver
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
new file mode 100644
index 0000000..35c56f4
--- /dev/null
+++ b/drivers/usb/host/ehci-mxc.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/usb/otg.h>
+
+#include <mach/mxc_ehci.h>
+
+#define ULPI_VIEWPORT_OFFSET	0x170
+#define PORTSC_OFFSET		0x184
+#define USBMODE_OFFSET		0x1a8
+#define USBMODE_CM_HOST		3
+
+struct ehci_mxc_priv {
+	struct clk *usbclk, *ahbclk;
+	struct usb_hcd *hcd;
+};
+
+/* called during probe() after chip reset completes */
+static int ehci_mxc_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	/* EHCI registers start at offset 0x100 */
+	ehci->caps = hcd->regs + 0x100;
+	ehci->regs = hcd->regs + 0x100 +
+	    HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	/* data structure init */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	hcd->has_tt = 1;
+
+	ehci->sbrn = 0x20;
+
+	ehci_reset(ehci);
+
+	ehci_port_power(ehci, 0);
+	return 0;
+}
+
+static const struct hc_driver ehci_mxc_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "Freescale On-Chip EHCI Host Controller",
+	.hcd_priv_size = sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = ehci_irq,
+	.flags = HCD_USB2 | HCD_MEMORY,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset = ehci_mxc_setup,
+	.start = ehci_run,
+	.stop = ehci_stop,
+	.shutdown = ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue = ehci_urb_enqueue,
+	.urb_dequeue = ehci_urb_dequeue,
+	.endpoint_disable = ehci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number = ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = ehci_hub_status_data,
+	.hub_control = ehci_hub_control,
+	.bus_suspend = ehci_bus_suspend,
+	.bus_resume = ehci_bus_resume,
+	.relinquish_port = ehci_relinquish_port,
+	.port_handed_over = ehci_port_handed_over,
+};
+
+static int ehci_mxc_drv_probe(struct platform_device *pdev)
+{
+	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
+	struct usb_hcd *hcd;
+	struct resource *res;
+	int irq, ret, temp;
+	struct ehci_mxc_priv *priv;
+	struct device *dev = &pdev->dev;
+
+	dev_info(&pdev->dev, "initializing i.MX USB Controller\n");
+
+	if (!pdata) {
+		dev_err(dev, "No platform data given, bailing out.\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+
+	hcd = usb_create_hcd(&ehci_mxc_hc_driver, dev, dev_name(dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "Found HC with no register addr. Check setup!\n");
+		ret = -ENODEV;
+		goto err_get_resource;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dev_dbg(dev, "controller already in use\n");
+		ret = -EBUSY;
+		goto err_request_mem;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_err(dev, "error mapping memory\n");
+		ret = -EFAULT;
+		goto err_ioremap;
+	}
+
+	/* enable clocks */
+	priv->usbclk = clk_get(dev, "usb");
+	if (IS_ERR(priv->usbclk)) {
+		ret = PTR_ERR(priv->usbclk);
+		goto err_clk;
+	}
+	clk_enable(priv->usbclk);
+
+	if (!cpu_is_mx35()) {
+		priv->ahbclk = clk_get(dev, "usb_ahb");
+		if (IS_ERR(priv->ahbclk)) {
+			ret = PTR_ERR(priv->ahbclk);
+			goto err_clk_ahb;
+		}
+		clk_enable(priv->ahbclk);
+	}
+
+	/* set USBMODE to host mode */
+	temp = readl(hcd->regs + USBMODE_OFFSET);
+	writel(temp | USBMODE_CM_HOST, hcd->regs + USBMODE_OFFSET);
+
+	/* set up the PORTSCx register */
+	writel(pdata->portsc, hcd->regs + PORTSC_OFFSET);
+	mdelay(10);
+
+	/* setup USBCONTROL. */
+	ret = mxc_set_usbcontrol(pdev->id, pdata->flags);
+	if (ret < 0)
+		goto err_init;
+
+	/* call platform specific init function */
+	if (pdata->init) {
+		ret = pdata->init(pdev);
+		if (ret) {
+			dev_err(dev, "platform init failed\n");
+			goto err_init;
+		}
+	}
+
+	/* most platforms need some time to settle changed IO settings */
+	mdelay(10);
+
+	/* Initialize the transceiver */
+	if (pdata->otg) {
+		pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
+		if (otg_init(pdata->otg) != 0)
+			dev_err(dev, "unable to init transceiver\n");
+		else if (otg_set_vbus(pdata->otg, 1) != 0)
+			dev_err(dev, "unable to enable vbus on transceiver\n");
+	}
+
+	priv->hcd = hcd;
+	platform_set_drvdata(pdev, priv);
+
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+	if (ret)
+		goto err_add;
+
+	return 0;
+
+err_add:
+	if (pdata && pdata->exit)
+		pdata->exit(pdev);
+err_init:
+	if (priv->ahbclk) {
+		clk_disable(priv->ahbclk);
+		clk_put(priv->ahbclk);
+	}
+err_clk_ahb:
+	clk_disable(priv->usbclk);
+	clk_put(priv->usbclk);
+err_clk:
+	iounmap(hcd->regs);
+err_ioremap:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_request_mem:
+err_get_resource:
+	kfree(priv);
+err_alloc:
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
+{
+	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
+	struct ehci_mxc_priv *priv = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = priv->hcd;
+
+	if (pdata && pdata->exit)
+		pdata->exit(pdev);
+
+	if (pdata->otg)
+		otg_shutdown(pdata->otg);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(pdev, NULL);
+
+	clk_disable(priv->usbclk);
+	clk_put(priv->usbclk);
+	if (priv->ahbclk) {
+		clk_disable(priv->ahbclk);
+		clk_put(priv->ahbclk);
+	}
+
+	kfree(priv);
+
+	return 0;
+}
+
+static void ehci_mxc_drv_shutdown(struct platform_device *pdev)
+{
+	struct ehci_mxc_priv *priv = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = priv->hcd;
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+}
+
+MODULE_ALIAS("platform:mxc-ehci");
+
+static struct platform_driver ehci_mxc_driver = {
+	.probe = ehci_mxc_drv_probe,
+	.remove = __exit_p(ehci_mxc_drv_remove),
+	.shutdown = ehci_mxc_drv_shutdown,
+	.driver = {
+		   .name = "mxc-ehci",
+	},
+};
-- 
1.6.3.3

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

* [PATCH 5/5] MX3: add USB support for lilly1131
  2009-09-02 20:47       ` [PATCH 4/5] USB: Add EHCI support for MX27 and MX31 based boards Daniel Mack
@ 2009-09-02 20:47         ` Daniel Mack
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Mack @ 2009-09-02 20:47 UTC (permalink / raw)
  To: linux-arm-kernel

This adds support for OTG, host1 and host2 ports on lilly1131.

Signed-off-by: Daniel Mack <daniel@caiaq.de>
---
 arch/arm/mach-mx3/Kconfig     |    1 +
 arch/arm/mach-mx3/mx31lilly.c |  147 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 148 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index 851f245..d69fa73 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -68,6 +68,7 @@ config MACH_MX31MOBOARD
 config MACH_MX31LILLY
 	bool "Support MX31 LILLY-1131 platforms (INCO startec)"
 	select ARCH_MX31
+	select MXC_ULPI
 	help
 	  Include support for mx31 based LILLY1131 modules. This includes
 	  specific configurations for the board and its peripherals.
diff --git a/arch/arm/mach-mx3/mx31lilly.c b/arch/arm/mach-mx3/mx31lilly.c
index 4230251..e75c232 100644
--- a/arch/arm/mach-mx3/mx31lilly.c
+++ b/arch/arm/mach-mx3/mx31lilly.c
@@ -31,6 +31,10 @@
 #include <linux/interrupt.h>
 #include <linux/smsc911x.h>
 #include <linux/mtd/physmap.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -41,6 +45,8 @@
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
 #include <mach/board-mx31lilly.h>
+#include <mach/mxc_ehci.h>
+#include <mach/ulpi.h>
 
 #include "devices.h"
 
@@ -105,6 +111,137 @@ static struct platform_device physmap_flash_device = {
 	.num_resources = 1,
 };
 
+/* USB */
+
+#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
+			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
+
+static int usbotg_init(struct platform_device *pdev)
+{
+	unsigned int pins[] = {
+		MX31_PIN_USBOTG_DATA0__USBOTG_DATA0,
+		MX31_PIN_USBOTG_DATA1__USBOTG_DATA1,
+		MX31_PIN_USBOTG_DATA2__USBOTG_DATA2,
+		MX31_PIN_USBOTG_DATA3__USBOTG_DATA3,
+		MX31_PIN_USBOTG_DATA4__USBOTG_DATA4,
+		MX31_PIN_USBOTG_DATA5__USBOTG_DATA5,
+		MX31_PIN_USBOTG_DATA6__USBOTG_DATA6,
+		MX31_PIN_USBOTG_DATA7__USBOTG_DATA7,
+		MX31_PIN_USBOTG_CLK__USBOTG_CLK,
+		MX31_PIN_USBOTG_DIR__USBOTG_DIR,
+		MX31_PIN_USBOTG_NXT__USBOTG_NXT,
+		MX31_PIN_USBOTG_STP__USBOTG_STP,
+	};
+
+	mxc_iomux_setup_multiple_pins(pins, ARRAY_SIZE(pins), "USB OTG");
+
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, USB_PAD_CFG);
+
+	mxc_iomux_set_gpr(MUX_PGP_USB_4WIRE, true);
+	mxc_iomux_set_gpr(MUX_PGP_USB_COMMON, true);
+
+	/* chip select */
+	mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_DTR_DCE2, IOMUX_CONFIG_GPIO),
+				"USBOTG_CS");
+	gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE2), "USBH1 CS");
+	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE2), 0);
+
+	return 0;
+}
+
+static int usbh1_init(struct platform_device *pdev)
+{
+	int pins[] = {
+		MX31_PIN_CSPI1_MOSI__USBH1_RXDM,
+		MX31_PIN_CSPI1_MISO__USBH1_RXDP,
+		MX31_PIN_CSPI1_SS0__USBH1_TXDM,
+		MX31_PIN_CSPI1_SS1__USBH1_TXDP,
+		MX31_PIN_CSPI1_SS2__USBH1_RCV,
+		MX31_PIN_CSPI1_SCLK__USBH1_OEB,
+		MX31_PIN_CSPI1_SPI_RDY__USBH1_FS,
+	};
+
+	mxc_iomux_setup_multiple_pins(pins, ARRAY_SIZE(pins), "USB H1");
+
+	mxc_iomux_set_pad(MX31_PIN_CSPI1_MOSI, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_CSPI1_MISO, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_CSPI1_SS0, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_CSPI1_SS1, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_CSPI1_SS2, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_CSPI1_SCLK, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_CSPI1_SPI_RDY, USB_PAD_CFG);
+
+	mxc_iomux_set_gpr(MUX_PGP_USB_SUSPEND, true);
+
+	return 0;
+}
+
+static int usbh2_init(struct platform_device *pdev)
+{
+	int pins[] = {
+		MX31_PIN_USBH2_DATA0__USBH2_DATA0,
+		MX31_PIN_USBH2_DATA1__USBH2_DATA1,
+		MX31_PIN_USBH2_CLK__USBH2_CLK,
+		MX31_PIN_USBH2_DIR__USBH2_DIR,
+		MX31_PIN_USBH2_NXT__USBH2_NXT,
+		MX31_PIN_USBH2_STP__USBH2_STP,
+	};
+
+	mxc_iomux_setup_multiple_pins(pins, ARRAY_SIZE(pins), "USB H2");
+
+	mxc_iomux_set_pad(MX31_PIN_USBH2_CLK, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DIR, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_NXT, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_STP, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DATA0, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DATA1, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SRXD6, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_STXD6, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SFS3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SCK3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SRXD3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_STXD3, USB_PAD_CFG);
+
+	mxc_iomux_set_gpr(MUX_PGP_UH2, true);
+
+	/* chip select */
+	mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_GPIO),
+				"USBH2_CS");
+	gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), "USBH2 CS");
+	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), 0);
+
+	return 0;
+}
+
+static struct mxc_usbh_platform_data usbotg_pdata = {
+	.init	= usbotg_init,
+	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
+	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
+};
+
+static struct mxc_usbh_platform_data usbh1_pdata = {
+	.init	= usbh1_init,
+	.portsc	= MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
+	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI,
+};
+
+static struct mxc_usbh_platform_data usbh2_pdata = {
+	.init	= usbh2_init,
+	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
+	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
+};
+
 static struct platform_device *devices[] __initdata = {
 	&smsc91x_device,
 	&physmap_flash_device,
@@ -132,6 +269,16 @@ static void __init mx31lilly_board_init(void)
 	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_MISO__SDA, "I2C SDA");
 
 	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	/* USB */
+	usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+
+	mxc_register_device(&mxc_otg_host, &usbotg_pdata);
+	mxc_register_device(&mxc_usbh1, &usbh1_pdata);
+	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 }
 
 static void __init mx31lilly_timer_init(void)
-- 
1.6.3.3

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

* Patches for Freescale MXC SoCs and direct ULPI communication [v3]
  2009-09-02 20:47 Patches for Freescale MXC SoCs and direct ULPI communication [v3] Daniel Mack
  2009-09-02 20:47 ` [PATCH 1/5] USB OTG: add support for ulpi connected external transceivers Daniel Mack
@ 2009-09-03 15:41 ` Valentin Longchamp
  2009-09-07 10:20   ` s.hauer at pengutronix.de
  1 sibling, 1 reply; 10+ messages in thread
From: Valentin Longchamp @ 2009-09-03 15:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Daniel,

Daniel Mack wrote:
> Sorry for the long delay on this issue.
> 
> Here comes another round of four patches to support the EHCI ports on
> Freescale's MX2/MX3 SoCs.
> 
> The difference to the last version I've sent is that the ISP1504
> specific drivers has become a generic ULPI driver now with all the
> defines renamed.
> 
> Also the driver does not set DRV_VBUS and DRV_VBUS_EXT blindly
> anymore but uses a flags field in the otg_transceiver struct which can
> be specified when creating the device. This allows the adaption of the
> code to a wider variety of applications.
> 
> As a reference, I've added a patch to add board specific support code
> for the lilly1131 module.

I have such a patch for mx31moboard too. Sascha, should I send it to you 
now or wait ?

> 
> Let me know if that still works for other boards and if that version
> looks better to you.

I cannnot say much about the code, it seems that you have addressed all 
the comments on the previous version (especially about the ulpi 
genericity). I can however confirm that it still works well on mx31moboard.

> 
> Again, #1, #2 and #4 are supposed to go thru the USB folks' channel,
> while the rest might be picked by Sascha Hauer eventually.
> 
> Thanks,
> Daniel
> 
> [PATCH 1/5] USB OTG: add support for ulpi connected external transceivers
> [PATCH 2/5] USB OTG: Add generic driver for ULPI OTG transceiver
> [PATCH 3/5] MXC: Add support for ULPI Viewports
> [PATCH 4/5] USB: Add EHCI support for MX27 and MX31 based boards
> [PATCH 5/5] MX3: add USB support for lilly1131

Val

-- 
Valentin Longchamp, PhD Student, EPFL-STI-LSRO1
valentin.longchamp at epfl.ch, Phone: +41216937827
http://people.epfl.ch/valentin.longchamp
MEA3485, Station 9, CH-1015 Lausanne

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

* Patches for Freescale MXC SoCs and direct ULPI communication [v3]
  2009-09-03 15:41 ` Patches for Freescale MXC SoCs and direct ULPI communication [v3] Valentin Longchamp
@ 2009-09-07 10:20   ` s.hauer at pengutronix.de
  2009-10-07  6:34     ` javier Martin
  0 siblings, 1 reply; 10+ messages in thread
From: s.hauer at pengutronix.de @ 2009-09-07 10:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Back from holiday...

On Thu, Sep 03, 2009 at 05:41:58PM +0200, Valentin Longchamp wrote:
> Hi Daniel,
>
> Daniel Mack wrote:
>> Sorry for the long delay on this issue.
>>
>> Here comes another round of four patches to support the EHCI ports on
>> Freescale's MX2/MX3 SoCs.
>>
>> The difference to the last version I've sent is that the ISP1504
>> specific drivers has become a generic ULPI driver now with all the
>> defines renamed.
>>
>> Also the driver does not set DRV_VBUS and DRV_VBUS_EXT blindly
>> anymore but uses a flags field in the otg_transceiver struct which can
>> be specified when creating the device. This allows the adaption of the
>> code to a wider variety of applications.
>>
>> As a reference, I've added a patch to add board specific support code
>> for the lilly1131 module.
>
> I have such a patch for mx31moboard too. Sascha, should I send it to you  
> now or wait ?

Please wait till it's clear that the patches go in the way they are,
otherwise I end up keeping patches that still need fixups.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Patches for Freescale MXC SoCs and direct ULPI communication [v3]
  2009-09-07 10:20   ` s.hauer at pengutronix.de
@ 2009-10-07  6:34     ` javier Martin
  2009-10-07  6:48       ` Daniel Mack
  0 siblings, 1 reply; 10+ messages in thread
From: javier Martin @ 2009-10-07  6:34 UTC (permalink / raw)
  To: linux-arm-kernel

What is the status regarding to mainline about these patches?

Have they been applied somewhere?

Thanks.

-- 
Javier Martin
Vista Silicon S.L.
CDTUC - FASE C - Oficina S-345
Avda de los Castros s/n
39005- Santander. Cantabria. Spain
+34 942 25 32 60
www.vista-silicon.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20091007/d74e2226/attachment.htm>

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

* Patches for Freescale MXC SoCs and direct ULPI communication [v3]
  2009-10-07  6:34     ` javier Martin
@ 2009-10-07  6:48       ` Daniel Mack
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Mack @ 2009-10-07  6:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 07, 2009 at 08:34:38AM +0200, javier Martin wrote:
> What is the status regarding to mainline about these patches?
> 
> Have they been applied somewhere?

Not yet. There are some API change requests pending which I will do as
soon as I can. I'm currently abroad without access to the hardware, so I
can't work on this issue. Please be patient.

Thanks,
Daniel

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

end of thread, other threads:[~2009-10-07  6:48 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-02 20:47 Patches for Freescale MXC SoCs and direct ULPI communication [v3] Daniel Mack
2009-09-02 20:47 ` [PATCH 1/5] USB OTG: add support for ulpi connected external transceivers Daniel Mack
2009-09-02 20:47   ` [PATCH 2/5] USB OTG: Add generic driver for ULPI OTG transceiver Daniel Mack
2009-09-02 20:47     ` [PATCH 3/5] MXC: Add support for ULPI Viewports Daniel Mack
2009-09-02 20:47       ` [PATCH 4/5] USB: Add EHCI support for MX27 and MX31 based boards Daniel Mack
2009-09-02 20:47         ` [PATCH 5/5] MX3: add USB support for lilly1131 Daniel Mack
2009-09-03 15:41 ` Patches for Freescale MXC SoCs and direct ULPI communication [v3] Valentin Longchamp
2009-09-07 10:20   ` s.hauer at pengutronix.de
2009-10-07  6:34     ` javier Martin
2009-10-07  6:48       ` Daniel Mack

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.