MXC: Add support for ULPI Viewports

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: Daniel Mack <daniel@caiaq.de>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: linux-usb@vger.kernel.org
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Daniel Mack 2009-11-05 09:44:09 +01:00 committed by Sascha Hauer
parent 04ea3c8019
commit f4f8bda232
4 changed files with 124 additions and 0 deletions

View File

@ -69,6 +69,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

View File

@ -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

View File

@ -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 */

113
arch/arm/plat-mxc/ulpi.c Normal file
View File

@ -0,0 +1,113 @@
/*
* Copyright 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
* Copyright 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., 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)
{
int timeout = 10000;
while (timeout--) {
u32 data = __raw_readl(view);
if (!(data & bit))
return 0;
cpu_relax();
};
printk(KERN_WARNING "timeout polling for ULPI device\n");
return -ETIMEDOUT;
}
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)
return ret;
}
/* read the register */
__raw_writel((ULPIVW_RUN | (reg << ULPIVW_ADDR_SHIFT)), view);
/* wait for completion */
ret = ulpi_poll(view, ULPIVW_RUN);
if (ret)
return ret;
return (__raw_readl(view) >> ULPIVW_RDATA_SHIFT) & ULPIVW_RDATA_MASK;
}
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)
return ret;
}
__raw_writel((ULPIVW_RUN | ULPIVW_WRITE |
(reg << ULPIVW_ADDR_SHIFT) |
((val & ULPIVW_WDATA_MASK) << ULPIVW_WDATA_SHIFT)), view);
/* wait for completion */
return ulpi_poll(view, ULPIVW_RUN);
}
struct otg_io_access_ops mxc_ulpi_access_ops = {
.read = ulpi_read,
.write = ulpi_write,
};
EXPORT_SYMBOL_GPL(mxc_ulpi_access_ops);