diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 08:12:43 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 08:12:43 -0800 |
commit | 79c9601c2e0dbbe69895d302de4d19f3a31fbd30 (patch) | |
tree | 78d4be2df851b2b4106adcfd736622a90cecf9e9 /arch/arm/plat-mxc/ulpi.c | |
parent | 41440ffe21f29bdb985cab76b2d0b06d83e63b19 (diff) | |
parent | 3d14b5beba35250c548d3851a2b84fce742d8311 (diff) | |
download | kernel_samsung_tuna-79c9601c2e0dbbe69895d302de4d19f3a31fbd30.zip kernel_samsung_tuna-79c9601c2e0dbbe69895d302de4d19f3a31fbd30.tar.gz kernel_samsung_tuna-79c9601c2e0dbbe69895d302de4d19f3a31fbd30.tar.bz2 |
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (272 commits)
Fix soc_common PCMCIA configuration
ARM: 5827/1: SA1100: h3100/h3600: emit messages on failed gpio_request
ARM: 5826/1: SA1100: h3100/h3600: always build htc-egpio driver
ARM: 5825/1: SA1100: h3600: update defconfig
ARM: 5824/1: SA1100: reuse h3600 PCMCIA driver on h3100
ARM: 5823/1: SA1100: h3100/h3600: add support for gpio-keys
ARM: 5822/1: SA1100: h3100/h3600: clean up #includes
ARM: 5821/1: SA1100: h3100/h3600: revise copyright boilerplates
ARM: 5820/1: SA1100: h3100/h3600: split h3600.c
ARM: 5819/1: SA1100: h3100/h3600: merge h3600.h and h3600_gpio.h into h3xxx.h
ARM: 5818/1: SA1100: h3100/h3600: drop old GPIO definitions
ARM: 5817/1: SA1100: h3100/h3600: configure all unused gpios as inputs
ARM: 5816/1: SA1100: h3600: remove IRQ_GPIO_* definitions
ARM: 5815/1: SA1100: h3100/h3600: remove now unused assign_h3600_egpio handlers
ARM: 5814/1: SA1100: h3100/h3600: convert all users of assign_h3600_egpio to gpiolib
ARM: 5813/1: SA1100: h3100/h3600: add htc-egpio driver
ARM: 5812/1: SA1100: h3100/h3600: separate machine-specific LCD helpers
ARM: 5811/2: pcmcia: convert sa1100_h3600 driver to gpiolib
ARM: 5799/1: SA1100: h3600: stop setting direction for LCD pins
ARM: 5798/1: SA1100: h3600: remove unused cruft from h3600.h
...
Diffstat (limited to 'arch/arm/plat-mxc/ulpi.c')
-rw-r--r-- | arch/arm/plat-mxc/ulpi.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/arch/arm/plat-mxc/ulpi.c b/arch/arm/plat-mxc/ulpi.c new file mode 100644 index 0000000..582c6df --- /dev/null +++ b/arch/arm/plat-mxc/ulpi.c @@ -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); + |