diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/mxcmmc.c | 8 | ||||
-rw-r--r-- | drivers/mmc/tegra2_mmc.c | 16 | ||||
-rw-r--r-- | drivers/spi/kirkwood_spi.c | 2 | ||||
-rw-r--r-- | drivers/spi/mxs_spi.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/Makefile | 3 | ||||
-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.c | 255 | ||||
-rw-r--r-- | drivers/usb/ulpi/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/ulpi/omap-ulpi-viewport.c | 105 | ||||
-rw-r--r-- | drivers/usb/ulpi/ulpi-viewport.c | 32 | ||||
-rw-r--r-- | drivers/usb/ulpi/ulpi.c | 54 |
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(®, (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(®, 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(®, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS); + else + setbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS); + + if (is_ehci_phy_mode(usbhs_pdata->port_mode[1])) + clrbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS); + else + setbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS); + + if (is_ehci_phy_mode(usbhs_pdata->port_mode[2])) + clrbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS); + else + setbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS); + } else if (rev == OMAP_USBHS_REV2) { + clrsetbits_le32(®, (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(®, OMAP_P1_MODE_HSIC); + + if (is_ehci_hsic_mode(usbhs_pdata->port_mode[1])) + setbits_le32(®, OMAP_P2_MODE_HSIC); + + if (is_ehci_hsic_mode(usbhs_pdata->port_mode[2])) + setbits_le32(®, 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); } |