[PATCH 2/5] MXC: Add support for ULPI Viewports

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The ARC USB OTG Core has support for accessing ULPI tranceivers
through so called ULPI viewports. As the ARC core is found on
other systems aswell, this is not Freescale specific and should
live under drivers/usb instead.

Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
---
 arch/arm/mach-mx2/Kconfig             |    1 +
 arch/arm/plat-mxc/Kconfig             |    2 +
 arch/arm/plat-mxc/Makefile            |    1 +
 arch/arm/plat-mxc/include/mach/ulpi.h |   31 +++++++++
 arch/arm/plat-mxc/ulpi.c              |  120 +++++++++++++++++++++++++++++++++
 5 files changed, 155 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/mach-mx2/Kconfig b/arch/arm/mach-mx2/Kconfig
index 42a7888..a8e06d0 100644
--- a/arch/arm/mach-mx2/Kconfig
+++ b/arch/arm/mach-mx2/Kconfig
@@ -40,6 +40,7 @@ choice
 config MACH_PCM970_BASEBOARD
 	prompt "PHYTEC PCM970 development board"
 	bool
+	select MXC_ULPI
 	help
 	  This adds board specific devices that can be found on Phytec's
 	  PCM970 evaluation board.
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 17d0e99..b5668a8 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -51,4 +51,6 @@ config MXC_PWM
 	help
 	  Enable support for the i.MX PWM controller(s).
 
+config MXC_ULPI
+	bool
 endif
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 0554063..3ce830a 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -8,3 +8,4 @@ obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o system.o
 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_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..0397fdb
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/ulpi.h
@@ -0,0 +1,31 @@
+#ifndef __MACH_ULPI_H
+#define __MACH_ULPI_H
+
+int ulpi_set(u8 bits, int reg, void __iomem *view);
+int ulpi_clear(u8 bits, int reg, void __iomem *view);
+int ulpi_read(int reg, void __iomem *view);
+
+/* ISP 1504 register addresses */
+#define ISP1504_VID_LOW		0x00	/* Vendor ID low */
+#define ISP1504_VID_HIGH	0x01	/* Vendor ID high */
+#define ISP1504_PID_LOW		0x02	/* Product ID low */
+#define ISP1504_PID_HIGH	0x03	/* Product ID high */
+#define ISP1504_ITFCTL		0x07	/* Interface Control */
+#define ISP1504_OTGCTL		0x0A	/* OTG Control */
+
+/* add to above register address to access Set/Clear functions */
+#define ISP1504_REG_SET		0x01
+#define ISP1504_REG_CLEAR	0x02
+
+/* 1504 OTG Control Register bits */
+#define USE_EXT_VBUS_IND	(1 << 7)	/* Use ext. Vbus indicator */
+#define DRV_VBUS_EXT		(1 << 6)	/* Drive Vbus external */
+#define DRV_VBUS		(1 << 5)	/* Drive Vbus */
+#define CHRG_VBUS		(1 << 4)	/* Charge Vbus */
+#define DISCHRG_VBUS		(1 << 3)	/* Discharge Vbus */
+#define DM_PULL_DOWN		(1 << 2)	/* enable DM Pull Down */
+#define DP_PULL_DOWN		(1 << 1)	/* enable DP Pull Down */
+#define ID_PULL_UP		(1 << 0)	/* enable ID Pull Up */
+
+#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..355fda1
--- /dev/null
+++ b/arch/arm/plat-mxc/ulpi.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2008 Sascha Hauer, Pengutronix <s.hauer@xxxxxxxxxxxxxx>
+ *
+ * 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 <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, uint32_t bit)
+{
+	uint32_t data;
+	int timeout = 10000;
+
+	data = __raw_readl(view);
+	while (data & bit) {
+		if (!timeout--)
+			return -ETIMEDOUT;
+
+		udelay(1);
+		data = __raw_readl(view);
+	}
+	return (data >> ULPIVW_RDATA_SHIFT) & ULPIVW_RDATA_MASK;
+}
+
+int ulpi_read(int reg, void __iomem *view)
+{
+	int ret;
+
+	/* 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);
+}
+EXPORT_SYMBOL(ulpi_read);
+
+int ulpi_set(u8 bits, int reg, void __iomem *view)
+{
+	int ret;
+
+	/* 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 + ISP1504_REG_SET) << ULPIVW_ADDR_SHIFT) |
+		      ((bits & ULPIVW_WDATA_MASK) << ULPIVW_WDATA_SHIFT)),
+		     view);
+
+	/* wait for completion */
+	ret = ulpi_poll(view, ULPIVW_RUN);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+EXPORT_SYMBOL(ulpi_set);
+
+int ulpi_clear(u8 bits, int reg, void __iomem *view)
+{
+	int ret;
+
+	__raw_writel((ULPIVW_RUN | ULPIVW_WRITE |
+		      ((reg + ISP1504_REG_CLEAR) << ULPIVW_ADDR_SHIFT) |
+		      ((bits & ULPIVW_WDATA_MASK) << ULPIVW_WDATA_SHIFT)),
+		     view);
+
+	/* wait for completion */
+	ret = ulpi_poll(view, ULPIVW_RUN);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+EXPORT_SYMBOL(ulpi_clear);
+
-- 
1.6.2.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux