summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/mxcmmc.c8
-rw-r--r--drivers/mmc/tegra2_mmc.c16
-rw-r--r--drivers/spi/kirkwood_spi.c2
-rw-r--r--drivers/spi/mxs_spi.c12
-rw-r--r--drivers/usb/host/Makefile3
-rw-r--r--drivers/usb/host/ehci-marvell.c (renamed from drivers/usb/host/ehci-kirkwood.c)36
-rw-r--r--drivers/usb/host/ehci-omap.c255
-rw-r--r--drivers/usb/ulpi/Makefile1
-rw-r--r--drivers/usb/ulpi/omap-ulpi-viewport.c105
-rw-r--r--drivers/usb/ulpi/ulpi-viewport.c32
-rw-r--r--drivers/usb/ulpi/ulpi.c54
11 files changed, 459 insertions, 65 deletions
diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c
index 8afb221..d58c18b 100644
--- a/drivers/mmc/mxcmmc.c
+++ b/drivers/mmc/mxcmmc.c
@@ -25,9 +25,7 @@
#include <mmc.h>
#include <asm/errno.h>
#include <asm/io.h>
-#ifdef CONFIG_MX27
#include <asm/arch/clock.h>
-#endif
#define DRIVER_NAME "mxc-mmc"
@@ -422,7 +420,7 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
{
unsigned int divider;
int prescaler = 0;
- unsigned long clk_in = imx_get_perclk2();
+ unsigned long clk_in = mxc_get_clock(MXC_ESDHC_CLK);
while (prescaler <= 0x800) {
for (divider = 1; divider <= 0xF; divider++) {
@@ -509,8 +507,8 @@ static int mxcmci_initialize(bd_t *bis)
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
- mmc->f_min = imx_get_perclk2() >> 7;
- mmc->f_max = imx_get_perclk2() >> 1;
+ mmc->f_min = mxc_get_clock(MXC_ESDHC_CLK) >> 7;
+ mmc->f_max = mxc_get_clock(MXC_ESDHC_CLK) >> 1;
mmc->b_max = 0;
diff --git a/drivers/mmc/tegra2_mmc.c b/drivers/mmc/tegra2_mmc.c
index 5b4c9f6..3191557 100644
--- a/drivers/mmc/tegra2_mmc.c
+++ b/drivers/mmc/tegra2_mmc.c
@@ -114,6 +114,14 @@ static void mmc_set_transfer_mode(struct mmc_host *host, struct mmc_data *data)
if (data->flags & MMC_DATA_READ)
mode |= TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ;
+ if (data->flags & MMC_DATA_WRITE) {
+ if ((uintptr_t)data->src & (ARCH_DMA_MINALIGN - 1))
+ printf("Warning: unaligned write to %p may fail\n",
+ data->src);
+ flush_dcache_range((ulong)data->src, (ulong)data->src +
+ data->blocks * data->blocksize);
+ }
+
writew(mode, &host->reg->trnmod);
}
@@ -310,6 +318,14 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
}
}
writel(mask, &host->reg->norintsts);
+ if (data->flags & MMC_DATA_READ) {
+ if ((uintptr_t)data->dest & (ARCH_DMA_MINALIGN - 1))
+ printf("Warning: unaligned read from %p "
+ "may fail\n", data->dest);
+ invalidate_dcache_range((ulong)data->dest,
+ (ulong)data->dest +
+ data->blocks * data->blocksize);
+ }
}
udelay(1000);
diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c
index dfe542d..db8ba8b 100644
--- a/drivers/spi/kirkwood_spi.c
+++ b/drivers/spi/kirkwood_spi.c
@@ -66,7 +66,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
debug("data = 0x%08x \n", data);
writel(KWSPI_SMEMRDIRQ, &spireg->irq_cause);
- writel(KWSPI_IRQMASK, spireg->irq_mask);
+ writel(KWSPI_IRQMASK, &spireg->irq_mask);
/* program mpp registers to select SPI_CSn */
if (cs) {
diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
index 4c27fef..adb9ca8 100644
--- a/drivers/spi/mxs_spi.c
+++ b/drivers/spi/mxs_spi.c
@@ -129,9 +129,15 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
int len = bitlen / 8;
const char *tx = dout;
char *rx = din;
-
- if (bitlen == 0)
- return 0;
+ char dummy;
+
+ if (bitlen == 0) {
+ if (flags & SPI_XFER_END) {
+ rx = &dummy;
+ len = 1;
+ } else
+ return 0;
+ }
if (!rx && !tx)
return 0;
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 77e217f..7c4df53 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -43,9 +43,10 @@ endif
COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
COBJS-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o
COBJS-$(CONFIG_USB_EHCI_MX5) += ehci-mx5.o
+COBJS-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o
COBJS-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o
COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o
-COBJS-$(CONFIG_USB_EHCI_KIRKWOOD) += ehci-kirkwood.o
+COBJS-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o
COBJS-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
diff --git a/drivers/usb/host/ehci-kirkwood.c b/drivers/usb/host/ehci-marvell.c
index 6300587..89c8af7 100644
--- a/drivers/usb/host/ehci-kirkwood.c
+++ b/drivers/usb/host/ehci-marvell.c
@@ -28,10 +28,17 @@
#include "ehci.h"
#include "ehci-core.h"
#include <asm/arch/cpu.h>
+
+#if defined(CONFIG_KIRKWOOD)
#include <asm/arch/kirkwood.h>
+#elif defined(CONFIG_ORION5X)
+#include <asm/arch/orion5x.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
-#define rdl(off) readl(KW_USB20_BASE + (off))
-#define wrl(off, val) writel((val), KW_USB20_BASE + (off))
+#define rdl(off) readl(MVUSB0_BASE + (off))
+#define wrl(off, val) writel((val), MVUSB0_BASE + (off))
#define USB_WINDOW_CTRL(i) (0x320 + ((i) << 4))
#define USB_WINDOW_BASE(i) (0x324 + ((i) << 4))
@@ -43,23 +50,23 @@
static void usb_brg_adrdec_setup(void)
{
int i;
- u32 size, attrib;
+ u32 size, base, attrib;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
/* Enable DRAM bank */
switch (i) {
case 0:
- attrib = KWCPU_ATTR_DRAM_CS0;
+ attrib = MVUSB0_CPU_ATTR_DRAM_CS0;
break;
case 1:
- attrib = KWCPU_ATTR_DRAM_CS1;
+ attrib = MVUSB0_CPU_ATTR_DRAM_CS1;
break;
case 2:
- attrib = KWCPU_ATTR_DRAM_CS2;
+ attrib = MVUSB0_CPU_ATTR_DRAM_CS2;
break;
case 3:
- attrib = KWCPU_ATTR_DRAM_CS3;
+ attrib = MVUSB0_CPU_ATTR_DRAM_CS3;
break;
default:
/* invalide bank, disable access */
@@ -67,15 +74,16 @@ static void usb_brg_adrdec_setup(void)
break;
}
- size = kw_sdram_bs(i);
+ size = gd->bd->bi_dram[i].size;
+ base = gd->bd->bi_dram[i].start;
if ((size) && (attrib))
wrl(USB_WINDOW_CTRL(i),
- KWCPU_WIN_CTRL_DATA(size, USB_TARGET_DRAM,
- attrib, KWCPU_WIN_ENABLE));
+ MVCPU_WIN_CTRL_DATA(size, USB_TARGET_DRAM,
+ attrib, MVCPU_WIN_ENABLE));
else
- wrl(USB_WINDOW_CTRL(i), KWCPU_WIN_DISABLE);
+ wrl(USB_WINDOW_CTRL(i), MVCPU_WIN_DISABLE);
- wrl(USB_WINDOW_BASE(i), kw_sdram_bar(i));
+ wrl(USB_WINDOW_BASE(i), base);
}
}
@@ -87,11 +95,11 @@ int ehci_hcd_init(void)
{
usb_brg_adrdec_setup();
- hccr = (struct ehci_hccr *)(KW_USB20_BASE + 0x100);
+ hccr = (struct ehci_hccr *)(MVUSB0_BASE + 0x100);
hcor = (struct ehci_hcor *)((uint32_t) hccr
+ HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
- debug("Kirkwood-ehci: init hccr %x and hcor %x hc_length %d\n",
+ debug("ehci-marvell: init hccr %x and hcor %x hc_length %d\n",
(uint32_t)hccr, (uint32_t)hcor,
(uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
new file mode 100644
index 0000000..00f787f
--- /dev/null
+++ b/drivers/usb/host/ehci-omap.c
@@ -0,0 +1,255 @@
+/*
+ * (C) Copyright 2011 Ilya Yanok, Emcraft Systems
+ * (C) Copyright 2004-2008
+ * Texas Instruments, <www.ti.com>
+ *
+ * Derived from Beagle Board code by
+ * Sunil Kumar <sunilsaini05@gmail.com>
+ * Shashi Ranjan <shashiranjanmca05@gmail.com>
+ *
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ */
+#include <common.h>
+#include <usb.h>
+#include <usb/ulpi.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/ehci.h>
+#include <asm/ehci-omap.h>
+#include "ehci-core.h"
+
+static struct omap_uhh *const uhh = (struct omap_uhh *)OMAP_UHH_BASE;
+static struct omap_usbtll *const usbtll = (struct omap_usbtll *)OMAP_USBTLL_BASE;
+static struct omap_ehci *const ehci = (struct omap_ehci *)OMAP_EHCI_BASE;
+
+static int omap_uhh_reset(void)
+{
+ unsigned long init = get_timer(0);
+
+ /* perform UHH soft reset, and wait until reset is complete */
+ writel(OMAP_UHH_SYSCONFIG_SOFTRESET, &uhh->sysc);
+
+ /* Wait for UHH reset to complete */
+ while (!(readl(&uhh->syss) & OMAP_UHH_SYSSTATUS_EHCI_RESETDONE))
+ if (get_timer(init) > CONFIG_SYS_HZ) {
+ debug("OMAP UHH error: timeout resetting ehci\n");
+ return -EL3RST;
+ }
+
+ return 0;
+}
+
+static int omap_ehci_tll_reset(void)
+{
+ unsigned long init = get_timer(0);
+
+ /* perform TLL soft reset, and wait until reset is complete */
+ writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET, &usbtll->sysc);
+
+ /* Wait for TLL reset to complete */
+ while (!(readl(&usbtll->syss) & OMAP_USBTLL_SYSSTATUS_RESETDONE))
+ if (get_timer(init) > CONFIG_SYS_HZ) {
+ debug("OMAP EHCI error: timeout resetting TLL\n");
+ return -EL3RST;
+ }
+
+ return 0;
+}
+
+static void omap_usbhs_hsic_init(int port)
+{
+ unsigned int reg;
+
+ /* Enable channels now */
+ reg = readl(&usbtll->channel_conf + port);
+
+ setbits_le32(&reg, (OMAP_TLL_CHANNEL_CONF_CHANMODE_TRANSPARENT_UTMI
+ | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
+ | OMAP_TLL_CHANNEL_CONF_DRVVBUS
+ | OMAP_TLL_CHANNEL_CONF_CHRGVBUS
+ | OMAP_TLL_CHANNEL_CONF_CHANEN));
+
+ writel(reg, &usbtll->channel_conf + port);
+}
+
+static void omap_ehci_soft_phy_reset(int port)
+{
+ struct ulpi_viewport ulpi_vp;
+
+ ulpi_vp.viewport_addr = (u32)&ehci->insreg05_utmi_ulpi;
+ ulpi_vp.port_num = port;
+
+ ulpi_reset(&ulpi_vp);
+}
+
+inline int __board_usb_init(void)
+{
+ return 0;
+}
+int board_usb_init(void) __attribute__((weak, alias("__board_usb_init")));
+
+#if defined(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO) || \
+ defined(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO)
+/* controls PHY(s) reset signal(s) */
+static inline void omap_ehci_phy_reset(int on, int delay)
+{
+ /*
+ * Refer ISSUE1:
+ * Hold the PHY in RESET for enough time till
+ * PHY is settled and ready
+ */
+ if (delay && !on)
+ udelay(delay);
+#ifdef CONFIG_OMAP_EHCI_PHY1_RESET_GPIO
+ gpio_request(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, "USB PHY1 reset");
+ gpio_direction_output(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, !on);
+#endif
+#ifdef CONFIG_OMAP_EHCI_PHY2_RESET_GPIO
+ gpio_request(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, "USB PHY2 reset");
+ gpio_direction_output(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, !on);
+#endif
+
+ /* Hold the PHY in RESET for enough time till DIR is high */
+ /* Refer: ISSUE1 */
+ if (delay && on)
+ udelay(delay);
+}
+#else
+#define omap_ehci_phy_reset(on, delay) do {} while (0)
+#endif
+
+/* Reset is needed otherwise the kernel-driver will throw an error. */
+int omap_ehci_hcd_stop(void)
+{
+ debug("Resetting OMAP EHCI\n");
+ omap_ehci_phy_reset(1, 0);
+
+ if (omap_uhh_reset() < 0)
+ return -1;
+
+ if (omap_ehci_tll_reset() < 0)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Initialize the OMAP EHCI controller and PHY.
+ * Based on "drivers/usb/host/ehci-omap.c" from Linux 3.1
+ * See there for additional Copyrights.
+ */
+int omap_ehci_hcd_init(struct omap_usbhs_board_data *usbhs_pdata)
+{
+ int ret;
+ unsigned int i, reg = 0, rev = 0;
+
+ debug("Initializing OMAP EHCI\n");
+
+ ret = board_usb_init();
+ if (ret < 0)
+ return ret;
+
+ /* Put the PHY in RESET */
+ omap_ehci_phy_reset(1, 10);
+
+ ret = omap_uhh_reset();
+ if (ret < 0)
+ return ret;
+
+ ret = omap_ehci_tll_reset();
+ if (ret)
+ return ret;
+
+ writel(OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
+ OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
+ OMAP_USBTLL_SYSCONFIG_CACTIVITY, &usbtll->sysc);
+
+ /* Put UHH in NoIdle/NoStandby mode */
+ writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc);
+
+ /* setup ULPI bypass and burst configurations */
+ clrsetbits_le32(&reg, OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN,
+ (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN |
+ OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN |
+ OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN));
+
+ rev = readl(&uhh->rev);
+ if (rev == OMAP_USBHS_REV1) {
+ if (is_ehci_phy_mode(usbhs_pdata->port_mode[0]))
+ clrbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS);
+ else
+ setbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS);
+
+ if (is_ehci_phy_mode(usbhs_pdata->port_mode[1]))
+ clrbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS);
+ else
+ setbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS);
+
+ if (is_ehci_phy_mode(usbhs_pdata->port_mode[2]))
+ clrbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS);
+ else
+ setbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS);
+ } else if (rev == OMAP_USBHS_REV2) {
+ clrsetbits_le32(&reg, (OMAP_P1_MODE_CLEAR | OMAP_P2_MODE_CLEAR),
+ OMAP4_UHH_HOSTCONFIG_APP_START_CLK);
+
+ /* Clear port mode fields for PHY mode*/
+
+ if (is_ehci_hsic_mode(usbhs_pdata->port_mode[0]))
+ setbits_le32(&reg, OMAP_P1_MODE_HSIC);
+
+ if (is_ehci_hsic_mode(usbhs_pdata->port_mode[1]))
+ setbits_le32(&reg, OMAP_P2_MODE_HSIC);
+
+ if (is_ehci_hsic_mode(usbhs_pdata->port_mode[2]))
+ setbits_le32(&reg, OMAP_P3_MODE_HSIC);
+ }
+
+ debug("OMAP UHH_REVISION 0x%x\n", rev);
+ writel(reg, &uhh->hostconfig);
+
+ for (i = 0; i < OMAP_HS_USB_PORTS; i++)
+ if (is_ehci_hsic_mode(usbhs_pdata->port_mode[i]))
+ omap_usbhs_hsic_init(i);
+
+ omap_ehci_phy_reset(0, 10);
+
+ /*
+ * An undocumented "feature" in the OMAP3 EHCI controller,
+ * causes suspended ports to be taken out of suspend when
+ * the USBCMD.Run/Stop bit is cleared (for example when
+ * we do ehci_bus_suspend).
+ * This breaks suspend-resume if the root-hub is allowed
+ * to suspend. Writing 1 to this undocumented register bit
+ * disables this feature and restores normal behavior.
+ */
+ writel(EHCI_INSNREG04_DISABLE_UNSUSPEND, &ehci->insreg04);
+
+ for (i = 0; i < OMAP_HS_USB_PORTS; i++)
+ if (is_ehci_phy_mode(usbhs_pdata->port_mode[i]))
+ omap_ehci_soft_phy_reset(i);
+
+ dcache_disable();
+ hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE);
+ hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10);
+
+ debug("OMAP EHCI init done\n");
+ return 0;
+}
diff --git a/drivers/usb/ulpi/Makefile b/drivers/usb/ulpi/Makefile
index d43b229..281eb1c 100644
--- a/drivers/usb/ulpi/Makefile
+++ b/drivers/usb/ulpi/Makefile
@@ -24,6 +24,7 @@ LIB := $(obj)libusb_ulpi.o
COBJS-$(CONFIG_USB_ULPI) += ulpi.o
COBJS-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi-viewport.o
+COBJS-$(CONFIG_USB_ULPI_VIEWPORT_OMAP) += omap-ulpi-viewport.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/usb/ulpi/omap-ulpi-viewport.c b/drivers/usb/ulpi/omap-ulpi-viewport.c
new file mode 100644
index 0000000..3c1ea1a
--- /dev/null
+++ b/drivers/usb/ulpi/omap-ulpi-viewport.c
@@ -0,0 +1,105 @@
+/*
+ * OMAP ulpi viewport support
+ * Based on drivers/usb/ulpi/ulpi-viewport.c
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Govindraj R <govindraj.raja@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <usb/ulpi.h>
+
+#define OMAP_ULPI_WR_OPSEL (3 << 21)
+#define OMAP_ULPI_ACCESS (1 << 31)
+
+/*
+ * Wait for the ULPI Access to complete
+ */
+static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask)
+{
+ int timeout = CONFIG_USB_ULPI_TIMEOUT;
+
+ while (--timeout) {
+ if ((readl(ulpi_vp->viewport_addr) & mask))
+ return 0;
+
+ udelay(1);
+ }
+
+ return ULPI_ERROR;
+}
+
+/*
+ * Wake the ULPI PHY up for communication
+ *
+ * returns 0 on success.
+ */
+static int ulpi_wakeup(struct ulpi_viewport *ulpi_vp)
+{
+ int err;
+
+ if (readl(ulpi_vp->viewport_addr) & OMAP_ULPI_ACCESS)
+ return 0; /* already awake */
+
+ writel(OMAP_ULPI_ACCESS, ulpi_vp->viewport_addr);
+
+ err = ulpi_wait(ulpi_vp, OMAP_ULPI_ACCESS);
+ if (err)
+ debug("ULPI wakeup timed out\n");
+
+ return err;
+}
+
+/*
+ * Issue a ULPI read/write request
+ */
+static int ulpi_request(struct ulpi_viewport *ulpi_vp, u32 value)
+{
+ int err;
+
+ err = ulpi_wakeup(ulpi_vp);
+ if (err)
+ return err;
+
+ writel(value, ulpi_vp->viewport_addr);
+
+ err = ulpi_wait(ulpi_vp, OMAP_ULPI_ACCESS);
+ if (err)
+ debug("ULPI request timed out\n");
+
+ return err;
+}
+
+int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value)
+{
+ u32 val = ((ulpi_vp->port_num & 0xf) << 24) |
+ OMAP_ULPI_WR_OPSEL | ((u32)reg << 16) | (value & 0xff);
+
+ return ulpi_request(ulpi_vp, val);
+}
+
+u32 ulpi_read(struct ulpi_viewport *ulpi_vp, u8 *reg)
+{
+ int err;
+ u32 val = ((ulpi_vp->port_num & 0xf) << 24) |
+ OMAP_ULPI_WR_OPSEL | ((u32)reg << 16);
+
+ err = ulpi_request(ulpi_vp, val);
+ if (err)
+ return err;
+
+ return readl(ulpi_vp->viewport_addr) & 0xff;
+}
diff --git a/drivers/usb/ulpi/ulpi-viewport.c b/drivers/usb/ulpi/ulpi-viewport.c
index 490fb0e..b4974ed 100644
--- a/drivers/usb/ulpi/ulpi-viewport.c
+++ b/drivers/usb/ulpi/ulpi-viewport.c
@@ -40,13 +40,13 @@
*
* returns 0 on mask match, ULPI_ERROR on time out.
*/
-static int ulpi_wait(u32 ulpi_viewport, u32 mask)
+static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask)
{
int timeout = CONFIG_USB_ULPI_TIMEOUT;
/* Wait for the bits in mask to become zero. */
while (--timeout) {
- if ((readl(ulpi_viewport) & mask) == 0)
+ if ((readl(ulpi_vp->viewport_addr) & mask) == 0)
return 0;
udelay(1);
@@ -60,16 +60,16 @@ static int ulpi_wait(u32 ulpi_viewport, u32 mask)
*
* returns 0 on success.
*/
-static int ulpi_wakeup(u32 ulpi_viewport)
+static int ulpi_wakeup(struct ulpi_viewport *ulpi_vp)
{
int err;
- if (readl(ulpi_viewport) & ULPI_SS)
+ if (readl(ulpi_vp->viewport_addr) & ULPI_SS)
return 0; /* already awake */
- writel(ULPI_WU, ulpi_viewport);
+ writel(ULPI_WU, ulpi_vp->viewport_addr);
- err = ulpi_wait(ulpi_viewport, ULPI_WU);
+ err = ulpi_wait(ulpi_vp, ULPI_WU);
if (err)
printf("ULPI wakeup timed out\n");
@@ -81,38 +81,40 @@ static int ulpi_wakeup(u32 ulpi_viewport)
*
* @value - the ULPI request
*/
-static int ulpi_request(u32 ulpi_viewport, u32 value)
+static int ulpi_request(struct ulpi_viewport *ulpi_vp, u32 value)
{
int err;
- err = ulpi_wakeup(ulpi_viewport);
+ err = ulpi_wakeup(ulpi_vp);
if (err)
return err;
- writel(value, ulpi_viewport);
+ writel(value, ulpi_vp->viewport_addr);
- err = ulpi_wait(ulpi_viewport, ULPI_RWRUN);
+ err = ulpi_wait(ulpi_vp, ULPI_RWRUN);
if (err)
printf("ULPI request timed out\n");
return err;
}
-int ulpi_write(u32 ulpi_viewport, u8 *reg, u32 value)
+int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value)
{
u32 val = ULPI_RWRUN | ULPI_RWCTRL | ((u32)reg << 16) | (value & 0xff);
- return ulpi_request(ulpi_viewport, val);
+ val |= (ulpi_vp->port_num & 0x7) << 24;
+ return ulpi_request(ulpi_vp, val);
}
-u32 ulpi_read(u32 ulpi_viewport, u8 *reg)
+u32 ulpi_read(struct ulpi_viewport *ulpi_vp, u8 *reg)
{
int err;
u32 val = ULPI_RWRUN | ((u32)reg << 16);
- err = ulpi_request(ulpi_viewport, val);
+ val |= (ulpi_vp->port_num & 0x7) << 24;
+ err = ulpi_request(ulpi_vp, val);
if (err)
return err;
- return (readl(ulpi_viewport) >> 8) & 0xff;
+ return (readl(ulpi_vp->viewport_addr) >> 8) & 0xff;
}
diff --git a/drivers/usb/ulpi/ulpi.c b/drivers/usb/ulpi/ulpi.c
index 6202227..dde2585 100644
--- a/drivers/usb/ulpi/ulpi.c
+++ b/drivers/usb/ulpi/ulpi.c
@@ -37,18 +37,18 @@
static struct ulpi_regs *ulpi = (struct ulpi_regs *)0;
-static int ulpi_integrity_check(u32 ulpi_viewport)
+static int ulpi_integrity_check(struct ulpi_viewport *ulpi_vp)
{
u32 val, tval = ULPI_TEST_VALUE;
int err, i;
/* Use the 'special' test value to check all bits */
for (i = 0; i < 2; i++, tval <<= 1) {
- err = ulpi_write(ulpi_viewport, &ulpi->scratch, tval);
+ err = ulpi_write(ulpi_vp, &ulpi->scratch, tval);
if (err)
return err;
- val = ulpi_read(ulpi_viewport, &ulpi->scratch);
+ val = ulpi_read(ulpi_vp, &ulpi->scratch);
if (val != tval) {
printf("ULPI integrity check failed\n");
return val;
@@ -58,7 +58,7 @@ static int ulpi_integrity_check(u32 ulpi_viewport)
return 0;
}
-int ulpi_init(u32 ulpi_viewport)
+int ulpi_init(struct ulpi_viewport *ulpi_vp)
{
u32 val, id = 0;
u8 *reg = &ulpi->product_id_high;
@@ -66,7 +66,7 @@ int ulpi_init(u32 ulpi_viewport)
/* Assemble ID from four ULPI ID registers (8 bits each). */
for (i = 0; i < ULPI_ID_REGS_COUNT; i++) {
- val = ulpi_read(ulpi_viewport, reg - i);
+ val = ulpi_read(ulpi_vp, reg - i);
if (val == ULPI_ERROR)
return val;
@@ -76,10 +76,10 @@ int ulpi_init(u32 ulpi_viewport)
/* Split ID into vendor and product ID. */
debug("ULPI transceiver ID 0x%04x:0x%04x\n", id >> 16, id & 0xffff);
- return ulpi_integrity_check(ulpi_viewport);
+ return ulpi_integrity_check(ulpi_vp);
}
-int ulpi_select_transceiver(u32 ulpi_viewport, unsigned speed)
+int ulpi_select_transceiver(struct ulpi_viewport *ulpi_vp, unsigned speed)
{
u32 tspeed = ULPI_FC_FULL_SPEED;
u32 val;
@@ -96,17 +96,18 @@ int ulpi_select_transceiver(u32 ulpi_viewport, unsigned speed)
"falling back to full speed\n", __func__, speed);
}
- val = ulpi_read(ulpi_viewport, &ulpi->function_ctrl);
+ val = ulpi_read(ulpi_vp, &ulpi->function_ctrl);
if (val == ULPI_ERROR)
return val;
/* clear the previous speed setting */
val = (val & ~ULPI_FC_XCVRSEL_MASK) | tspeed;
- return ulpi_write(ulpi_viewport, &ulpi->function_ctrl, val);
+ return ulpi_write(ulpi_vp, &ulpi->function_ctrl, val);
}
-int ulpi_set_vbus(u32 ulpi_viewport, int on, int ext_power, int ext_ind)
+int ulpi_set_vbus(struct ulpi_viewport *ulpi_vp, int on, int ext_power,
+ int ext_ind)
{
u32 flags = ULPI_OTG_DRVVBUS;
u8 *reg = on ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear;
@@ -116,18 +117,18 @@ int ulpi_set_vbus(u32 ulpi_viewport, int on, int ext_power, int ext_ind)
if (ext_ind)
flags |= ULPI_OTG_EXTVBUSIND;
- return ulpi_write(ulpi_viewport, reg, flags);
+ return ulpi_write(ulpi_vp, reg, flags);
}
-int ulpi_set_pd(u32 ulpi_viewport, int enable)
+int ulpi_set_pd(struct ulpi_viewport *ulpi_vp, int enable)
{
u32 val = ULPI_OTG_DP_PULLDOWN | ULPI_OTG_DM_PULLDOWN;
u8 *reg = enable ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear;
- return ulpi_write(ulpi_viewport, reg, val);
+ return ulpi_write(ulpi_vp, reg, val);
}
-int ulpi_opmode_sel(u32 ulpi_viewport, unsigned opmode)
+int ulpi_opmode_sel(struct ulpi_viewport *ulpi_vp, unsigned opmode)
{
u32 topmode = ULPI_FC_OPMODE_NORMAL;
u32 val;
@@ -144,17 +145,17 @@ int ulpi_opmode_sel(u32 ulpi_viewport, unsigned opmode)
"falling back to OpMode Normal\n", __func__, opmode);
}
- val = ulpi_read(ulpi_viewport, &ulpi->function_ctrl);
+ val = ulpi_read(ulpi_vp, &ulpi->function_ctrl);
if (val == ULPI_ERROR)
return val;
/* clear the previous opmode setting */
val = (val & ~ULPI_FC_OPMODE_MASK) | topmode;
- return ulpi_write(ulpi_viewport, &ulpi->function_ctrl, val);
+ return ulpi_write(ulpi_vp, &ulpi->function_ctrl, val);
}
-int ulpi_serial_mode_enable(u32 ulpi_viewport, unsigned smode)
+int ulpi_serial_mode_enable(struct ulpi_viewport *ulpi_vp, unsigned smode)
{
switch (smode) {
case ULPI_IFACE_6_PIN_SERIAL_MODE:
@@ -166,14 +167,14 @@ int ulpi_serial_mode_enable(u32 ulpi_viewport, unsigned smode)
return ULPI_ERROR;
}
- return ulpi_write(ulpi_viewport, &ulpi->iface_ctrl_set, smode);
+ return ulpi_write(ulpi_vp, &ulpi->iface_ctrl_set, smode);
}
-int ulpi_suspend(u32 ulpi_viewport)
+int ulpi_suspend(struct ulpi_viewport *ulpi_vp)
{
int err;
- err = ulpi_write(ulpi_viewport, &ulpi->function_ctrl_clear,
+ err = ulpi_write(ulpi_vp, &ulpi->function_ctrl_clear,
ULPI_FC_SUSPENDM);
if (err)
printf("ULPI: %s: failed writing the suspend bit\n", __func__);
@@ -186,7 +187,7 @@ int ulpi_suspend(u32 ulpi_viewport)
* Actual wait for reset must be done in a view port specific way,
* because it involves checking the DIR line.
*/
-static int __ulpi_reset_wait(u32 ulpi_viewport)
+static int __ulpi_reset_wait(struct ulpi_viewport *ulpi_vp)
{
u32 val;
int timeout = CONFIG_USB_ULPI_TIMEOUT;
@@ -199,7 +200,7 @@ static int __ulpi_reset_wait(u32 ulpi_viewport)
* for the error of ulpi_read(), if there is one, then
* there will be a timeout.
*/
- val = ulpi_read(ulpi_viewport, &ulpi->function_ctrl);
+ val = ulpi_read(ulpi_vp, &ulpi->function_ctrl);
if (!(val & ULPI_FC_RESET))
return 0;
@@ -210,18 +211,19 @@ static int __ulpi_reset_wait(u32 ulpi_viewport)
return ULPI_ERROR;
}
-int ulpi_reset_wait(u32) __attribute__((weak, alias("__ulpi_reset_wait")));
+int ulpi_reset_wait(struct ulpi_viewport *ulpi_vp)
+ __attribute__((weak, alias("__ulpi_reset_wait")));
-int ulpi_reset(u32 ulpi_viewport)
+int ulpi_reset(struct ulpi_viewport *ulpi_vp)
{
int err;
- err = ulpi_write(ulpi_viewport,
+ err = ulpi_write(ulpi_vp,
&ulpi->function_ctrl_set, ULPI_FC_RESET);
if (err) {
printf("ULPI: %s: failed writing reset bit\n", __func__);
return err;
}
- return ulpi_reset_wait(ulpi_viewport);
+ return ulpi_reset_wait(ulpi_vp);
}