diff options
Diffstat (limited to 'target/linux/coldfire/patches/040-Add-USB-support-for-MCF5445x-and-MCF54418.patch')
-rw-r--r-- | target/linux/coldfire/patches/040-Add-USB-support-for-MCF5445x-and-MCF54418.patch | 7007 |
1 files changed, 0 insertions, 7007 deletions
diff --git a/target/linux/coldfire/patches/040-Add-USB-support-for-MCF5445x-and-MCF54418.patch b/target/linux/coldfire/patches/040-Add-USB-support-for-MCF5445x-and-MCF54418.patch deleted file mode 100644 index 98984be2ff..0000000000 --- a/target/linux/coldfire/patches/040-Add-USB-support-for-MCF5445x-and-MCF54418.patch +++ /dev/null @@ -1,7007 +0,0 @@ -From 632dc9e46a9ff032138f81fd420c0f01fd6c3cbc Mon Sep 17 00:00:00 2001 -From: Jason Jin <Jason.jin@freescale.com> -Date: Thu, 4 Aug 2011 14:21:29 +0800 -Subject: [PATCH 40/52] Add USB support for MCF5445x and MCF54418 - -The OTG module function with external ULPI of USB3300 -on M5445xEVB and Modelo TWR-SER2, while the Max3353 charge -pump on Modelo TWR-SER1 with version-B CPU board only -function FS/LS tranceiver. -It also support USB host module on Modelo TWR-SER2. -And the host mode on M54455EVB with FS/LS only tranceiver -is supported by p4 interface on the board. - -Signed-off-by: Jingchang Lu <b35083@freescale.com> ---- - arch/m68k/Kconfig | 2 + - arch/m68k/coldfire/m5441x/Makefile | 4 +- - arch/m68k/coldfire/m5441x/max3353.h | 96 +++ - arch/m68k/coldfire/m5441x/max3353_otg.c | 508 +++++++++++++ - arch/m68k/coldfire/m5441x/max3353_xc.c | 310 ++++++++ - arch/m68k/coldfire/m5441x/usb.c | 276 +++++++ - arch/m68k/coldfire/m5441x/usb.h | 76 ++ - arch/m68k/coldfire/m5441x/usb_dr.c | 179 +++++ - arch/m68k/coldfire/m5441x/usb_host.c | 115 +++ - arch/m68k/coldfire/m5441x/xcvr.c | 198 +++++ - arch/m68k/coldfire/m5441x/xcvr_host.c | 53 ++ - arch/m68k/coldfire/m5445x/usb.c | 220 ++++++ - arch/m68k/coldfire/m5445x/usb.h | 107 +++ - arch/m68k/coldfire/m5445x/usb_dr.c | 152 ++++ - arch/m68k/coldfire/m5445x/xcvr.c | 127 ++++ - arch/m68k/include/asm/fsl_usb_gadget.h | 45 ++ - arch/m68k/include/asm/fsl_usb_io.h | 43 ++ - arch/m68k/include/asm/fsl_usb_platform.h | 78 ++ - drivers/Makefile | 1 + - drivers/usb/Kconfig | 2 + - drivers/usb/core/Kconfig | 2 +- - drivers/usb/gadget/Kconfig | 2 +- - drivers/usb/gadget/fsl_udc_core.c | 360 ++++++++- - drivers/usb/gadget/fsl_usb2_udc.h | 16 + - drivers/usb/gadget/serial.c | 40 +- - drivers/usb/host/Kconfig | 72 ++- - drivers/usb/host/ehci-fsl.c | 257 ++++++- - drivers/usb/host/ehci-fsl.h | 7 + - drivers/usb/host/ehci-hub.c | 34 + - drivers/usb/host/ehci.h | 55 ++- - drivers/usb/otg/Makefile | 7 + - drivers/usb/otg/fsl_otg.c | 1212 ++++++++++++++++++++++++++++++ - drivers/usb/otg/fsl_otg.h | 423 +++++++++++ - drivers/usb/otg/otg_fsm.c | 371 +++++++++ - drivers/usb/otg/otg_fsm.h | 151 ++++ - drivers/usb/otg/usb.c | 76 ++ - include/linux/fsl_devices.h | 26 + - include/linux/usb/fsl_usb2.h | 410 ++++++++++ - include/linux/usb/fsl_xcvr.h | 36 + - include/linux/usb/otg.h | 2 +- - 40 files changed, 6087 insertions(+), 64 deletions(-) - create mode 100644 arch/m68k/coldfire/m5441x/max3353.h - create mode 100644 arch/m68k/coldfire/m5441x/max3353_otg.c - create mode 100644 arch/m68k/coldfire/m5441x/max3353_xc.c - create mode 100644 arch/m68k/coldfire/m5441x/usb.c - create mode 100644 arch/m68k/coldfire/m5441x/usb.h - create mode 100644 arch/m68k/coldfire/m5441x/usb_dr.c - create mode 100644 arch/m68k/coldfire/m5441x/usb_host.c - create mode 100644 arch/m68k/coldfire/m5441x/xcvr.c - create mode 100644 arch/m68k/coldfire/m5441x/xcvr_host.c - create mode 100644 arch/m68k/coldfire/m5445x/usb.c - create mode 100644 arch/m68k/coldfire/m5445x/usb.h - create mode 100644 arch/m68k/coldfire/m5445x/usb_dr.c - create mode 100644 arch/m68k/coldfire/m5445x/xcvr.c - create mode 100644 arch/m68k/include/asm/fsl_usb_gadget.h - create mode 100644 arch/m68k/include/asm/fsl_usb_io.h - create mode 100644 arch/m68k/include/asm/fsl_usb_platform.h - create mode 100644 drivers/usb/otg/fsl_otg.c - create mode 100644 drivers/usb/otg/fsl_otg.h - create mode 100644 drivers/usb/otg/otg_fsm.c - create mode 100644 drivers/usb/otg/otg_fsm.h - create mode 100644 drivers/usb/otg/usb.c - create mode 100644 include/linux/usb/fsl_usb2.h - create mode 100644 include/linux/usb/fsl_xcvr.h - ---- a/arch/m68k/Kconfig -+++ b/arch/m68k/Kconfig -@@ -327,6 +327,7 @@ config M5445X - bool "MCF5445x support" - depends on COLDFIRE - select GENERIC_TIME -+ select USB_ARCH_HAS_EHCI - select USB_EHCI_FSL - select HAVE_FSL_USB_DR - help -@@ -430,6 +431,7 @@ config M5441X - depends on COLDFIRE - select GENERIC_TIME - select USB_EHCI_FSL -+ select USB_ARCH_HAS_EHCI - select HAVE_FSL_USB_DR - select HAVE_CAN_FLEXCAN - help ---- a/arch/m68k/coldfire/m5441x/Makefile -+++ b/arch/m68k/coldfire/m5441x/Makefile -@@ -14,9 +14,11 @@ endif - endif - - #ifneq ($(strip $(CONFIG_USB) $(CONFIG_USB_GADGET_FSL_USB2)),) --ifneq ($(strip $(CONFIG_USB_OTG) $(CONFIG_USB_M5441X_MAX3353_FSLS)),) -+ifneq ($(strip $(CONFIG_USB_OTG)),) -+ifeq ($(strip $(CONFIG_USB_M5441X_MAX3353_FSLS)),) - obj-y += xcvr.o - endif -+endif - ifneq ($(strip $(CONFIG_USB_M5441X_MAX3353_FSLS)), ) - obj-y += max3353_xc.o - ifneq ($(strip $(CONFIG_USB_OTG)),) ---- /dev/null -+++ b/arch/m68k/coldfire/m5441x/max3353.h -@@ -0,0 +1,96 @@ -+/* -+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef _MAX3353_H_ -+#define _MAX3353_H_ -+/* registers */ -+ -+/* Manufacturer registers */ -+#define MAX3353_MAN0 0x00 -+#define MAX3353_MAN1 0x01 -+#define MAX3353_MAN2 0x02 -+#define MAX3353_MAN3 0x03 -+ -+/* Product ID registers */ -+#define MAX3353_PID0 0x04 -+#define MAX3353_PID1 0x05 -+#define MAX3353_PID2 0x06 -+#define MAX3353_PID3 0x07 -+ -+/* Control register 1 */ -+#define MAX3353_CR1 0x10 -+#define CR1_DM_PULLDOWN (1 << 7) -+#define CR1_DP_PULLDOWN (1 << 6) -+#define CR1_DM_PULLUP (1 << 5) -+#define CR1_DP_PULLUP (1 << 4) -+#define CR1_BDISC_ACONN (1 << 2) -+#define CR1_IRQ_PUSH_PULL (1 << 1) -+ -+/* Control register 2 */ -+#define MAX3353_CR2 0x11 -+#define CR2_VBUS_DISCHRG (1 << 4) -+#define CR2_VBUS_DRV (1 << 3) -+#define CR2_VBUS_CHG2 (1 << 2) -+#define CR2_VBUS_CHG1 (1 << 1) -+#define CR2_SHUTDOWN (1 << 0) -+ -+/* Status register */ -+#define MAX3353_STATUS 0x13 -+#define STATUS_B_HNP (1 << 6) -+#define STATUS_A_HNP (1 << 5) -+#define STATUS_ID_FLOAT (1 << 4) -+#define STATUS_ID_GND (1 << 3) -+#define STATUS_SESSION_END (1 << 2) -+#define STATUS_SESSION_VALID (1 << 1) -+#define STATUS_VBUS_VALID (1 << 0) -+ -+/* Interrupt mask register */ -+#define MAX3353_INTR_MASK 0x14 -+#define IM_A_HNP_EN (1 << 5) -+#define IM_ID_FLOAT_EN (1 << 4) -+#define IM_ID_GND_EN (1 << 3) -+#define IM_SESSION_END_EN (1 << 2) -+#define IM_SESSION_VLD_EN (1 << 1) -+#define IM_VBUS_VLD_EN (1 << 0) -+ -+/* Interrupt edge register */ -+#define MAX3353_INTR_EDGE 0x15 -+#define IE_SESSION_VALID_ED (1 << 1) -+#define IE_VBUS_VLD_ED (1 << 0) -+ -+/* Interrupt latch register (read-only) */ -+#define MAX3353_INTR_LATCH 0x16 -+#define IL_A_HNP_RQ (1 << 7) -+#define IL_ID_FLOAT_RQ (1 << 6) -+#define IL_ID_GND_RQ (1 << 5) -+#define IL_SESSION_END_RQ (1 << 4) -+#define IL_SESSION_VALID_RN (1 << 3) -+#define IL_VBUS_VALID_RN (1 << 2) -+#define IL_SESSION_VALID_RP (1 << 1) -+#define IL_VBUS_VALID_RP (1 << 0) -+ -+ -+#define MAX3353_DEV_ADDR 0x2c -+#define MAX3353_IRQ (64 + 4) /* IRQ4 */ -+ -+extern u8 max3353_read_reg(u8 reg); -+extern void max3353_write_reg(u8 reg, u8 data); -+extern int max3353_read_id_pin(void); -+extern int otg_set_resources(struct resource *resources); -+ -+#endif /* _MAX3353_H_ */ ---- /dev/null -+++ b/arch/m68k/coldfire/m5441x/max3353_otg.c -@@ -0,0 +1,508 @@ -+/* -+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/err.h> -+#include <linux/errno.h> -+#include <linux/init.h> -+#include <linux/io.h> -+#include <linux/moduleparam.h> -+#include <linux/delay.h> -+#include <linux/sched.h> -+#include <linux/usb.h> -+#include <linux/usb/gadget.h> -+#include <linux/usb/otg.h> -+#include <linux/workqueue.h> -+#include <linux/time.h> -+#include <linux/platform_device.h> -+#include <linux/fsl_devices.h> -+#include <linux/usb/fsl_usb2.h> -+#include <linux/usb/otg.h> -+ -+#include <asm/fsl_usb_io.h> -+#include "max3353.h" -+ -+#define DRIVER_VERSION "1.0" -+#define DRIVER_AUTHOR "Freescale Semiconductor Inc." -+#define DRIVER_DESC "Freescale MAX3353 USBOTG Driver" -+#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC -+ -+MODULE_DESCRIPTION("Freescale MAX3353 USBOTG Driver"); -+ -+#if 0 -+#undef pr_debug -+#define pr_debug(x...) printk(x) -+#endif -+ -+static const char driver_name[] = "max3353-otg"; -+ -+const pm_message_t otg_suspend_state = { -+ .event = 1, -+}; -+ -+static volatile struct fsl_usb_device_regs *usb_dr_regs; -+ -+struct otg_fsm { -+ int id; /* 0=host 1=gadget */ -+ struct otg_fsm_ops *ops; -+ struct otg_transceiver *transceiver; -+}; -+ -+struct otg_fsm_ops { -+ int (*start_host)(struct otg_fsm *fsm, int on); -+ int (*start_gadget)(struct otg_fsm *fsm, int on); -+}; -+ -+struct max_otg { -+ struct otg_transceiver otg; -+ struct otg_fsm fsm; -+ struct delayed_work otg_event; -+ struct work_struct work_wq; -+ u8 host_working; -+ int irq; -+}; -+ -+static struct max_otg *max_otg_dev; -+ -+#define SET_OTG_STATE(otg_ptr, newstate) ((otg_ptr)->state = newstate) -+ -+ -+/* Reset controller, not reset the bus */ -+void otg_reset_controller(void) -+{ -+ u32 command; -+ -+ command = fsl_readl(&usb_dr_regs->usbcmd); -+ command |= (1 << 1); -+ fsl_writel(command, &usb_dr_regs->usbcmd); -+ while (fsl_readl(&usb_dr_regs->usbcmd) & (1 << 1)) -+ ; -+} -+ -+ -+/* Call suspend/resume routines in host driver */ -+static int maxotg_start_host(struct otg_fsm *fsm, int on) -+{ -+ struct otg_transceiver *xceiv = fsm->transceiver; -+ struct device *dev; -+ struct max_otg *otg_dev = container_of(xceiv, struct max_otg, otg); -+ u32 retval = 0; -+ -+ pr_debug("%s: host %s\n", __func__, on ? "on" : "off"); -+ -+ if (!xceiv->host) -+ return -ENODEV; -+ dev = xceiv->host->controller; -+ -+ if (on) { -+ /* start fsl usb host controller */ -+ if (otg_dev->host_working) -+ goto end; -+ else { -+ otg_reset_controller(); -+ pr_debug("host on......\n"); -+ if (dev->driver->resume) -+ retval = dev->driver->resume(dev); -+ -+ otg_dev->host_working = 1; -+ } -+ } else { -+ /* stop fsl usb host controller */ -+ if (!otg_dev->host_working) -+ goto end; -+ else { -+ pr_debug("host off......\n"); -+ if (dev && dev->driver) -+ retval = dev->driver->suspend(dev, -+ otg_suspend_state); -+ otg_dev->host_working = 0; -+ } -+ } -+end: -+ return retval; -+} -+ -+/* Call suspend and resume function in udc driver -+ * to stop and start udc driver. -+ */ -+static int maxotg_start_gadget(struct otg_fsm *fsm, int on) -+{ -+ struct otg_transceiver *xceiv = fsm->transceiver; -+ struct device *dev; -+ -+ pr_debug("%s: gadget %s\n", __func__, on ? "on" : "off"); -+ -+ if (!xceiv->gadget || !xceiv->gadget->dev.parent) -+ return -ENODEV; -+ -+ dev = xceiv->gadget->dev.parent; -+ -+ if (on) -+ dev->driver->resume(dev); -+ else -+ dev->driver->suspend(dev, otg_suspend_state); -+ -+ return 0; -+} -+ -+ -+/* delayed interrupt handler */ -+static void handle_irq(struct work_struct *work) -+{ -+ u8 latch; -+ int id_host; -+ struct otg_fsm *fsm = &max_otg_dev->fsm; -+ struct otg_transceiver *otg = &max_otg_dev->otg; -+ -+ if (max_otg_dev == NULL) -+ return; -+ -+ latch = max3353_read_reg(MAX3353_INTR_LATCH); -+ -+ if (latch) { -+ id_host = max3353_read_id_pin(); -+ fsm->id = !id_host; -+ pr_debug("\t\t\t%s host mode %s\n", __func__, -+ id_host ? "ON" : "OFF"); -+ -+ if (otg->host) -+ otg->host->is_b_host = fsm->id; -+ if (otg->gadget) -+ otg->gadget->is_a_peripheral = !fsm->id; -+ -+ if (fsm->id) { /* switch to gadget */ -+ schedule_delayed_work(&max_otg_dev->otg_event, 100); -+ } else { /* switch to host */ -+ cancel_delayed_work(&max_otg_dev->otg_event); -+ maxotg_start_gadget(fsm, 0); -+ maxotg_start_host(fsm, 1); -+ } -+ } -+ enable_irq(MAX3353_IRQ); -+} -+ -+DECLARE_DELAYED_WORK(max3353_dwq, handle_irq); -+ -+/* -+ * MAX3353 interrupt handler -+ * -+ * We're interested in ID pin changes. Since we can't do i2c -+ * operations from interrupt context, we use a delayed workqueue -+ * routine to clear the interrupt in the MAX3353, and to handle -+ * the role switching. The delay also allows for debouncing the -+ * state of the ID pin. To avoid the flood of interrupts between -+ * the irq and its processing, we disable the irq here, and re-enable -+ * it in the delayed routine. -+ */ -+irqreturn_t max3353_isr(int irq, void *dev_id) -+{ -+ disable_irq(MAX3353_IRQ); -+ schedule_delayed_work(&max3353_dwq, 25); -+ -+ return IRQ_HANDLED; -+} -+ -+ -+/* Called by initialization code of host driver. Register host controller -+ * to the OTG. Suspend host for OTG role detection. -+ */ -+static int set_host(struct otg_transceiver *otg_p, struct usb_bus *host) -+{ -+ struct max_otg *otg_dev = container_of(otg_p, struct max_otg, otg); -+ -+ pr_debug("%s() host %p\n", __func__, host); -+ -+ if (!otg_p || otg_dev != max_otg_dev) -+ return -ENODEV; -+ -+ otg_p->host = host; -+ if (host) { -+ pr_debug("host off......\n"); -+ -+ /* must leave time for khubd to finish its thing -+ * before yanking the host driver out from under it, -+ * so suspend the host after a short delay. -+ */ -+ otg_dev->host_working = 1; -+ schedule_delayed_work(&otg_dev->otg_event, 100); -+ return 0; -+ } else { /* host driver going away */ -+ if (max3353_read_id_pin()) { -+ /* Mini-A cable connected */ -+ otg_p->state = OTG_STATE_UNDEFINED; -+ } -+ } -+ -+ otg_dev->host_working = 0; -+ -+ return 0; -+} -+ -+/* Called by initialization code of udc. Register udc to OTG.*/ -+static int set_peripheral(struct otg_transceiver *otg_p, -+ struct usb_gadget *gadget) -+{ -+ struct max_otg *otg_dev = container_of(otg_p, struct max_otg, otg); -+ -+ pr_debug("%s gadget %p\n", __func__, gadget); -+ -+ pr_debug("otg_dev 0x%x\n", (int)otg_dev); -+ pr_debug("max_otg_dev 0x%x\n", (int)max_otg_dev); -+ -+ if (!otg_p || otg_dev != max_otg_dev) -+ return -ENODEV; -+ -+ if (!gadget) { -+ if (!otg_dev->otg.default_a) -+ otg_p->gadget->ops->vbus_draw(otg_p->gadget, 0); -+ usb_gadget_vbus_disconnect(otg_dev->otg.gadget); -+ otg_dev->otg.gadget = 0; -+ return 0; -+ } -+ -+ otg_p->gadget = gadget; -+ otg_p->gadget->is_a_peripheral = !otg_dev->fsm.id; -+ -+ /* start the gadget right away if the ID pin says Mini-B */ -+ pr_debug("ID pin=%d\n", otg_dev->fsm.id); -+ if (otg_dev->fsm.id == 1) { -+ maxotg_start_host(&otg_dev->fsm, 0); -+ maxotg_start_gadget(&otg_dev->fsm, 1); -+ } -+ -+ return 0; -+} -+ -+/* Set OTG port power, only for B-device */ -+static int set_power(struct otg_transceiver *otg_p, unsigned mA) -+{ -+ return 0; -+} -+ -+/* Delayed pin detect interrupt processing. -+ * -+ * When the Mini-A cable is disconnected from the board, -+ * the pin-detect interrupt happens before the disconnnect -+ * interrupts for the connected device(s). In order to -+ * process the disconnect interrupt(s) prior to switching -+ * roles, the pin-detect interrupts are delayed, and handled -+ * by this routine. -+ */ -+static void maxotg_event(struct work_struct *work) -+{ -+ struct max_otg *og = container_of(work, struct max_otg, otg_event.work); -+ struct otg_fsm *fsm = &og->fsm; -+ -+ if (fsm->id) { /* switch to gadget */ -+ maxotg_start_host(fsm, 0); -+ maxotg_start_gadget(fsm, 1); -+ } -+} -+ -+ -+static struct otg_fsm_ops maxotg_ops = { -+ .start_host = maxotg_start_host, -+ .start_gadget = maxotg_start_gadget, -+}; -+ -+ -+/* Initialize the global variable max_otg_dev and request IRQ for OTG */ -+static int maxotg_conf(struct platform_device *pdev) -+{ -+ int status; -+ struct max_otg *max_otg_tc; -+ struct fsl_usb2_platform_data *pdata; -+ -+ pdata = pdev->dev.platform_data; -+ -+ pr_debug("%s\n", __func__); -+ -+ if (max_otg_dev) -+ return 0; -+ -+ /* allocate space to fsl otg device */ -+ max_otg_tc = kzalloc(sizeof(struct max_otg), GFP_KERNEL); -+ if (!max_otg_tc) -+ return -ENODEV; -+ -+ INIT_DELAYED_WORK(&max_otg_tc->otg_event, maxotg_event); -+ -+ /* Set OTG state machine operations */ -+ max_otg_tc->fsm.ops = &maxotg_ops; -+ -+ /* initialize the otg structure */ -+ max_otg_tc->otg.label = DRIVER_DESC; -+ max_otg_tc->otg.set_host = set_host; -+ max_otg_tc->otg.set_peripheral = set_peripheral; -+ max_otg_tc->otg.set_power = set_power; -+ -+ max_otg_dev = max_otg_tc; -+ pr_debug("%s: set max_otg_dev %p, fsm %p\n", __func__, -+ max_otg_dev, &max_otg_dev->fsm); -+ -+ /* Store the otg transceiver */ -+ status = otg_set_transceiver(&max_otg_tc->otg); -+ if (status) { -+ printk(KERN_WARNING ": unable to register OTG transceiver.\n"); -+ return status; -+ } -+ -+ return 0; -+} -+ -+/* OTG Initialization*/ -+static int maxotg_start(struct platform_device *pdev) -+{ -+ struct max_otg *p_otg; -+ struct otg_transceiver *otg_trans = otg_get_transceiver(); -+ struct otg_fsm *fsm; -+ int status; -+ struct resource *res; -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ -+ p_otg = container_of(otg_trans, struct max_otg, otg); -+ fsm = &p_otg->fsm; -+ -+ /* Initialize the state machine structure with default values */ -+ SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED); -+ fsm->transceiver = &p_otg->otg; -+ -+ /* We don't require predefined MEM/IRQ resource index */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) -+ return -ENXIO; -+ -+ /* -+ * We don't request_mem_region here to enable resource sharing -+ * with host/device -+ */ -+ usb_dr_regs = ioremap(res->start, sizeof(struct fsl_usb_device_regs)); -+ pdata->regs = (void *)usb_dr_regs; -+ pr_debug("ioremap %x to %p\n", res->start, pdata->regs); -+ -+ if (pdata->init && pdata->init(pdev) != 0) -+ return -EINVAL; -+ -+ /* grab the irq */ -+ status = request_irq(MAX3353_IRQ, max3353_isr, IRQF_DISABLED, -+ driver_name, p_otg); -+ if (status) { -+ printk(KERN_ERR "max3353: can't get IRQ, rc %d\n", status); -+ return -EINVAL; -+ } -+ -+ /* enable interrupts on the part */ -+ pr_debug("%s: enabling MAX3353 interrupts\n", __func__); -+ max3353_write_reg(MAX3353_INTR_MASK, IM_ID_GND_EN | IM_ID_FLOAT_EN); -+ -+ /* Export DR controller resources */ -+ otg_set_resources(pdev->resource); -+ -+ /* record initial state of ID pin */ -+ p_otg->fsm.id = !max3353_read_id_pin(); -+ if (p_otg->fsm.id) -+ p_otg->otg.state = OTG_STATE_UNDEFINED; -+ else -+ p_otg->otg.state = OTG_STATE_A_IDLE; -+ -+ pr_debug("initial ID pin: fsm.id=%d (%s)\n", p_otg->fsm.id, -+ p_otg->fsm.id ? "gadget" : "host"); -+ -+ return 0; -+} -+ -+static int __init maxotg_probe(struct platform_device *pdev) -+{ -+ int status; -+ struct fsl_usb2_platform_data *pdata; -+ -+ pr_debug("%s: pdev=0x%p\n", __func__, pdev); -+ -+ if (!pdev) -+ return -ENODEV; -+ -+ if (!pdev->dev.platform_data) -+ return -ENOMEM; -+ -+ pdata = pdev->dev.platform_data; -+ fsl_set_usb_accessors(pdata); -+ -+ /* configure the OTG */ -+ status = maxotg_conf(pdev); -+ if (status) { -+ printk(KERN_INFO "Couldn't init OTG module\n"); -+ return -status; -+ } -+ -+ /* start OTG */ -+ status = maxotg_start(pdev); -+ -+ return status; -+} -+ -+static int __exit maxotg_remove(struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ -+ /* disable max3353 interrupts */ -+ max3353_write_reg(MAX3353_INTR_MASK, 0); -+ -+ otg_set_transceiver(NULL); -+ free_irq(MAX3353_IRQ, max_otg_dev); -+ -+ iounmap((void *)usb_dr_regs); -+ -+ kfree(max_otg_dev); -+ max_otg_dev = NULL; -+ -+ if (pdata->exit) -+ pdata->exit(pdev); -+ -+ return 0; -+} -+ -+struct platform_driver max3353_otg_driver = { -+ .probe = maxotg_probe, -+ .remove = __exit_p(maxotg_remove), -+ .driver = { -+ .name = driver_name, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+ -+static int __init maxotg_init(void) -+{ -+ printk(KERN_INFO DRIVER_DESC " loaded, %s\n", DRIVER_VERSION); -+ return platform_driver_register(&max3353_otg_driver); -+} -+ -+static void __exit maxotg_exit(void) -+{ -+ platform_driver_unregister(&max3353_otg_driver); -+ printk(KERN_INFO DRIVER_DESC " unloaded\n"); -+} -+ -+module_init(maxotg_init); -+module_exit(maxotg_exit); -+ -+MODULE_DESCRIPTION(DRIVER_INFO); -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/arch/m68k/coldfire/m5441x/max3353_xc.c -@@ -0,0 +1,310 @@ -+/* -+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+#define DEBUG -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/init.h> -+#include <linux/slab.h> -+#include <linux/io.h> -+#include <linux/i2c.h> -+#include <linux/usb/fsl_xcvr.h> -+#include <asm/mcfsim.h> -+#include "max3353.h" -+ -+#define DRIVER_DESC "Freescale MAX3353 Driver" -+ -+static struct i2c_device_id max3353_id[] = { -+ {"max3353", 0}, -+ {} -+}; -+MODULE_DEVICE_TABLE(i2c, max3353_id); -+ -+struct max3353_state { -+ struct i2c_client *client; -+}; -+ -+static int max3353_probe(struct i2c_client *client, -+ const struct i2c_device_id *id); -+static int __devexit max3353_remove(struct i2c_client *client); -+ -+static struct i2c_driver max3353_i2c_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "max3353", -+ }, -+ .probe = max3353_probe, -+ .remove = __devexit_p(max3353_remove), -+ .id_table = max3353_id, -+}; -+ -+static struct i2c_client *max3353_i2c_client; -+ -+/* Write a max3353 register*/ -+void max3353_write_reg(u8 reg, u8 data) -+{ -+ i2c_smbus_write_byte_data(max3353_i2c_client, reg, data); -+} -+EXPORT_SYMBOL(max3353_write_reg); -+ -+/* Read a max3353 register*/ -+u8 max3353_read_reg(u8 reg) -+{ -+ return i2c_smbus_read_byte_data(max3353_i2c_client, reg); -+} -+EXPORT_SYMBOL(max3353_read_reg); -+ -+/* -+ * max3353 I2C probe function -+ */ -+ -+static int max3353_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct max3353_state *state; -+ struct device *dev = &client->dev; -+ -+ state = kzalloc(sizeof(struct max3353_state), GFP_KERNEL); -+ if (state == NULL) { -+ dev_err(dev, "failed to create our state\n"); -+ return -ENOMEM; -+ } -+ -+ state->client = client; -+ i2c_set_clientdata(client, state); -+ -+ max3353_i2c_client = client; -+ -+ /* rest of the initialisation goes here. */ -+ printk(KERN_INFO "MAX3353 USB charge pump detected\n"); -+ pr_debug("MANUF:%02x %02x %02x %02x PID:%02x %02x %02x %02x\n", -+ max3353_read_reg(MAX3353_MAN0), -+ max3353_read_reg(MAX3353_MAN1), -+ max3353_read_reg(MAX3353_MAN2), -+ max3353_read_reg(MAX3353_MAN3), -+ max3353_read_reg(MAX3353_PID0), -+ max3353_read_reg(MAX3353_PID1), -+ max3353_read_reg(MAX3353_PID2), -+ max3353_read_reg(MAX3353_PID3)); -+ pr_debug("%s done\n", __func__); -+ -+ return 0; -+ -+} -+ -+/* -+ * max3353 I2C remove function -+ */ -+static int __devexit max3353_remove(struct i2c_client *client) -+{ -+ struct max3353_state *state = i2c_get_clientdata(client); -+ -+ max3353_i2c_client = NULL; -+ -+ kfree(state); -+ return 0; -+} -+ -+static int max3353_running; -+ -+static void max3353_init(struct fsl_xcvr_ops *this) -+{ -+ int __maybe_unused rc; -+ u8 tmp; -+ -+ pr_debug("%s\n", __func__); -+ -+ if (!max3353_running) { -+ i2c_add_driver(&max3353_i2c_driver); -+ -+ /* disable interrupts on the part */ -+ max3353_write_reg(MAX3353_INTR_MASK, 0); -+ -+ /* configure irq mode */ -+ tmp = max3353_read_reg(MAX3353_CR1); -+ tmp |= CR1_IRQ_PUSH_PULL; -+ max3353_write_reg(MAX3353_CR1, tmp); -+ -+ /* take the part out of shutdown */ -+ tmp = max3353_read_reg(MAX3353_CR2); -+ tmp &= ~CR2_SHUTDOWN; /* turn on the part */ -+ max3353_write_reg(MAX3353_CR2, tmp); -+ } -+ max3353_running++; -+#if 0 -+ /* configure INT2 for max3353 INT */ -+ MCF_GPIO_PAR_IRQ0L = -+ (MCF_GPIO_PAR_IRQ0L & MCF_GPIO_PAR_IRQL_IRQ2_MASK) | -+ MCF_GPIO_PAR_IRQL_IRQ2_IRQ2; -+#else -+ /* -+ MCF_GPIO_PAR_IRQ0H |= MCF_GPIO_PAR_IRQH_IRQ7; -+ MCF_EPORT_EPPAR = MCF_EPORT_EPPAR | MCF_EPORT_EPPAR_EPPA7_LEVEL; -+ MCF_EPORT_EPIER = MCF_EPORT_EPIER | MCF_EPORT_EPIER_EPIE7; -+ MCF_INTC0_ICR7 = 2; -+ */ -+ /* use IRQ4 on Twr-Ser1 board by J11 selected */ -+ MCF_GPIO_PAR_IRQ0H |= MCF_GPIO_PAR_IRQH_IRQ4_IRQ4; -+ MCF_EPORT_EPPAR &= ~MCF_EPORT_EPPAR_EPPA4_LEVEL; -+ MCF_EPORT_EPIER = MCF_EPORT_EPIER | MCF_EPORT_EPIER_EPIE4; -+ MCF_INTC0_ICR4 = 7; -+ -+#endif -+ /* Configure USB_DP_PDOWN/USB_DM_PDOWN */ -+ MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT0; -+ MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT1; -+ MCF_GPIO_PDDR_I |= 0xc0; -+ MCF_GPIO_PODR_I &= 0x3f; -+ -+ /* Enable VBUS_EN and VBUS_OC signals */ -+ MCF_GPIO_PAR_TIMER = -+ (MCF_GPIO_PAR_TIMER & -+ MCF_GPIO_PAR_TIMER_T3IN_MASK) | -+ MCF_GPIO_PAR_TIMER_T3IN_USB0_VBUSEN; -+ -+ MCF_GPIO_PAR_TIMER = -+ (MCF_GPIO_PAR_TIMER & -+ MCF_GPIO_PAR_TIMER_T0IN_MASK) | -+ MCF_GPIO_PAR_TIMER_T0IN_USBO_VBUSOC; -+ -+ /* Setup USB_VBUS_OC signal to be active-low */ -+ MCF_CCM_MISCCR &= (~MCF_CCM_MISCCR_USBOOC); -+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBPUE; -+} -+ -+static void max3353_uninit(struct fsl_xcvr_ops *this) -+{ -+ pr_debug("%s\n", __func__); -+ -+ max3353_running--; -+ if (!max3353_running) -+ i2c_del_driver(&max3353_i2c_driver); -+} -+ -+/* set max3353 as USB host */ -+static inline void max3353_set_host(void) -+{ -+ u8 cr1, cr2, status; -+ pr_debug("%s\n", __func__); -+ -+ /* configure transceiver for host mode */ -+ cr1 = max3353_read_reg(MAX3353_CR1); -+ cr2 = max3353_read_reg(MAX3353_CR2); -+ status = max3353_read_reg(MAX3353_STATUS); -+ pr_debug("before: CR1 %02x CR2 %02x STATUS %02x\n", cr1, cr2, status); -+ -+ cr1 &= ~(CR1_DM_PULLDOWN | CR1_DP_PULLDOWN | -+ CR1_DM_PULLUP | CR1_DP_PULLUP); -+ cr1 |= (CR1_DP_PULLDOWN | CR1_DM_PULLDOWN); -+ max3353_write_reg(MAX3353_CR1, cr1); -+ -+ cr1 = max3353_read_reg(MAX3353_CR1); -+ cr2 = max3353_read_reg(MAX3353_CR2); -+ status = max3353_read_reg(MAX3353_STATUS); -+ pr_debug(" after: CR1 %02x CR2 %02x STATUS %02x\n", cr1, cr2, status); -+} -+ -+/* set max3353 as USB device */ -+static inline void max3353_set_dev(void) -+{ -+ u8 cr1; -+ pr_debug("%s\n", __func__); -+ -+ /* FS mode, DP pull up */ -+ cr1 = max3353_read_reg(MAX3353_CR1); -+ cr1 &= ~(CR1_DM_PULLDOWN | CR1_DM_PULLDOWN | CR1_DP_PULLDOWN); -+ cr1 |= CR1_DP_PULLUP; -+ max3353_write_reg(MAX3353_CR1, cr1); -+ -+} -+ -+static void max3353_set_vbus_power(struct fsl_xcvr_ops *this, int on) -+{ -+ pr_debug("%s(on=%d)\n", __func__, on); -+} -+ -+ -+/* Enable or disable the D+ pullup. */ -+static void max3353_pullup(int on) -+{ -+ u8 cr1; -+ unsigned short ccm; -+ -+ pr_debug("%s(%d)\n", __func__, on); -+ -+ cr1 = max3353_read_reg(MAX3353_CR1); -+ cr1 &= ~(CR1_DM_PULLDOWN | CR1_DP_PULLDOWN | -+ CR1_DM_PULLUP | CR1_DP_PULLUP); -+ -+ ccm = MCF_CCM_UOCSR; -+ if (on) { -+ cr1 |= CR1_DP_PULLUP; -+ ccm |= MCF_CCM_UOCSR_BVLD; -+ ccm &= ~MCF_CCM_UOCSR_SEND; -+ } else { -+ ccm &= ~MCF_CCM_UOCSR_BVLD; -+ } -+ -+ max3353_write_reg(MAX3353_CR1, cr1); -+ MCF_CCM_UOCSR = ccm; -+} -+ -+/* -+ * return the state of the ID pin. -+ * return: 0 Mini-B or nothing connected (Gadget mode) -+ * 1 Mini-A connected (Host mode) -+ */ -+int max3353_read_id_pin(void) -+{ -+ u8 status = max3353_read_reg(MAX3353_STATUS); -+ return !!(status & STATUS_ID_GND); -+} -+EXPORT_SYMBOL(max3353_read_id_pin); -+ -+static struct fsl_xcvr_ops max3353_ops = { -+ .name = "dr-max3353", -+ .init = max3353_init, -+ .uninit = max3353_uninit, -+ .set_host = max3353_set_host, -+ .set_device = max3353_set_dev, -+ .set_vbus_power = max3353_set_vbus_power, -+ .pullup = max3353_pullup, -+}; -+ -+/* module init routine. register the transceiver */ -+static int __init max3353xc_init(void) -+{ -+ pr_debug("%s\n", __func__); -+ -+ fsl_usb_xcvr_register(&max3353_ops); -+ return 0; -+} -+ -+static void __exit max3353xc_exit(void) -+{ -+ pr_debug("%s\n", __func__); -+ fsl_usb_xcvr_unregister(&max3353_ops); -+} -+ -+module_init(max3353xc_init); -+module_exit(max3353xc_exit); -+ -+MODULE_ALIAS("max3353"); -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("max3353 transceiver driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/arch/m68k/coldfire/m5441x/usb.c -@@ -0,0 +1,276 @@ -+/* -+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <linux/err.h> -+#include <linux/platform_device.h> -+#include <linux/fsl_devices.h> -+#include <linux/usb/fsl_xcvr.h> -+#include <asm/mcfsim.h> -+ -+#define MCF_SCM_BCR MCF_REG32(0xFC040024) -+#define MCF_SCM_BCR_GBR (1 << 9) /* global bursts for read */ -+#define MCF_SCM_BCR_GBW (1 << 8) /* global bursts for write */ -+#define MCF_SCM_BCR_SBE_ALL (0xff << 0) /* slave burst enable */ -+ -+#define MAX_XCVR 3 -+struct fsl_xcvr_ops *g_xc_ops[MAX_XCVR] = { NULL }; -+ -+#ifdef ULPI_DEBUG -+void print_ulpi_regs(void) -+{ -+ pr_debug("MCF_SCM_BCR=0x%08lx MCF_CCM_MISCCR=0x%08x " -+ "MCF_CCM_MISSCR2=0x%08x " -+ "MCF_GPIO_PAR_TIMER=0x%08x MCF_GPIO_PAR_FEC=08%08x " -+ "MCF_GPIO_PAR_SIMP0H=08%08x MCF_GPIO_PODR_G=08%08x\n", -+ MCF_SCM_BCR, MCF_CCM_MISCCR, -+ MCF_CCM_MISCCR2, MCF_GPIO_PAR_TIMER, -+ MCF_GPIO_PAR_FEC, MCF_GPIO_PAR_SIMP0H, MCF_GPIO_PODR_G); -+} -+EXPORT_SYMBOL(print_ulpi_regs); -+#endif -+ -+static inline void fsl_usb_enable_clk(void) -+{ -+ pr_debug("%s\n", __func__); -+ -+#if defined(CONFIG_USB_M5441X_MAX3353_FSLS) -+ MCF_PM_PPMCR0 = 0x30; -+ MCF_CCM_MISCCR &= ~(MCF_CCM_MISCCR_USBOOC | MCF_CCM_MISCCR_USBHOC); -+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBSRC; -+#elif !defined(CONFIG_USB_M5441X_PLLCLK) -+ /* Use external clock source if PLL isn't a multiple of 60MHz */ -+ MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_USBSRC; -+ -+ /* Initialize the USB Clock: use USB input clock */ -+ MCF_GPIO_PAR_IRQ0L = -+ (MCF_GPIO_PAR_IRQ0L & -+ MCF_GPIO_PAR_IRQL_IRQ6_MASK) | -+ MCF_GPIO_PAR_IRQL_IRQ6_USBCLKIN; -+#else -+ uint fvco, usbclk; -+ -+ fvco = CONFIG_MCFCLK * ((MCF_PLL_DR & MCF_PLL_DR_OUTDIV1) + 1); -+ usbclk = fvco / (((MCF_PLL_DR & MCF_PLL_DR_OUTDIV4) >> 16) + 1); -+ -+ if (usbclk != 60000000) -+ printk(KERN_ERR, "The usb host clock must be 60MHZ!\n\n"); -+ -+ MCF_PM_PPMCR0 = 0x30; -+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBSRC; -+#endif -+} -+ -+static inline void fsl_usb_disable_clk(void) -+{ -+ pr_debug("%s\n", __func__); -+} -+ -+void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops) -+{ -+ int i; -+ -+ pr_debug("%s '%s'\n", __func__, xcvr_ops->name); -+ for (i = 0; i < MAX_XCVR; i++) { -+ if (g_xc_ops[i] == NULL) { -+ g_xc_ops[i] = xcvr_ops; -+ return; -+ } -+ } -+ -+ pr_debug("%s failed\n", __func__); -+} -+EXPORT_SYMBOL_GPL(fsl_usb_xcvr_register); -+ -+void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops) -+{ -+ int i; -+ -+ pr_debug("%s '%s'\n", __func__, xcvr_ops->name); -+ for (i = 0; i < MAX_XCVR; i++) { -+ if (g_xc_ops[i] == xcvr_ops) { -+ g_xc_ops[i] = NULL; -+ return; -+ } -+ } -+ -+ pr_debug("%s failed\n", __func__); -+} -+EXPORT_SYMBOL_GPL(fsl_usb_xcvr_unregister); -+ -+static struct fsl_xcvr_ops *fsl_usb_get_xcvr(char *name) -+{ -+ int i; -+ -+ pr_debug("%s '%s'\n", __func__, name); -+ if (name == NULL) { -+ printk(KERN_ERR "get_xcvr(): No tranceiver name\n"); -+ return NULL; -+ } -+ -+ for (i = 0; i < MAX_XCVR; i++) { -+ if (strcmp(g_xc_ops[i]->name, name) == 0) -+ return g_xc_ops[i]; -+ } -+ pr_debug("Failed %s\n", __func__); -+ return NULL; -+} -+ -+/* The dmamask must be set for EHCI to work */ -+static u64 ehci_dmamask = ~(u32) 0; -+ -+/*! -+ * Register an instance of a USB host platform device. -+ * -+ * @param res: resource pointer -+ * @param n_res: number of resources -+ * @param config: config pointer -+ * -+ * @return newly-registered platform_device -+ * -+ * Each supported host interface is registered as an instance -+ * of the "fsl-ehci" device. Call this function multiple times -+ * to register each host interface. -+ */ -+static int instance_id; -+struct platform_device *host_pdev_register(struct resource *res, int n_res, -+ struct fsl_usb2_platform_data *config) -+{ -+ struct platform_device *pdev; -+ int rc; -+ -+ pr_debug("register host res=0x%p, size=%d\n", res, n_res); -+ -+ pdev = platform_device_register_simple("fsl-ehci", -+ instance_id, res, n_res); -+ if (IS_ERR(pdev)) { -+ printk(KERN_ERR "usb: can't register %s Host, %ld\n", -+ config->name, PTR_ERR(pdev)); -+ return NULL; -+ } -+ -+ pdev->dev.coherent_dma_mask = 0xffffffff; -+ pdev->dev.dma_mask = &ehci_dmamask; -+ -+ rc = platform_device_add_data(pdev, config, -+ sizeof(struct fsl_usb2_platform_data)); -+ if (rc) { -+ platform_device_unregister(pdev); -+ return NULL; -+ } -+ -+ printk(KERN_INFO "usb: %s host (%s) registered\n", config->name, -+ config->transceiver); -+ pr_debug("pdev=0x%p dev=0x%p resources=0x%p pdata=0x%p\n", -+ pdev, &pdev->dev, pdev->resource, pdev->dev.platform_data); -+ -+ instance_id++; -+ -+ return pdev; -+} -+ -+int usb_platform_host_init(struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ struct fsl_xcvr_ops *xops; -+ -+ xops = fsl_usb_get_xcvr(pdata->transceiver); -+ if (!xops) { -+ printk(KERN_ERR "DR transceiver ops missing\n"); -+ return -EINVAL; -+ } -+ pdata->xcvr_ops = xops; -+ pdata->xcvr_type = xops->xcvr_type; -+ pdata->pdev = pdev; -+ xops->pdata = pdata; -+ -+ if (pdata->gpio_usb_active) -+ if (pdata->gpio_usb_active()) -+ return -EINVAL; -+ -+ /* enable USB read, write and slave bursts */ -+ MCF_SCM_BCR = MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW | MCF_SCM_BCR_SBE_ALL; -+ fsl_usb_enable_clk(); -+ -+ if (xops->init) -+ xops->init(xops); -+ -+ return 0; -+} -+ -+void usb_platform_host_uninit(struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ -+ if (pdata->xcvr_ops && pdata->xcvr_ops->uninit) -+ pdata->xcvr_ops->uninit(pdata->xcvr_ops); -+ -+ pdata->regs = NULL; -+ -+ if (pdata->gpio_usb_inactive) -+ pdata->gpio_usb_inactive(); -+ -+ fsl_usb_disable_clk(); -+} -+ -+ -+static int dr_used; -+ -+int usb_platform_dr_init(struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ struct fsl_xcvr_ops *xops; -+ -+ pr_debug("%s: pdev=0x%p pdata=0x%p\n", __func__, pdev, pdata); -+ -+ xops = fsl_usb_get_xcvr(pdata->transceiver); -+ if (!xops) { -+ printk(KERN_ERR "DR transceiver ops missing\n"); -+ return -EINVAL; -+ } -+ pdata->xcvr_ops = xops; -+ pdata->xcvr_type = xops->xcvr_type; -+ pdata->pdev = pdev; -+ xops->pdata = pdata; -+ -+ /* enable USB read, write and slave bursts */ -+ MCF_SCM_BCR = MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW | MCF_SCM_BCR_SBE_ALL; -+ -+ if (!dr_used) { -+ fsl_usb_enable_clk(); -+ -+ if (xops->init) -+ xops->init(xops); -+ } -+ -+ dr_used++; -+ pr_debug("%s: success\n", __func__); -+ return 0; -+} -+EXPORT_SYMBOL_GPL(usb_platform_dr_init); -+ -+void usb_platform_dr_uninit(struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ pr_debug("%s\n", __func__); -+ -+ dr_used--; -+ if (!dr_used) { -+ if (pdata->xcvr_ops && pdata->xcvr_ops->uninit) -+ pdata->xcvr_ops->uninit(pdata->xcvr_ops); -+ -+ pdata->regs = NULL; -+ fsl_usb_disable_clk(); -+ } -+} -+EXPORT_SYMBOL_GPL(usb_platform_dr_uninit); ---- /dev/null -+++ b/arch/m68k/coldfire/m5441x/usb.h -@@ -0,0 +1,76 @@ -+/* -+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+extern int usb_platform_host_init(struct platform_device *pdev); -+extern void usb_platform_host_uninit(struct fsl_usb2_platform_data *pdata); -+extern int usb_platform_dr_init(struct platform_device *pdev); -+extern void usb_platform_dr_uninit(struct fsl_usb2_platform_data *pdata); -+extern struct platform_device *host_pdev_register(struct resource *res, -+ int n_res, struct fsl_usb2_platform_data *config); -+ -+ -+#if defined CONFIG_USB_EHCI_HCD || defined CONFIG_USB_EHCI_HCD_MODULE -+static inline void dr_register_host(struct resource *r, int rs) -+{ -+ PDATA->operating_mode = DR_HOST_MODE; -+ host_pdev_register(r, rs, PDATA); -+} -+#else -+static inline void dr_register_host(struct resource *r, int rs) -+{ -+} -+#endif -+ -+#ifdef CONFIG_USB_GADGET_FSL_USB2 -+static struct platform_device dr_udc_device; -+ -+static inline void dr_register_udc(void) -+{ -+ PDATA->operating_mode = DR_UDC_MODE; -+ dr_udc_device.dev.platform_data = PDATA; -+ -+ if (platform_device_register(&dr_udc_device)) -+ printk(KERN_ERR "usb: can't register DR gadget\n"); -+ else -+ printk(KERN_INFO "usb: DR gadget (%s) registered\n", -+ PDATA->transceiver); -+} -+#else -+static inline void dr_register_udc(void) -+{ -+} -+#endif -+ -+#ifdef CONFIG_USB_OTG -+static struct platform_device dr_otg_device; -+ -+/* -+ * set the proper operating_mode and -+ * platform_data pointer, then register the -+ * device. -+ */ -+static inline void dr_register_otg(void) -+{ -+ PDATA->operating_mode = FSL_USB2_DR_OTG; -+ dr_otg_device.dev.platform_data = PDATA; -+ -+ if (platform_device_register(&dr_otg_device)) -+ printk(KERN_ERR "usb: can't register otg device\n"); -+ else -+ printk(KERN_INFO "usb: DR OTG registered\n"); -+} -+#else -+static inline void dr_register_otg(void) -+{ -+} -+#endif ---- /dev/null -+++ b/arch/m68k/coldfire/m5441x/usb_dr.c -@@ -0,0 +1,179 @@ -+/* -+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/platform_device.h> -+#include <linux/fsl_devices.h> -+#include <asm/mcfsim.h> -+ -+#define USB_OTGREGS_BASE MCF_REG32(0xFC0B0000) -+#define INT_USB (64 + 64 + 64 + 17) /* INTC1:17 17.2.9.1*/ -+#define INT_UOCSR (64 + 64 + 64 + 27) /* INTC1:27 17.2.9.1 */ -+ -+/* -+ * Determine which platform_data struct to use, based on which -+ * transceiver is configured. -+ * PDATA is a pointer to it. -+ */ -+#ifdef CONFIG_USB_M5441X_ULPI -+static struct fsl_usb2_platform_data dr_config_ulpi; -+#define PDATA (&dr_config_ulpi) -+#else -+static struct fsl_usb2_platform_data dr_config_fsls; -+#define PDATA (&dr_config_fsls) -+#endif -+ -+/* -+ * Used to set pdata->operating_mode before registering the platform_device. -+ * If OTG is configured, the controller operates in OTG mode, -+ * otherwise it's either host or device. -+ */ -+#ifdef CONFIG_USB_OTG -+#define DR_UDC_MODE FSL_USB2_DR_OTG -+#define DR_HOST_MODE FSL_USB2_DR_OTG -+#else -+#define DR_UDC_MODE FSL_USB2_DR_DEVICE -+#define DR_HOST_MODE FSL_USB2_DR_HOST -+#endif -+ -+#include "usb.h" -+ -+/* -+ * platform data structs -+ * - Which one to use is determined by CONFIG options in usb.h -+ * - operating_mode plugged at run time -+ */ -+ -+/* off-chip ULPI transceiver */ -+static struct fsl_usb2_platform_data __maybe_unused dr_config_ulpi = { -+ .name = "DR", -+ .init = usb_platform_dr_init, -+ .exit = usb_platform_dr_uninit, -+ .phy_mode = FSL_USB2_PHY_ULPI, -+ .transceiver = "dr-ulpi", -+ .power_budget = 500, -+ .es = 1, -+ .big_endian_mmio = 1, -+ .big_endian_desc = 1, -+ .le_setup_buf = 1, -+}; -+ -+/* on-chip FS/LS serial transceiver */ -+static struct fsl_usb2_platform_data __maybe_unused dr_config_fsls = { -+ .name = "DR", -+ .init = usb_platform_dr_init, -+ .exit = usb_platform_dr_uninit, -+ .phy_mode = FSL_USB2_PHY_SERIAL, -+#ifdef CONFIG_USB_M5441X_MAX3353_FSLS -+ .transceiver = "dr-max3353", -+#else -+ .transceiver = "dr-fsls", -+#endif -+ .power_budget = 500, -+ .es = 1, -+ .big_endian_mmio = 1, -+ .big_endian_desc = 1, -+ .le_setup_buf = 1, -+}; -+ -+/* -+ * resources -+ */ -+static struct resource dr_udc_resources[] = { -+ [0] = { -+ .start = (u32)(&USB_OTGREGS_BASE), -+ .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = INT_USB, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct resource dr_otg_resources[] = { -+ [0] = { -+ .start = (u32)(&USB_OTGREGS_BASE), -+ .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = INT_USB, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct resource dr_host_resources[] = { -+ [0] = { -+ .start = (u32)(&USB_OTGREGS_BASE), -+ .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = INT_USB, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 dr_udc_dmamask = ~(u32) 0; -+static void dr_udc_release(struct device *dev) -+{ -+} -+ -+static u64 dr_otg_dmamask = ~(u32) 0; -+static void dr_otg_release(struct device *dev) -+{ -+} -+ -+/* -+ * platform device structs -+ * dev.platform_data field plugged at run time -+ */ -+static struct platform_device __maybe_unused dr_udc_device = { -+ .name = "fsl-usb2-udc", -+ .id = -1, -+ .dev = { -+ .release = dr_udc_release, -+ .dma_mask = &dr_udc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .resource = dr_udc_resources, -+ .num_resources = ARRAY_SIZE(dr_udc_resources), -+}; -+ -+static struct platform_device __maybe_unused dr_otg_device = { -+#ifdef CONFIG_USB_M5441X_MAX3353_FSLS -+ .name = "max3353-otg", -+#else -+ .name = "fsl-usb2-otg", -+#endif -+ .id = -1, -+ .dev = { -+ .release = dr_otg_release, -+ .dma_mask = &dr_otg_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .resource = dr_otg_resources, -+ .num_resources = ARRAY_SIZE(dr_otg_resources), -+}; -+ -+static int __init usb_dr_init(void) -+{ -+ pr_debug("%s:\n", __func__); -+ -+ dr_register_otg(); -+ dr_register_host(dr_host_resources, ARRAY_SIZE(dr_host_resources)); -+ dr_register_udc(); -+ -+ return 0; -+} -+ -+module_init(usb_dr_init); ---- /dev/null -+++ b/arch/m68k/coldfire/m5441x/usb_host.c -@@ -0,0 +1,115 @@ -+/* -+ * Copyright (C) 2004-2011 Freescale Semiconductor, Inc. All rights reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/platform_device.h> -+#include <linux/fsl_devices.h> -+#include <asm/mcfsim.h> -+ -+#define USB_H1REGS_BASE (0xFC0B4000) -+#define INT_USB_HOST (64 + 64 + 64 + 18) /* INTC1:18*/ -+ -+ -+/* -+ * Define Host module platform_data struct to use, based on which -+ * transceiver is configured. -+ * PDATA is a pointer to it. -+ */ -+#if defined(CONFIG_USB_M5441X_H1_FSLS) -+static struct fsl_usb2_platform_data h1_config_fsls; -+#define PDATA (&h1_config_fsls) -+#else -+#warning "Unknow ColdFire USB Host module transceiver!" -+#endif -+/* -+ * Used to set pdata->operating_mode before registering the platform_device. -+ */ -+#define DR_UDC_MODE FSL_USB2_DR_DEVICE -+#define DR_HOST_MODE FSL_USB2_DR_HOST -+ -+#include "usb.h" -+ -+static int h1_gpio_active(void) -+{ -+ /* Configure USB_DP_PDOWN/USB_DM_PDOWN (external resistor) */ -+ MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT0; -+ MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT1; -+ MCF_GPIO_PDDR_I |= 0xc0; -+ MCF_GPIO_PODR_I &= 0x3f; -+ -+ MCF_GPIO_PAR_CS &= 0x0F; /*Enable GPIOB5, GPIOB6*/ -+ -+ MCF_GPIO_PDDR_B &= 0xDF; /*GPIOB5, input, USB_OC*/ -+ MCF_GPIO_PCR_B |= 0x0C00; /*pull up*/ -+ -+ MCF_GPIO_PDDR_B |= 0x40; /*GPIOB6, output*/ -+ MCF_GPIO_PODR_B |= 0x40; /*GPIOB6, output 1, VBUS enable*/ -+ MCF_GPIO_PCR_B &= ~0x3000; /*pull disable*/ -+ -+ return 0; -+} -+ -+static void h1_gpio_inactive(void) -+{ -+ MCF_GPIO_PODR_B &= 0xBF; /*GPIOB6, output 0*/ -+} -+ -+ -+/* -+ * platform data struct -+ * - operating_mode plugged at run time -+ */ -+ -+/* on-chip FS/LS serial transceiver */ -+static struct fsl_usb2_platform_data usbh1_config = { -+ .name = "Host1", -+ .init = usb_platform_host_init, -+ .exit = usb_platform_host_uninit, -+ .operating_mode = FSL_USB2_MPH_HOST, -+ .power_budget = 500, /* MIC2076: 500 mA max power */ -+ .phy_mode = FSL_USB2_PHY_SERIAL, /* FS/LS on-chip xcvr */ -+ .transceiver = "h1-fsls", -+ .gpio_usb_active = h1_gpio_active, -+ .gpio_usb_inactive = h1_gpio_inactive, -+ .es = 1, -+ .big_endian_mmio = 1, -+ .big_endian_desc = 1, -+}; -+ -+/* -+ * resources -+ */ -+static struct resource h1_resources[] = { -+ [0] = { -+ .start = USB_H1REGS_BASE, -+ .end = USB_H1REGS_BASE + 0x1ff, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = INT_USB_HOST, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static int __init usbh1_init(void) -+{ -+ host_pdev_register(h1_resources, ARRAY_SIZE(h1_resources), -+ &usbh1_config); -+ return 0; -+} -+module_init(usbh1_init); ---- /dev/null -+++ b/arch/m68k/coldfire/m5441x/xcvr.c -@@ -0,0 +1,198 @@ -+/* -+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/init.h> -+#include <linux/io.h> -+#include <linux/delay.h> -+#include <linux/usb/fsl_xcvr.h> -+#include <asm/mcfsim.h> -+ -+/* Use the configured xcvr_ops */ -+#ifdef CONFIG_USB_M5441X_ULPI -+#define XCVR_OPS (&xcvr_ops_ulpi) -+#elif defined CONFIG_USB_M5441X_FSLS -+#define XCVR_OPS (&xcvr_ops_fsls) -+#else -+#error "Invalid USB transceiver selection." -+#endif -+ -+#define MCF_FEC_ENET0_RCR MCF_REG32(0xFC0D4084) -+ -+/* -+ * Init routine for on-chip FSLS xcvr -+ */ -+static void xcvr_fsls_init(struct fsl_xcvr_ops *this) -+{ -+ pr_debug("%s: name=%s\n", __func__, this->name); -+ -+ /* Configure USB_DP_PDOWN/USB_DM_PDOWN (external resistor) */ -+ MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT0; -+ MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT1; -+ MCF_GPIO_PDDR_I |= 0xc0; -+ MCF_GPIO_PODR_I &= 0x3f; -+ -+ -+ MCF_GPIO_PAR_CS &= 0x0F; /*Enable GPIOB5, GPIOB6*/ -+ -+ MCF_GPIO_PDDR_B &= 0xDF; /*GPIOB5, input*/ -+ MCF_GPIO_PDDR_B |= 0x40; /*GPIOB6, output*/ -+ -+ MCF_GPIO_PODR_B |= 0x40; /*GPIOB6, output 1*/ -+#if 0 -+ /* Enable VBUS_EN and VBUS_OC signals */ -+ MCF_GPIO_PAR_TIMER = -+ (MCF_GPIO_PAR_TIMER & -+ MCF_GPIO_PAR_TIMER_T3IN_MASK) | -+ MCF_GPIO_PAR_TIMER_T3IN_USB0_VBUSEN; -+ -+ MCF_GPIO_PAR_TIMER = -+ (MCF_GPIO_PAR_TIMER & -+ MCF_GPIO_PAR_TIMER_T0IN_MASK) | -+ MCF_GPIO_PAR_TIMER_T0IN_USBO_VBUSOC; -+ -+ /* Setup USB_VBUS_OC signal to be active-low */ -+ MCF_CCM_MISCCR &= (~MCF_CCM_MISCCR_USBOOC); -+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBPUE; -+#endif -+ -+} -+ -+/* -+ * Init routine for off-chip ULPI xcvr -+ */ -+static void xcvr_ulpi_init(struct fsl_xcvr_ops *this) -+{ -+ pr_debug("%s: name=%s\n", __func__, this->name); -+ -+ /* disable FEC2 clock */ -+ MCF_PM_PPMSR0 = 54; -+ -+ /* enable USB OTG clock*/ -+ MCF_PM_PPMCR0 = 44; -+ -+ /* Chip select for ULPI: GPIO G4 as CS between ULPI and RMII1*/ -+ MCF_GPIO_PAR_SIMP0H = -+ (MCF_GPIO_PAR_SIMP0H & -+ MCF_GPIO_PAR_SIMP0H_DAT_MASK) | -+ MCF_GPIO_PAR_SIMP0H_DAT_GPIO; -+ -+ MCF_GPIO_PDDR_G = -+ (MCF_GPIO_PDDR_G & -+ MCF_GPIO_PDDR_G4_MASK) | -+ MCF_GPIO_PDDR_G4_OUTPUT; -+ -+ MCF_GPIO_PODR_G = -+ (MCF_GPIO_PODR_G & -+ MCF_GPIO_PODR_G4_MASK) | -+ MCF_GPIO_PODR_G4_VAL; -+ -+ /* Enable ULPI */ -+ MCF_CCM_MISCCR2 = MCF_CCM_MISCCR2 & (~MCF_CCM_MISCCR2_ULPI); -+ -+ /* Slew rate setting for OTG */ -+ MCF_GPIO_SRCR_FEC = 0x0f; -+ MCF_GPIO_SRCR_TIMER = 0xc3; -+ MCF_GPIO_SRCR_IRQ0 = 0x03; -+ -+ /* Enable the required ULPI signals */ -+ MCF_GPIO_PAR_TIMER = -+ (MCF_GPIO_PAR_TIMER & -+ MCF_GPIO_PAR_TIMER_T3IN_MASK) | -+ MCF_GPIO_PAR_TIMER_T3IN_ULPI_DIR; -+ -+ MCF_GPIO_PAR_TIMER = -+ (MCF_GPIO_PAR_TIMER & -+ MCF_GPIO_PAR_TIMER_T0IN_MASK) | -+ MCF_GPIO_PAR_TIMER_T0IN_ULPI_NXT; -+ -+ MCF_FEC_ENET0_RCR = 0x104; /* FEC0 as RMII mode */ -+ -+ MCF_GPIO_PAR_FEC = -+ (MCF_GPIO_PAR_FEC & -+ MCF_GPIO_PAR_FEC_FEC_MASK) | -+ MCF_GPIO_PAR_FEC_FEC_RMII0FUL_ULPI; -+ -+ -+ pr_debug("MCF_GPIO_PAR_TIMER:0x%x, MCF_GPIO_PAR_FEC:0x%x," -+ "MCF_GPIO_PAR_SIMP0H:0x%x, MCF_GPIO_PDDR_G:0x%x," -+ "MCF_GPIO_PODR_G:0x%x, MCF_CCM_MISCCR2:0x%x\n\n", -+ MCF_GPIO_PAR_TIMER, MCF_GPIO_PAR_FEC, -+ MCF_GPIO_PAR_SIMP0H, MCF_GPIO_PDDR_G, -+ MCF_GPIO_PODR_G, MCF_CCM_MISCCR2); -+ -+ pr_debug("OTGSC:0x%lx, PORTSC:0x%lx, USBMODE:0x%lx, " -+ "USBCMD:0x%lx, USBSTS:0x%lx, USBINTR:0x%lx, " -+ "MCF_CCM_UOCSR:0x%x\n\n", -+ MCF_REG32(0xfc0b01a4), MCF_REG32(0xfc0b0184), -+ MCF_REG32(0xfc0b01a8), MCF_REG32(0xfc0b0140), -+ MCF_REG32(0xfc0b0144), MCF_REG32(0xfc0b0148), -+ MCF_CCM_UOCSR); -+} -+ -+static void xcvr_uninit(struct fsl_xcvr_ops *this) -+{ -+ pr_debug("%s\n", __func__); -+} -+ -+static void xcvr_pullup(int on) -+{ -+ unsigned short ccm = in_be16(&MCF_CCM_UOCSR); -+ -+ pr_debug("%s(%d)\n", __func__, on); -+ -+ ccm = in_be16(&MCF_CCM_UOCSR); -+ if (on) { -+ ccm |= MCF_CCM_UOCSR_BVLD; -+ ccm &= ~MCF_CCM_UOCSR_SEND; -+ out_be16(&MCF_CCM_UOCSR, ccm); -+ } else { -+ ccm &= ~MCF_CCM_UOCSR_BVLD; -+ out_be16(&MCF_CCM_UOCSR, ccm); -+ } -+} -+ -+struct fsl_xcvr_ops xcvr_ops_ulpi = { -+ .init = xcvr_ulpi_init, -+ .uninit = xcvr_uninit, -+ .pullup = xcvr_pullup, -+ .name = "dr-ulpi", -+}; -+ -+struct fsl_xcvr_ops xcvr_ops_fsls = { -+ .init = xcvr_fsls_init, -+ .uninit = xcvr_uninit, -+ .pullup = xcvr_pullup, -+ .name = "dr-fsls", -+}; -+ -+static int __init usb_xcvr_init(void) -+{ -+ struct fsl_xcvr_ops *xops = XCVR_OPS; -+ -+ pr_debug("%s %s\n", __func__, xops->name); -+ fsl_usb_xcvr_register(xops); -+ -+ return 0; -+} -+ -+static void __exit usb_xcvr_exit(void) -+{ -+ fsl_usb_xcvr_unregister(XCVR_OPS); -+} -+ -+module_init(usb_xcvr_init); -+module_exit(usb_xcvr_exit); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("External ULPI xcvr driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/arch/m68k/coldfire/m5441x/xcvr_host.c -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All rights reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/init.h> -+#include <linux/io.h> -+#include <linux/usb/fsl_xcvr.h> -+#include <asm/mcfsim.h> -+ -+/* -+ * xcvr_ops for the on-chip xcvr on the DR controller -+ * No ops needed. -+ */ -+struct fsl_xcvr_ops xcvr_ops_h1_fsls = { -+ .name = "h1-fsls", -+}; -+ -+ -+static int __init usb_xcvr_host_init(void) -+{ -+ fsl_usb_xcvr_register(&xcvr_ops_h1_fsls); -+ -+ return 0; -+} -+ -+static void __exit usb_xcvr_host_exit(void) -+{ -+ fsl_usb_xcvr_unregister(&xcvr_ops_h1_fsls); -+} -+ -+module_init(usb_xcvr_host_init); -+module_exit(usb_xcvr_host_exit); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("On-chip FS/LS xcvr host driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/arch/m68k/coldfire/m5445x/usb.c -@@ -0,0 +1,220 @@ -+/* -+ * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <linux/err.h> -+#include <linux/platform_device.h> -+#include <linux/fsl_devices.h> -+#include <linux/usb/fsl_xcvr.h> -+#include <asm/mcfsim.h> -+ -+#define MCF_SCM_BCR MCF_REG32(0xFC040024) -+#define MCF_SCM_BCR_GBR (1 << 9) /* global bursts for read */ -+#define MCF_SCM_BCR_GBW (1 << 8) /* global bursts for write */ -+#define MCF_SCM_BCR_SBE_ALL (0xff << 0) /* slave burst enable */ -+ -+#define MAX_XCVR 3 -+struct fsl_xcvr_ops *g_xc_ops[MAX_XCVR] = { NULL }; -+ -+#ifdef ULPI_DEBUG -+void print_ulpi_regs(void) -+{ -+ pr_debug("MCF_SCM_BCR=0x%08lx MCF_CCM_MISCCR=0x%08x " -+ "MCF_GPIO_PAR_DMA=0x%08x MCF_GPIO_PAR_USB=08%08x " -+ "MCF_GPIO_PAR_FEC=08%08x\n", -+ MCF_SCM_BCR, MCF_CCM_MISCCR, MCF_GPIO_PAR_DMA, -+ MCF_GPIO_PAR_USB, MCF_GPIO_PAR_FEC); -+} -+EXPORT_SYMBOL(print_ulpi_regs); -+#endif -+ -+static inline void fsl_usb_enable_clk(void) -+{ -+ pr_debug("%s\n", __func__); -+ -+ /* Use external clock source if PLL isn't a multiple of 60MHz */ -+ MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_USBSRC; -+ -+ /* Initialize the USB Clock: use USB input clock */ -+ MCF_GPIO_PAR_DMA = (MCF_GPIO_PAR_DMA & MCF_GPIO_PAR_DMA_DREQ1_MASK) | -+ MCF_GPIO_PAR_DMA_DREQ1_USB_CLKIN; -+} -+ -+static inline void fsl_usb_disable_clk(void) -+{ -+ pr_debug("%s\n", __func__); -+} -+ -+void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops) -+{ -+ int i; -+ -+ pr_debug("%s '%s'\n", __func__, xcvr_ops->name); -+ for (i = 0; i < MAX_XCVR; i++) { -+ if (g_xc_ops[i] == NULL) { -+ g_xc_ops[i] = xcvr_ops; -+ return; -+ } -+ } -+ -+ pr_debug("%s failed\n", __func__); -+} -+EXPORT_SYMBOL_GPL(fsl_usb_xcvr_register); -+ -+void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops) -+{ -+ int i; -+ -+ pr_debug("%s '%s'\n", __func__, xcvr_ops->name); -+ for (i = 0; i < MAX_XCVR; i++) { -+ if (g_xc_ops[i] == xcvr_ops) { -+ g_xc_ops[i] = NULL; -+ return; -+ } -+ } -+ -+ pr_debug("%s failed\n", __func__); -+} -+EXPORT_SYMBOL_GPL(fsl_usb_xcvr_unregister); -+ -+static struct fsl_xcvr_ops *fsl_usb_get_xcvr(char *name) -+{ -+ int i; -+ -+ pr_debug("%s '%s'\n", __func__, name); -+ if (name == NULL) { -+ printk(KERN_ERR "get_xcvr(): No tranceiver name\n"); -+ return NULL; -+ } -+ -+ for (i = 0; i < MAX_XCVR; i++) { -+ if (strcmp(g_xc_ops[i]->name, name) == 0) -+ return g_xc_ops[i]; -+ } -+ pr_debug("Failed %s\n", __func__); -+ return NULL; -+} -+ -+/* The dmamask must be set for EHCI to work */ -+static u64 ehci_dmamask = ~(u32) 0; -+ -+/*! -+ * Register an instance of a USB host platform device. -+ * -+ * @param res: resource pointer -+ * @param n_res: number of resources -+ * @param config: config pointer -+ * -+ * @return newly-registered platform_device -+ * -+ * Each supported host interface is registered as an instance -+ * of the "fsl-ehci" device. Call this function multiple times -+ * to register each host interface. -+ */ -+static int instance_id; -+struct platform_device *host_pdev_register(struct resource *res, int n_res, -+ struct fsl_usb2_platform_data *config) -+{ -+ struct platform_device *pdev; -+ int rc; -+ -+ pr_debug("register host res=0x%p, size=%d\n", res, n_res); -+ -+ pdev = platform_device_register_simple("fsl-ehci", -+ instance_id, res, n_res); -+ if (IS_ERR(pdev)) { -+ printk(KERN_ERR "usb: can't register %s Host, %ld\n", -+ config->name, PTR_ERR(pdev)); -+ return NULL; -+ } -+ -+ pdev->dev.coherent_dma_mask = 0xffffffff; -+ pdev->dev.dma_mask = &ehci_dmamask; -+ -+ rc = platform_device_add_data(pdev, config, -+ sizeof(struct fsl_usb2_platform_data)); -+ if (rc) { -+ platform_device_unregister(pdev); -+ return NULL; -+ } -+ -+ printk(KERN_INFO "usb: %s host (%s) registered\n", config->name, -+ config->transceiver); -+ pr_debug("pdev=0x%p dev=0x%p resources=0x%p pdata=0x%p\n", -+ pdev, &pdev->dev, pdev->resource, pdev->dev.platform_data); -+ -+ instance_id++; -+ -+ return pdev; -+} -+ -+ -+static int dr_used; -+ -+int usb_platform_dr_init(struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ struct fsl_xcvr_ops *xops; -+ -+ pr_debug("%s: pdev=0x%p pdata=0x%p\n", __func__, pdev, pdata); -+ -+ xops = fsl_usb_get_xcvr(pdata->transceiver); -+ if (!xops) { -+ printk(KERN_ERR "DR transceiver ops missing\n"); -+ return -EINVAL; -+ } -+ pdata->xcvr_ops = xops; -+ pdata->xcvr_type = xops->xcvr_type; -+ pdata->pdev = pdev; -+ xops->pdata = pdata; -+ -+ /* enable USB read, write and slave bursts */ -+ MCF_SCM_BCR = MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW | MCF_SCM_BCR_SBE_ALL; -+ -+ if (!dr_used) { -+ fsl_usb_enable_clk(); -+ -+ if (xops->init) -+ xops->init(xops); -+ } -+ -+ dr_used++; -+ pr_debug("%s: success\n", __func__); -+ return 0; -+} -+EXPORT_SYMBOL_GPL(usb_platform_dr_init); -+ -+void usb_platform_dr_uninit(struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ -+ pr_debug("%s\n", __func__); -+ -+ dr_used--; -+ if (!dr_used) { -+ if (pdata->xcvr_ops && pdata->xcvr_ops->uninit) -+ pdata->xcvr_ops->uninit(pdata->xcvr_ops); -+ -+ pdata->regs = NULL; -+ fsl_usb_disable_clk(); -+ } -+} -+EXPORT_SYMBOL_GPL(usb_platform_dr_uninit); ---- /dev/null -+++ b/arch/m68k/coldfire/m5445x/usb.h -@@ -0,0 +1,107 @@ -+/* -+ * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+ -+extern int usb_platform_dr_init(struct platform_device *pdev); -+extern void usb_platform_dr_uninit(struct fsl_usb2_platform_data *pdata); -+extern struct platform_device *host_pdev_register(struct resource *res, -+ int n_res, struct fsl_usb2_platform_data *config); -+ -+ -+/* -+ * Determine which platform_data struct to use, based on which -+ * transceiver is configured. -+ * PDATA is a pointer to it. -+ */ -+#ifdef CONFIG_USB_M5445X_ULPI -+static struct fsl_usb2_platform_data dr_config_ulpi; -+#define PDATA (&dr_config_ulpi) -+#else -+static struct fsl_usb2_platform_data dr_config_fsls; -+#define PDATA (&dr_config_fsls) -+#endif -+ -+/* -+ * Used to set pdata->operating_mode before registering the platform_device. -+ * If OTG is configured, the controller operates in OTG mode, -+ * otherwise it's either host or device. -+ */ -+#ifdef CONFIG_USB_OTG -+#define DR_UDC_MODE FSL_USB2_DR_OTG -+#define DR_HOST_MODE FSL_USB2_DR_OTG -+#else -+#define DR_UDC_MODE FSL_USB2_DR_DEVICE -+#define DR_HOST_MODE FSL_USB2_DR_HOST -+#endif -+ -+ -+#if defined CONFIG_USB_EHCI_HCD || defined CONFIG_USB_EHCI_HCD_MODULE -+static inline void dr_register_host(struct resource *r, int rs) -+{ -+ PDATA->operating_mode = DR_HOST_MODE; -+ host_pdev_register(r, rs, PDATA); -+} -+#else -+static inline void dr_register_host(struct resource *r, int rs) -+{ -+} -+#endif -+ -+#ifdef CONFIG_USB_GADGET_FSL_USB2 -+static struct platform_device dr_udc_device; -+ -+static inline void dr_register_udc(void) -+{ -+ PDATA->operating_mode = DR_UDC_MODE; -+ dr_udc_device.dev.platform_data = PDATA; -+ -+ if (platform_device_register(&dr_udc_device)) -+ printk(KERN_ERR "usb: can't register DR gadget\n"); -+ else -+ printk(KERN_INFO "usb: DR gadget (%s) registered\n", -+ PDATA->transceiver); -+} -+#else -+static inline void dr_register_udc(void) -+{ -+} -+#endif -+ -+#ifdef CONFIG_USB_OTG -+static struct platform_device dr_otg_device; -+ -+/* -+ * set the proper operating_mode and -+ * platform_data pointer, then register the -+ * device. -+ */ -+static inline void dr_register_otg(void) -+{ -+ PDATA->operating_mode = FSL_USB2_DR_OTG; -+ dr_otg_device.dev.platform_data = PDATA; -+ -+ if (platform_device_register(&dr_otg_device)) -+ printk(KERN_ERR "usb: can't register otg device\n"); -+ else -+ printk(KERN_INFO "usb: DR OTG registered\n"); -+} -+#else -+static inline void dr_register_otg(void) -+{ -+} -+#endif ---- /dev/null -+++ b/arch/m68k/coldfire/m5445x/usb_dr.c -@@ -0,0 +1,152 @@ -+/* -+ * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/platform_device.h> -+#include <linux/fsl_devices.h> -+#include <asm/mcfsim.h> -+ -+#define USB_OTGREGS_BASE MCF_REG32(0xFC0B0000) -+#define INT_USB (64 + 64 + 47) /* INTC1:47 16.2.9.1 */ -+#define INT_UOCSR (64 + 64 + 53) /* INTC1:53 16.2.9.1 */ -+ -+#include "usb.h" -+ -+/* -+ * platform data structs -+ * - Which one to use is determined by CONFIG options in usb.h -+ * - operating_mode plugged at run time -+ */ -+ -+/* off-chip ULPI transceiver */ -+static struct fsl_usb2_platform_data __maybe_unused dr_config_ulpi = { -+ .name = "DR", -+ .init = usb_platform_dr_init, -+ .exit = usb_platform_dr_uninit, -+ .phy_mode = FSL_USB2_PHY_ULPI, -+ .transceiver = "dr-ulpi", -+ .power_budget = 500, -+ .es = 1, -+ .big_endian_mmio = 1, -+ .big_endian_desc = 1, -+ .le_setup_buf = 1, -+}; -+ -+/* on-chip FS/LS serial transceiver */ -+static struct fsl_usb2_platform_data __maybe_unused dr_config_fsls = { -+ .name = "DR", -+ .init = usb_platform_dr_init, -+ .exit = usb_platform_dr_uninit, -+ .phy_mode = FSL_USB2_PHY_SERIAL, -+ .transceiver = "dr-fsls", -+ .power_budget = 500, -+ .es = 1, -+ .big_endian_mmio = 1, -+ .big_endian_desc = 1, -+ .le_setup_buf = 1, -+}; -+ -+/* -+ * resources -+ */ -+static struct resource dr_host_resources[] = { -+ [0] = { -+ .start = (u32)(&USB_OTGREGS_BASE), -+ .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = INT_USB, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct resource dr_otg_resources[] = { -+ [0] = { -+ .start = (u32)(&USB_OTGREGS_BASE), -+ .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = INT_USB, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct resource dr_udc_resources[] = { -+ [0] = { -+ .start = (u32)(&USB_OTGREGS_BASE), -+ .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = INT_USB, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+static u64 dr_udc_dmamask = ~(u32) 0; -+static void dr_udc_release(struct device *dev) -+{ -+} -+ -+static u64 dr_otg_dmamask = ~(u32) 0; -+static void dr_otg_release(struct device *dev) -+{ -+} -+ -+/* -+ * platform device structs -+ * dev.platform_data field plugged at run time -+ */ -+static struct platform_device __maybe_unused dr_udc_device = { -+ .name = "fsl-usb2-udc", -+ .id = -1, -+ .dev = { -+ .release = dr_udc_release, -+ .dma_mask = &dr_udc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .resource = dr_udc_resources, -+ .num_resources = ARRAY_SIZE(dr_udc_resources), -+}; -+ -+static struct platform_device __maybe_unused dr_otg_device = { -+ .name = "fsl-usb2-otg", -+ .id = -1, -+ .dev = { -+ .release = dr_otg_release, -+ .dma_mask = &dr_otg_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .resource = dr_otg_resources, -+ .num_resources = ARRAY_SIZE(dr_otg_resources), -+}; -+ -+static int __init usb_dr_init(void) -+{ -+ pr_debug("%s:\n", __func__); -+ -+ dr_register_otg(); -+ dr_register_host(dr_host_resources, ARRAY_SIZE(dr_host_resources)); -+ dr_register_udc(); -+ -+ return 0; -+} -+ -+module_init(usb_dr_init); ---- /dev/null -+++ b/arch/m68k/coldfire/m5445x/xcvr.c -@@ -0,0 +1,127 @@ -+/* -+ * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/init.h> -+#include <linux/io.h> -+#include <linux/usb/fsl_xcvr.h> -+#include <asm/mcfsim.h> -+ -+/* Use the configured xcvr_ops */ -+#ifdef CONFIG_USB_M5445X_ULPI -+#define XCVR_OPS (&xcvr_ops_ulpi) -+#elif defined CONFIG_USB_M5445X_FSLS -+#define XCVR_OPS (&xcvr_ops_fsls) -+#else -+#error "Invalid USB transceiver selection." -+#endif -+ -+/* -+ * Init routine for on-chip FSLS xcvr -+ */ -+static void xcvr_fsls_init(struct fsl_xcvr_ops *this) -+{ -+ pr_debug("%s: name=%s\n", __func__, this->name); -+ -+ /* Enable VBUS_EN and VBUS_OC signals */ -+ MCF_GPIO_PAR_USB = MCF_GPIO_PAR_USB_VBUSEN_VBUSEN | -+ MCF_GPIO_PAR_USB_VBUSOC_VBUSOC; -+ -+ /* Setup USB_VBUS_OC signal to be active-low */ -+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBOC; -+} -+ -+/* -+ * Init routine for off-chip ULPI xcvr -+ */ -+static void xcvr_ulpi_init(struct fsl_xcvr_ops *this) -+{ -+ pr_debug("%s: name=%s\n", __func__, this->name); -+ -+ /* Enable the required ULPI signals */ -+ MCF_GPIO_PAR_DMA = (MCF_GPIO_PAR_DMA & -+ MCF_GPIO_PAR_DMA_DACK1_MASK) | -+ MCF_GPIO_PAR_DMA_DACK1_ULPI_DIR; -+ -+ MCF_GPIO_PAR_USB = MCF_GPIO_PAR_USB_VBUSEN_ULPI_NXT | -+ MCF_GPIO_PAR_USB_VBUSOC_ULPI_STP; -+ -+ MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC & -+ MCF_GPIO_PAR_FEC_FEC0_MASK) | -+ MCF_GPIO_PAR_FEC_FEC0_RMII_ULPI; -+} -+ -+static void xcvr_uninit(struct fsl_xcvr_ops *this) -+{ -+ pr_debug("%s\n", __func__); -+} -+ -+static void xcvr_pullup(int on) -+{ -+ unsigned short ccm = in_be16(&MCF_CCM_UOCSR); -+ -+ pr_debug("%s(%d)\n", __func__, on); -+ -+ ccm = in_be16(&MCF_CCM_UOCSR); -+ if (on) { -+ ccm |= MCF_CCM_UOCSR_BVLD; -+ ccm &= ~MCF_CCM_UOCSR_SEND; -+ out_be16(&MCF_CCM_UOCSR, ccm); -+ } else { -+ ccm &= ~MCF_CCM_UOCSR_BVLD; -+ out_be16(&MCF_CCM_UOCSR, ccm); -+ } -+} -+ -+struct fsl_xcvr_ops xcvr_ops_ulpi = { -+ .init = xcvr_ulpi_init, -+ .uninit = xcvr_uninit, -+ .pullup = xcvr_pullup, -+ .name = "dr-ulpi", -+}; -+ -+struct fsl_xcvr_ops xcvr_ops_fsls = { -+ .init = xcvr_fsls_init, -+ .uninit = xcvr_uninit, -+ .pullup = xcvr_pullup, -+ .name = "dr-fsls", -+}; -+ -+static int __init usb_xcvr_init(void) -+{ -+ struct fsl_xcvr_ops *xops = XCVR_OPS; -+ -+ pr_debug("%s %s\n", __func__, xops->name); -+ fsl_usb_xcvr_register(xops); -+ -+ return 0; -+} -+ -+static void __exit usb_xcvr_exit(void) -+{ -+ fsl_usb_xcvr_unregister(XCVR_OPS); -+} -+ -+module_init(usb_xcvr_init); -+module_exit(usb_xcvr_exit); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("External ULPI xcvr driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/arch/m68k/include/asm/fsl_usb_gadget.h -@@ -0,0 +1,45 @@ -+/* -+ * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+/* -+ * USB Gadget side, platform-specific functionality. -+ */ -+ -+#include <linux/usb/fsl_xcvr.h> -+ -+/* Needed for i2c/serial transceivers */ -+static inline void -+fsl_platform_set_device_mode(struct fsl_usb2_platform_data *pdata) -+{ -+ if (pdata->xcvr_ops && pdata->xcvr_ops->set_device) -+ pdata->xcvr_ops->set_device(); -+} -+ -+static inline void -+fsl_platform_pullup_enable(struct fsl_usb2_platform_data *pdata) -+{ -+ if (pdata->xcvr_ops && pdata->xcvr_ops->pullup) -+ pdata->xcvr_ops->pullup(1); -+} -+ -+static inline void -+fsl_platform_pullup_disable(struct fsl_usb2_platform_data *pdata) -+{ -+ if (pdata->xcvr_ops && pdata->xcvr_ops->pullup) -+ pdata->xcvr_ops->pullup(0); -+} ---- /dev/null -+++ b/arch/m68k/include/asm/fsl_usb_io.h -@@ -0,0 +1,43 @@ -+/* Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+#ifndef _FSL_USB_IO_H -+#define _FSL_USB_IO_H -+ -+#undef inb_p -+#undef outb_p -+#undef inl_p -+#undef outl_p -+#define inb_p in_8 -+#define outb_p(b, addr) (void)((*(__force volatile u8 *) (addr)) = (b)) -+#define inl_p in_be32 -+#define outl_p(l, addr) (void)((*(__force volatile u32 *) (addr)) = (l)) -+ -+#define fsl_readl(addr) in_be32((__force unsigned *)(addr)) -+#define fsl_writel(val32, addr) out_be32((__force unsigned *)(addr), (val32)) -+ -+static inline void fsl_set_usb_accessors(struct fsl_usb2_platform_data *pdata) -+{ -+} -+/* -+#ifndef cpu_to_hc32 -+#define cpu_to_hc32(x) (x) -+#endif -+#ifndef hc32_to_cpu -+#define hc32_to_cpu(x) (x) -+#endif -+*/ -+#endif /* _FSL_USB_IO_H */ ---- /dev/null -+++ b/arch/m68k/include/asm/fsl_usb_platform.h -@@ -0,0 +1,78 @@ -+/* -+ * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#ifndef FSL_USB_PLATFORM_H -+#define FSL_USB_PLATFORM_H -+ -+#include <linux/usb/fsl_xcvr.h> -+#include <linux/usb/fsl_usb2.h> -+#include <asm/mcfsim.h> -+ -+extern struct resource *otg_get_resources(void); -+ -+extern struct fsl_usb2_platform_data; -+ -+/* ehci_arc_hc_driver.flags value */ -+#define FSL_PLATFORM_HC_FLAGS (HCD_USB2 | HCD_MEMORY) -+ -+static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, -+ enum fsl_usb2_phy_modes phy_mode, -+ unsigned int port_offset); -+ -+static inline void fsl_platform_usb_setup(struct ehci_hcd *ehci) -+{ -+ struct fsl_usb2_platform_data *pdata; -+ -+ pdata = ehci_to_hcd(ehci)->self.controller->platform_data; -+ ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); -+} -+ -+static inline void fsl_platform_set_host_mode(struct usb_hcd *hcd) -+{ -+ unsigned int temp; -+ struct fsl_usb2_platform_data *pdata; -+ struct fsl_usb_host_regs *regs; -+ -+ pdata = hcd->self.controller->platform_data; -+ regs = pdata->regs; -+ -+ if (pdata->xcvr_ops && pdata->xcvr_ops->set_host) -+ pdata->xcvr_ops->set_host(); -+ -+ /* set host mode and select "big endian" */ -+ temp = in_be32(®s->usbmode); -+ temp |= USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0); -+ out_be32(®s->usbmode, temp); -+ -+ pr_debug("%s: set usbmode to 0x%x\n\n", __func__, -+ in_be32(®s->usbmode)); -+ -+} -+ -+static inline void -+fsl_platform_set_vbus_power(struct fsl_usb2_platform_data *pdata, int on) -+{ -+#ifdef CONFIG_USB_M5441X_FSLS -+ MCF_GPIO_PAR_CS &= 0x0F; /*Enable GPIOB5, GPIOB6*/ -+ -+ MCF_GPIO_PDDR_B &= 0xDF; /*GPIOB5, input*/ -+ MCF_GPIO_PDDR_B |= 0x40; /*GPIOB6, output*/ -+ -+ if (on) -+ MCF_GPIO_PODR_B |= 0x40; /*GPIOB6, output 1*/ -+ else -+ MCF_GPIO_PODR_B &= 0xBF; /*GPIOB6, output 0*/ -+#endif -+} -+ -+#endif ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -66,6 +66,7 @@ obj-$(CONFIG_PARIDE) += block/paride/ - obj-$(CONFIG_TC) += tc/ - obj-$(CONFIG_UWB) += uwb/ - obj-$(CONFIG_USB_OTG_UTILS) += usb/otg/ -+obj-$(CONFIG_USB_OTG) += usb/otg/ - obj-$(CONFIG_USB) += usb/ - obj-$(CONFIG_USB_MUSB_HDRC) += usb/musb/ - obj-$(CONFIG_PCI) += usb/ ---- a/drivers/usb/Kconfig -+++ b/drivers/usb/Kconfig -@@ -57,6 +57,8 @@ config USB_ARCH_HAS_EHCI - boolean - default y if PPC_83xx - default y if PPC_MPC512x -+ default y if M5445X -+ default y if M5441X - default y if SOC_AU1200 - default y if ARCH_IXP4XX - default y if ARCH_W90X900 ---- a/drivers/usb/core/Kconfig -+++ b/drivers/usb/core/Kconfig -@@ -109,7 +109,7 @@ config USB_SUSPEND - config USB_OTG - bool "OTG support" - depends on USB && EXPERIMENTAL -- depends on USB_SUSPEND -+# depends on USB_SUSPEND - default n - help - The most notable feature of USB OTG is support for a ---- a/drivers/usb/gadget/Kconfig -+++ b/drivers/usb/gadget/Kconfig -@@ -156,7 +156,7 @@ config USB_ATMEL_USBA - - config USB_GADGET_FSL_USB2 - boolean "Freescale Highspeed USB DR Peripheral Controller" -- depends on FSL_SOC || ARCH_MXC -+ depends on FSL_SOC || ARCH_MXC || HAVE_FSL_USB_DR - select USB_GADGET_DUALSPEED - select USB_FSL_MPH_DR_OF if OF - help ---- a/drivers/usb/gadget/fsl_udc_core.c -+++ b/drivers/usb/gadget/fsl_udc_core.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2004-2007 Freescale Semicondutor, Inc. All rights reserved. -+ * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. All rights reserved. - * - * Author: Li Yang <leoli@freescale.com> - * Jiang Bo <tanya.jiang@freescale.com> -@@ -52,6 +52,12 @@ - #define DRIVER_AUTHOR "Li Yang/Jiang Bo" - #define DRIVER_VERSION "Apr 20, 2007" - -+ -+#define USB_MODE_CTRL_MODE_MASK 0x00000003 -+#define USB_MODE_ES 0x00000004 /* (big) Endian */ -+#define cpu_to_hc32(x) (x) -+#define hc32_to_cpu(x) (x) -+ - #define DMA_ADDR_INVALID (~(dma_addr_t)0) - - static const char driver_name[] = "fsl-usb2-udc"; -@@ -62,6 +68,9 @@ static struct usb_dr_device *dr_regs; - static struct usb_sys_interface *usb_sys_regs; - #endif - -+static int fsl_udc_suspend(struct device *dev, pm_message_t state); -+static int fsl_udc_resume(struct device *dev); -+ - /* it is initialized in probe() */ - static struct fsl_udc *udc_controller = NULL; - -@@ -76,6 +85,7 @@ fsl_ep0_desc = { - - static void fsl_ep_fifo_flush(struct usb_ep *_ep); - -+#ifndef CONFIG_COLDFIRE - #ifdef CONFIG_PPC32 - #define fsl_readl(addr) in_le32(addr) - #define fsl_writel(val32, addr) out_le32(addr, val32) -@@ -83,7 +93,7 @@ static void fsl_ep_fifo_flush(struct usb - #define fsl_readl(addr) readl(addr) - #define fsl_writel(val32, addr) writel(val32, addr) - #endif -- -+#endif - /******************************************************************** - * Internal Used Function - ********************************************************************/ -@@ -184,6 +194,12 @@ static int dr_controller_setup(struct fs - unsigned long timeout; - #define FSL_UDC_RESET_TIMEOUT 1000 - -+#ifdef CONFIG_COLDFIRE -+ struct fsl_usb2_platform_data *pdata; -+ if (!udc) -+ return -EINVAL; -+ pdata = udc->pdata; -+#endif - /* Config PHY interface */ - portctrl = fsl_readl(&dr_regs->portsc1); - portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH); -@@ -226,11 +242,20 @@ static int dr_controller_setup(struct fs - - /* Set the controller as device mode */ - tmp = fsl_readl(&dr_regs->usbmode); -+#ifdef CONFIG_COLDFIRE -+ tmp &= ~USB_MODE_CTRL_MODE_MASK; /* clear mode bits */ -+#endif - tmp |= USB_MODE_CTRL_MODE_DEVICE; - /* Disable Setup Lockout */ - tmp |= USB_MODE_SETUP_LOCK_OFF; -+#ifdef CONFIG_COLDFIRE -+ if (pdata->es) -+ tmp |= USB_MODE_ES; -+#endif - fsl_writel(tmp, &dr_regs->usbmode); -- -+#ifdef CONFIG_COLDFIRE -+ fsl_platform_set_device_mode(pdata); -+#endif - /* Clear the setup status */ - fsl_writel(0, &dr_regs->usbsts); - -@@ -243,7 +268,7 @@ static int dr_controller_setup(struct fs - fsl_readl(&dr_regs->endpointlistaddr)); - - /* Config control enable i/o output, cpu endian register */ --#ifndef CONFIG_ARCH_MXC -+#if !defined(CONFIG_ARCH_MXC) && !defined(CONFIG_COLDFIRE) - ctrl = __raw_readl(&usb_sys_regs->control); - ctrl |= USB_CTRL_IOENB; - __raw_writel(ctrl, &usb_sys_regs->control); -@@ -267,7 +292,9 @@ static int dr_controller_setup(struct fs - static void dr_controller_run(struct fsl_udc *udc) - { - u32 temp; -- -+#ifdef CONFIG_COLDFIRE -+ fsl_platform_pullup_enable(udc->pdata); -+#endif - /* Enable DR irq reg */ - temp = USB_INTR_INT_EN | USB_INTR_ERR_INT_EN - | USB_INTR_PTC_DETECT_EN | USB_INTR_RESET_EN -@@ -277,12 +304,12 @@ static void dr_controller_run(struct fsl - - /* Clear stopped bit */ - udc->stopped = 0; -- -+#ifndef CONFIG_COLDFIRE - /* Set the controller as device mode */ - temp = fsl_readl(&dr_regs->usbmode); - temp |= USB_MODE_CTRL_MODE_DEVICE; - fsl_writel(temp, &dr_regs->usbmode); -- -+#endif - /* Set controller to Run */ - temp = fsl_readl(&dr_regs->usbcmd); - temp |= USB_CMD_RUN_STOP; -@@ -292,7 +319,18 @@ static void dr_controller_run(struct fsl - static void dr_controller_stop(struct fsl_udc *udc) - { - unsigned int tmp; -- -+#ifdef CONFIG_COLDFIRE -+ if (udc->gadget.is_otg) { -+#ifdef CONFIG_USB_M5441X_MAX3353_FSLS -+ if (max3353_read_id_pin()) { -+#else -+ if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) { -+#endif -+ pr_debug("udc: Leaving early\n"); -+ return; -+ } -+ } -+#endif - /* disable all INTR */ - fsl_writel(0, &dr_regs->usbintr); - -@@ -301,7 +339,9 @@ static void dr_controller_stop(struct fs - - /* disable IO output */ - /* usb_sys_regs->control = 0; */ -- -+#ifdef CONFIG_COLDFIRE -+ fsl_platform_pullup_disable(udc->pdata); -+#endif - /* set controller to Stop */ - tmp = fsl_readl(&dr_regs->usbcmd); - tmp &= ~USB_CMD_RUN_STOP; -@@ -408,10 +448,13 @@ static void struct_ep_qh_setup(struct fs - } - if (zlt) - tmp |= EP_QUEUE_HEAD_ZLT_SEL; -- -+#ifdef CONFIG_COLDFIRE -+ p_QH->max_pkt_length = cpu_to_hc32(tmp); -+#else - p_QH->max_pkt_length = cpu_to_le32(tmp); - p_QH->next_dtd_ptr = 1; - p_QH->size_ioc_int_sts = 0; -+#endif - } - - /* Setup qh structure and ep register for ep0. */ -@@ -616,7 +659,11 @@ static void fsl_queue_td(struct fsl_ep * - struct fsl_req *lastreq; - lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); - lastreq->tail->next_td_ptr = -+#ifdef CONFIG_COLDFIRE -+ cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); -+#else - cpu_to_le32(req->head->td_dma & DTD_ADDR_MASK); -+#endif - /* Read prime bit, if 1 goto done */ - if (fsl_readl(&dr_regs->endpointprime) & bitmask) - goto out; -@@ -641,11 +688,19 @@ static void fsl_queue_td(struct fsl_ep * - - /* Write dQH next pointer and terminate bit to 0 */ - temp = req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK; -+#ifdef CONFIG_COLDFIRE -+ dQH->next_dtd_ptr = cpu_to_hc32(temp); -+#else - dQH->next_dtd_ptr = cpu_to_le32(temp); -- -+#endif - /* Clear active and halt bit */ -+#ifdef CONFIG_COLDFIRE -+ temp = cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE -+ | EP_QUEUE_HEAD_STATUS_HALT)); -+#else - temp = cpu_to_le32(~(EP_QUEUE_HEAD_STATUS_ACTIVE - | EP_QUEUE_HEAD_STATUS_HALT)); -+#endif - dQH->size_ioc_int_sts &= temp; - - /* Ensure that updates to the QH will occure before priming. */ -@@ -682,18 +737,32 @@ static struct ep_td_struct *fsl_build_dt - - dtd->td_dma = *dma; - /* Clear reserved field */ -+#ifdef CONFIG_COLDFIRE -+ swap_temp = hc32_to_cpu(dtd->size_ioc_sts); -+#else - swap_temp = cpu_to_le32(dtd->size_ioc_sts); -+#endif - swap_temp &= ~DTD_RESERVED_FIELDS; -+#ifdef CONFIG_COLDFIRE -+ dtd->size_ioc_sts = cpu_to_hc32(swap_temp); -+#else - dtd->size_ioc_sts = cpu_to_le32(swap_temp); -- -+#endif - /* Init all of buffer page pointers */ - swap_temp = (u32) (req->req.dma + req->req.actual); -+#ifdef CONFIG_COLDFIRE -+ dtd->buff_ptr0 = cpu_to_hc32(swap_temp); -+ dtd->buff_ptr1 = cpu_to_hc32(swap_temp + 0x1000); -+ dtd->buff_ptr2 = cpu_to_hc32(swap_temp + 0x2000); -+ dtd->buff_ptr3 = cpu_to_hc32(swap_temp + 0x3000); -+ dtd->buff_ptr4 = cpu_to_hc32(swap_temp + 0x4000); -+#else - dtd->buff_ptr0 = cpu_to_le32(swap_temp); - dtd->buff_ptr1 = cpu_to_le32(swap_temp + 0x1000); - dtd->buff_ptr2 = cpu_to_le32(swap_temp + 0x2000); - dtd->buff_ptr3 = cpu_to_le32(swap_temp + 0x3000); - dtd->buff_ptr4 = cpu_to_le32(swap_temp + 0x4000); -- -+#endif - req->req.actual += *length; - - /* zlp is needed if req->req.zero is set */ -@@ -715,9 +784,11 @@ static struct ep_td_struct *fsl_build_dt - /* Enable interrupt for the last dtd of a request */ - if (*is_last && !req->req.no_interrupt) - swap_temp |= DTD_IOC; -- -+#ifdef CONFIG_COLDFIRE -+ dtd->size_ioc_sts = cpu_to_hc32(swap_temp); -+#else - dtd->size_ioc_sts = cpu_to_le32(swap_temp); -- -+#endif - mb(); - - VDBG("length = %d address= 0x%x", *length, (int)*dma); -@@ -743,16 +814,22 @@ static int fsl_req_to_dtd(struct fsl_req - is_first = 0; - req->head = dtd; - } else { -+#ifdef CONFIG_COLDFIRE -+ last_dtd->next_td_ptr = cpu_to_hc32(dma); -+#else - last_dtd->next_td_ptr = cpu_to_le32(dma); -+#endif - last_dtd->next_td_virt = dtd; - } - last_dtd = dtd; - - req->dtd_count++; - } while (!is_last); -- -+#ifdef CONFIG_COLDFIRE -+ dtd->next_td_ptr = cpu_to_hc32(DTD_NEXT_TERMINATE); -+#else - dtd->next_td_ptr = cpu_to_le32(DTD_NEXT_TERMINATE); -- -+#endif - req->tail = dtd; - - return 0; -@@ -963,7 +1040,39 @@ out: - - return status; - } -+#ifdef CONFIG_COLDFIRE -+static int arcotg_fifo_status(struct usb_ep *_ep) -+{ -+ struct fsl_ep *ep; -+ struct fsl_udc *udc; -+ int size = 0; -+ u32 bitmask; -+ struct ep_queue_head *d_qh; -+ -+ ep = container_of(_ep, struct fsl_ep, ep); -+ if (!_ep || (!ep->desc && ep_index(ep) != 0)) -+ return -ENODEV; -+ -+ udc = (struct fsl_udc *)ep->udc; -+ -+ if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) -+ return -ESHUTDOWN; -+ -+ d_qh = &ep->udc->ep_qh[ep_index(ep) * 2 + ep_is_in(ep)]; -+ -+ bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) : -+ (1 << (ep_index(ep))); -+ -+ if (fsl_readl(&dr_regs->endptstatus) & bitmask) -+ size = (d_qh->size_ioc_int_sts & DTD_PACKET_SIZE) -+ >> DTD_LENGTH_BIT_POS; -+ -+ pr_debug("%s %u\n", __func__, size); -+ return size; -+} -+ - -+#endif - static void fsl_ep_fifo_flush(struct usb_ep *_ep) - { - struct fsl_ep *ep; -@@ -1016,6 +1125,9 @@ static struct usb_ep_ops fsl_ep_ops = { - .dequeue = fsl_ep_dequeue, - - .set_halt = fsl_ep_set_halt, -+#ifdef CONFIG_COLDFIRE -+ .fifo_status = arcotg_fifo_status, -+#endif - .fifo_flush = fsl_ep_fifo_flush, /* flush fifo */ - }; - -@@ -1396,7 +1508,9 @@ static void tripwire_handler(struct fsl_ - { - u32 temp; - struct ep_queue_head *qh; -- -+#ifdef CONFIG_COLDFIRE -+ struct fsl_usb2_platform_data *pdata = udc->pdata; -+#endif - qh = &udc->ep_qh[ep_num * 2 + EP_DIR_OUT]; - - /* Clear bit in ENDPTSETUPSTAT */ -@@ -1410,7 +1524,20 @@ static void tripwire_handler(struct fsl_ - fsl_writel(temp | USB_CMD_SUTW, &dr_regs->usbcmd); - - /* Copy the setup packet to local buffer */ -+#if CONFIG_COLDFIRE -+ if (pdata->le_setup_buf) { -+ u32 *p = (u32 *)buffer_ptr; -+ u32 *s = (u32 *)qh->setup_buffer; -+ -+ /* Convert little endian setup buffer to CPU endian */ -+ *p++ = le32_to_cpu(*s++); -+ *p = le32_to_cpu(*s); -+ } else { -+ memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8); -+ } -+#else - memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8); -+#endif - } while (!(fsl_readl(&dr_regs->usbcmd) & USB_CMD_SUTW)); - - /* Clear Setup Tripwire */ -@@ -1434,19 +1561,19 @@ static int process_ep_req(struct fsl_udc - actual = curr_req->req.length; - - for (j = 0; j < curr_req->dtd_count; j++) { -- remaining_length = (le32_to_cpu(curr_td->size_ioc_sts) -+ remaining_length = (hc32_to_cpu(curr_td->size_ioc_sts) - & DTD_PACKET_SIZE) - >> DTD_LENGTH_BIT_POS; - actual -= remaining_length; - -- if ((errors = le32_to_cpu(curr_td->size_ioc_sts) & -- DTD_ERROR_MASK)) { -+ errors = hc32_to_cpu(curr_td->size_ioc_sts); -+ if (errors & DTD_ERROR_MASK) { - if (errors & DTD_STATUS_HALTED) { - ERR("dTD error %08x QH=%d\n", errors, pipe); - /* Clear the errors and Halt condition */ -- tmp = le32_to_cpu(curr_qh->size_ioc_int_sts); -+ tmp = hc32_to_cpu(curr_qh->size_ioc_int_sts); - tmp &= ~errors; -- curr_qh->size_ioc_int_sts = cpu_to_le32(tmp); -+ curr_qh->size_ioc_int_sts = cpu_to_hc32(tmp); - status = -EPIPE; - /* FIXME: continue with next queued TD? */ - -@@ -1464,7 +1591,7 @@ static int process_ep_req(struct fsl_udc - ERR("Unknown error has occured (0x%x)!\n", - errors); - -- } else if (le32_to_cpu(curr_td->size_ioc_sts) -+ } else if (hc32_to_cpu(curr_td->size_ioc_sts) - & DTD_STATUS_ACTIVE) { - VDBG("Request not complete"); - status = REQ_UNCOMPLETE; -@@ -1552,7 +1679,10 @@ static void dtd_complete_irq(struct fsl_ - static void port_change_irq(struct fsl_udc *udc) - { - u32 speed; -- -+#ifdef CONFIG_COLDFIRE -+ if (udc->bus_reset) -+ udc->bus_reset = 0; -+#endif - /* Bus resetting is finished */ - if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) { - /* Get the speed */ -@@ -1660,6 +1790,10 @@ static void reset_irq(struct fsl_udc *ud - - if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) { - VDBG("Bus reset"); -+#ifdef CONFIG_COLDFIRE -+ /* Bus is reseting */ -+ udc->bus_reset = 1; -+#endif - /* Reset all the queues, include XD, dTD, EP queue - * head and TR Queue */ - reset_queues(udc); -@@ -1793,19 +1927,49 @@ int usb_gadget_probe_driver(struct usb_g - udc_controller->driver = NULL; - goto out; - } -- -+#ifdef CONFIG_COLDFIRE -+ if (udc_controller->transceiver) { -+ /* Suspend the controller until OTG enable it */ -+ udc_controller->stopped = 1; -+ printk(KERN_INFO "Suspend udc for OTG auto detect\n"); -+ -+ /* export udc suspend/resume call to OTG */ -+ udc_controller->gadget.dev.driver->suspend = fsl_udc_suspend; -+ udc_controller->gadget.dev.driver->resume = fsl_udc_resume; -+ -+ /* connect to bus through transceiver */ -+ if (udc_controller->transceiver) { -+ retval = otg_set_peripheral(udc_controller->transceiver, -+ &udc_controller->gadget); -+ if (retval < 0) { -+ ERR("can't bind to transceiver\n"); -+ driver->unbind(&udc_controller->gadget); -+ udc_controller->gadget.dev.driver = 0; -+ udc_controller->driver = 0; -+ return retval; -+ } -+ } -+ } else { -+ /* Enable DR IRQ reg and Set usbcmd reg Run bit */ -+ dr_controller_run(udc_controller); -+ udc_controller->usb_state = USB_STATE_ATTACHED; -+ udc_controller->ep0_state = WAIT_FOR_SETUP; -+ udc_controller->ep0_dir = 0; -+ } -+#else - /* Enable DR IRQ reg and Set usbcmd reg Run bit */ - dr_controller_run(udc_controller); - udc_controller->usb_state = USB_STATE_ATTACHED; - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = 0; -+#endif - printk(KERN_INFO "%s: bind to driver %s\n", - udc_controller->gadget.name, driver->driver.name); - - out: - if (retval) - printk(KERN_WARNING "gadget driver register failed %d\n", -- retval); -+ retval); - return retval; - } - EXPORT_SYMBOL(usb_gadget_probe_driver); -@@ -2239,7 +2403,7 @@ static int __init fsl_udc_probe(struct p - int ret = -ENODEV; - unsigned int i; - u32 dccparams; -- -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - if (strcmp(pdev->name, driver_name)) { - VDBG("Wrong device"); - return -ENODEV; -@@ -2253,6 +2417,24 @@ static int __init fsl_udc_probe(struct p - - spin_lock_init(&udc_controller->lock); - udc_controller->stopped = 1; -+#ifdef CONFIG_COLDFIRE -+ udc_controller->pdata = pdata; -+#endif -+#ifdef CONFIG_USB_OTG -+ /* Memory and interrupt resources will be passed from OTG */ -+ udc_controller->transceiver = otg_get_transceiver(); -+ if (!udc_controller->transceiver) { -+ printk(KERN_ERR "Can't find OTG driver!\n"); -+ ret = -ENODEV; -+ goto err_kfree; -+ } -+ -+ res = otg_get_resources(); -+ if (!res) { -+ DBG("resource not registered!\n"); -+ return -ENODEV; -+ } -+#else - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { -@@ -2266,18 +2448,30 @@ static int __init fsl_udc_probe(struct p - ret = -EBUSY; - goto err_kfree; - } -- -+#endif - dr_regs = ioremap(res->start, resource_size(res)); - if (!dr_regs) { - ret = -ENOMEM; - goto err_release_mem_region; - } -+#ifdef CONFIG_COLDFIRE -+ pdata->regs = (void *)dr_regs; -+ fsl_set_usb_accessors(pdata); -+ -+ /* -+ * do platform specific init: check the clock, grab/config pins, etc. -+ */ -+ if (pdata->init && pdata->init(pdev)) { -+ ret = -ENODEV; -+ goto err_iounmap_noclk; -+ } - -+#else - #ifndef CONFIG_ARCH_MXC - usb_sys_regs = (struct usb_sys_interface *) - ((u32)dr_regs + USB_DR_SYS_OFFSET); - #endif -- -+#endif - /* Initialize USB clocks */ - ret = fsl_udc_clk_init(pdev); - if (ret < 0) -@@ -2293,8 +2487,12 @@ static int __init fsl_udc_probe(struct p - /* Get max device endpoints */ - /* DEN is bidirectional ep number, max_ep doubles the number */ - udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2; -- -+#ifdef CONFIG_USB_OTG -+ res++; -+ udc_controller->irq = res->start; -+#else - udc_controller->irq = platform_get_irq(pdev, 0); -+#endif - if (!udc_controller->irq) { - ret = -ENODEV; - goto err_iounmap; -@@ -2314,11 +2512,17 @@ static int __init fsl_udc_probe(struct p - ret = -ENOMEM; - goto err_free_irq; - } -- -+#ifdef CONFIG_COLDFIRE -+ if (!udc_controller->transceiver) { -+ /* initialize usb hw reg except for regs for EP, -+ * leave usbintr reg untouched */ -+ dr_controller_setup(udc_controller); -+ } -+#else - /* initialize usb hw reg except for regs for EP, - * leave usbintr reg untouched */ - dr_controller_setup(udc_controller); -- -+#endif - fsl_udc_clk_finalize(pdev); - - /* Setup gadget structure */ -@@ -2336,7 +2540,10 @@ static int __init fsl_udc_probe(struct p - ret = device_register(&udc_controller->gadget.dev); - if (ret < 0) - goto err_free_irq; -- -+#ifdef CONFIG_COLDFIRE -+ if (udc_controller->transceiver) -+ udc_controller->gadget.is_otg = 1; -+#endif - /* setup QH and epctrl for ep0 */ - ep0_setup(udc_controller); - -@@ -2392,7 +2599,9 @@ err_kfree: - static int __exit fsl_udc_remove(struct platform_device *pdev) - { - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- -+#ifdef CONFIG_COLDFIRE -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+#endif - DECLARE_COMPLETION(done); - - if (!udc_controller) -@@ -2412,31 +2621,103 @@ static int __exit fsl_udc_remove(struct - dma_pool_destroy(udc_controller->td_pool); - free_irq(udc_controller->irq, udc_controller); - iounmap(dr_regs); -+#ifndef CONFIG_USB_OTG - release_mem_region(res->start, res->end - res->start + 1); -- -+#endif - device_unregister(&udc_controller->gadget.dev); - /* free udc --wait for the release() finished */ - wait_for_completion(&done); -+#ifdef CONFIG_COLDFIRE -+ /* -+ * do platform specific un-initialization: -+ * release iomux pins, etc. -+ */ -+ if (pdata->exit) -+ pdata->exit(pdev); -+ -+#endif -+ return 0; -+} -+#ifdef CONFIG_COLDFIRE -+ -+static int udc_suspend(struct fsl_udc *udc) -+{ -+ u32 mode, usbcmd; -+ -+ mode = fsl_readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_MASK; -+ usbcmd = fsl_readl(&dr_regs->usbcmd); -+ -+ pr_debug("%s(): mode 0x%x stopped %d\n", __func__, mode, udc->stopped); -+ -+ /* -+ * If the controller is already stopped, then this must be a -+ * PM suspend. Remember this fact, so that we will leave the -+ * controller stopped at PM resume time. -+ */ -+ if (udc->stopped) { -+ pr_debug("gadget already stopped, leaving early\n"); -+ udc->already_stopped = 1; -+ return 0; -+ } - -+ if (mode != USB_MODE_CTRL_MODE_DEVICE) { -+ pr_debug("gadget not in device mode, leaving early\n"); -+ return 0; -+ } -+ -+ printk(KERN_INFO "USB Gadget suspended\n"); -+ -+ /* stop the controller */ -+ usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP; -+ fsl_writel(usbcmd, &dr_regs->usbcmd); -+ -+ udc->stopped = 1; - return 0; - } - -+#endif - /*----------------------------------------------------------------- - * Modify Power management attributes - * Used by OTG statemachine to disable gadget temporarily - -----------------------------------------------------------------*/ -+#ifdef CONFIG_COLDFIRE -+static int fsl_udc_suspend(struct device *dev, pm_message_t state) -+#else - static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state) -+#endif - { -+#ifdef CONFIG_COLDFIRE -+ return udc_suspend(udc_controller); -+#else - dr_controller_stop(udc_controller); - return 0; -+#endif - } - - /*----------------------------------------------------------------- - * Invoked on USB resume. May be called in_interrupt. - * Here we start the DR controller and enable the irq - *-----------------------------------------------------------------*/ -+#ifdef CONFIG_COLDFIRE -+static int fsl_udc_resume(struct device *dev) -+#else - static int fsl_udc_resume(struct platform_device *pdev) -+#endif - { -+#ifdef CONFIG_COLDFIRE -+ pr_debug("%s(): stopped %d already_stopped %d\n", __func__, -+ udc_controller->stopped, udc_controller->already_stopped); -+ -+ /* -+ * If the controller was stopped at suspend time, then -+ * don't resume it now. -+ */ -+ if (udc_controller->already_stopped) { -+ udc_controller->already_stopped = 0; -+ pr_debug("gadget was already stopped, leaving early\n"); -+ return 0; -+ } -+#endif - /* Enable DR irq reg and set controller Run */ - if (udc_controller->stopped) { - dr_controller_setup(udc_controller); -@@ -2445,6 +2726,9 @@ static int fsl_udc_resume(struct platfor - udc_controller->usb_state = USB_STATE_ATTACHED; - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = 0; -+ -+ printk(KERN_INFO "USB Gadget resumed\n"); -+ - return 0; - } - -@@ -2455,11 +2739,15 @@ static int fsl_udc_resume(struct platfor - static struct platform_driver udc_driver = { - .remove = __exit_p(fsl_udc_remove), - /* these suspend and resume are not usb suspend and resume */ -+#ifndef CONFIG_COLDFIRE - .suspend = fsl_udc_suspend, - .resume = fsl_udc_resume, -+#endif - .driver = { - .name = (char *)driver_name, - .owner = THIS_MODULE, -+ .suspend = fsl_udc_suspend, -+ .resume = fsl_udc_resume, - }, - }; - ---- a/drivers/usb/gadget/fsl_usb2_udc.h -+++ b/drivers/usb/gadget/fsl_usb2_udc.h -@@ -461,6 +461,7 @@ struct fsl_ep { - struct fsl_udc { - struct usb_gadget gadget; - struct usb_gadget_driver *driver; -+ struct fsl_usb2_platform_data *pdata; - struct completion *done; /* to make sure release() is done */ - struct fsl_ep *eps; - unsigned int max_ep; -@@ -473,6 +474,7 @@ struct fsl_udc { - unsigned vbus_active:1; - unsigned stopped:1; - unsigned remote_wakeup:1; -+ unsigned already_stopped:1; - - struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */ - struct fsl_req *status_req; /* ep0 status request */ -@@ -482,6 +484,7 @@ struct fsl_udc { - size_t ep_qh_size; /* size after alignment adjustment*/ - dma_addr_t ep_qh_dma; /* dma address of QH */ - -+ u32 bus_reset; /* Device is bus reseting */ - u32 max_pipes; /* Device max pipes */ - u32 resume_state; /* USB state to resume */ - u32 usb_state; /* USB current state */ -@@ -581,4 +584,17 @@ static inline void fsl_udc_clk_release(v - } - #endif - -+#ifdef CONFIG_COLDFIRE -+#include <asm/mcfsim.h> -+#include <asm/fsl_usb_io.h> -+#include <asm/fsl_usb_gadget.h> -+#include <asm/cf_cacheflush.h> -+ -+extern struct resource *otg_get_resources(void); -+#ifdef CONFIG_USB_M5441X_MAX3353_FSLS -+extern int max3353_read_id_pin(void); -+#endif -+ -+#endif -+ - #endif ---- a/drivers/usb/gadget/serial.c -+++ b/drivers/usb/gadget/serial.c -@@ -4,6 +4,7 @@ - * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) - * Copyright (C) 2008 by David Brownell - * Copyright (C) 2008 by Nokia Corporation -+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. - * - * This software is distributed under the terms of the GNU General - * Public License ("GPL") as published by the Free Software Foundation, -@@ -134,7 +135,44 @@ MODULE_PARM_DESC(use_obex, "Use CDC OBEX - static unsigned n_ports = 1; - module_param(n_ports, uint, 0); - MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); -- -+/*-------------------------------------------------------------------------*/ -+#if 0 -+static void gs_setup_complete_set_line_coding(struct usb_ep *ep, -+ struct usb_request *req) -+{ -+ struct gs_dev *dev = ep->driver_data; -+ struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ -+ -+ switch (req->status) { -+ case 0: -+ /* normal completion */ -+ if (req->actual != sizeof(port->port_line_coding)) -+ usb_ep_set_halt(ep); -+ else if (port) { -+ struct usb_cdc_line_coding *value = req->buf; -+ -+ /* REVISIT: we currently just remember this data. -+ * If we change that, (a) validate it first, then -+ * (b) update whatever hardware needs updating. -+ */ -+ spin_lock(&port->port_lock); -+ port->port_line_coding = *value; -+ spin_unlock(&port->port_lock); -+ } -+ break; -+ -+ case -ESHUTDOWN: -+ /* disconnect */ -+ gs_free_req(ep, req); -+ break; -+ -+ default: -+ /* unexpected */ -+ break; -+ } -+ return; -+} -+#endif - /*-------------------------------------------------------------------------*/ - - static int __init serial_bind_config(struct usb_configuration *c) ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -95,13 +95,14 @@ config USB_EHCI_BIG_ENDIAN_MMIO - bool - depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \ - ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ -- PPC_MPC512x || CPU_CAVIUM_OCTEON) -+ PPC_MPC512x || CPU_CAVIUM_OCTEON || \ -+ COLDFIRE) - default y - - config USB_EHCI_BIG_ENDIAN_DESC - bool - depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ -- PPC_MPC512x) -+ PPC_MPC512x || COLDFIRE) - default y - - config XPS_USB_HCD_XILINX -@@ -120,12 +121,77 @@ config USB_FSL_MPH_DR_OF - - config USB_EHCI_FSL - bool "Support for Freescale on-chip EHCI USB controller" -- depends on USB_EHCI_HCD && FSL_SOC -+ depends on USB_EHCI_HCD && (FSL_SOC || COLDFIRE) - select USB_EHCI_ROOT_HUB_TT - select USB_FSL_MPH_DR_OF if OF - ---help--- - Variation of ARC USB block used in some Freescale chips. - -+config USB_M5441X_PLLCLK -+ bool "ColdFire USB module use PLL clock source" -+ depends on M5441X -+ ---help--- -+ Select USB clock source from PLL instead external USBCLKIN, -+ to generate the exact USB module 60MHZ clock, the system clock -+ must be shrink to match the divide requirement which is down -+ in u-boot. -+ -+config USB_M5441X_H1 -+ bool "ColdFire EHCI USB Host module support" -+ depends on USB_EHCI_HCD && M5441X -+ ---help--- -+ Some ColdFire platform have two USB controllers, one is HOST module, -+ the other is OTG module, this config select the HOST module support. -+ -+choice -+ prompt "Selcet ColdFire HOST module transceiver" -+ depends on USB_M5441X_H1 -+ default USB_M5441X_H1_FSLS -+ -+config USB_M5441X_H1_FSLS -+ bool "on-chip (FS/LS only)" -+ depends on M5441X -+ ---help--- -+ Enable support for the on-chip FS/LS transceiver. -+endchoice -+ -+choice -+ prompt "Select ColdiFire OTG module transceiver" -+ depends on M5445X || M5441X -+ default USB_M5445X_ULPI if M5445X -+ default USB_M5441X_ULPI if M5441X -+ -+config USB_M5445X_ULPI -+ bool "External ULPI" -+ depends on M5445X -+ ---help--- -+ Enable support for the external HS ULPI transceiver. -+ -+config USB_M5445X_FSLS -+ bool "On-chip (FL/LS only)" -+ depends on M54455EVB -+ ---help--- -+ Enable support for the on-chip FL/LS transceiver. -+ -+config USB_M5441X_ULPI -+ bool "External ULPI" -+ depends on M5441X -+ ---help--- -+ Enable support for the external HS ULPI transceiver. -+ -+config USB_M5441X_FSLS -+ bool "On-chip (FL/LS only)" -+ depends on M54418EVB -+ ---help--- -+ Enable support for the on-chip FL/LS transceiver. -+ -+config USB_M5441X_MAX3353_FSLS -+ bool "MAX3353 chip charge pump to on-chip (FS/LS only)" -+ depends on M54418EVB -+ ---help--- -+ Max3353 provides charge pump for SER1 board on m54418 platform. -+endchoice -+ - config USB_EHCI_MXC - bool "Support for Freescale on-chip EHCI USB controller" - depends on USB_EHCI_HCD && ARCH_MXC ---- a/drivers/usb/host/ehci-fsl.c -+++ b/drivers/usb/host/ehci-fsl.c -@@ -22,16 +22,21 @@ - * Jerry Huang <Chang-Ming.Huang@freescale.com> and - * Anton Vorontsov <avorontsov@ru.mvista.com>. - */ -- - #include <linux/kernel.h> - #include <linux/types.h> - #include <linux/delay.h> - #include <linux/pm.h> - #include <linux/platform_device.h> - #include <linux/fsl_devices.h> -- -+#include <linux/usb/otg.h> - #include "ehci-fsl.h" - -+#ifdef DEBUG -+#define DBG(X...) printk(X) -+#else -+#define DBG(X...) -+#endif -+ - /* configure so an HC device and id are always provided */ - /* always called with process context; sleeping is OK */ - -@@ -75,7 +80,27 @@ static int usb_hcd_fsl_probe(const struc - dev_name(&pdev->dev)); - return -ENODEV; - } -- -+ hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); -+ if (!hcd) { -+ retval = -ENOMEM; -+ goto err1; -+ } -+#ifdef CONFIG_USB_OTG -+ if (pdata->operating_mode == FSL_USB2_DR_OTG) { -+ res = otg_get_resources(); -+ if (!res) { -+ dev_err(&pdev->dev, -+ "Found HC with no IRQ. Check %s setup!\n", -+ dev_name(&pdev->dev)); -+ return -ENODEV; -+ goto err2; -+ } -+ irq = res[1].start; -+ hcd->rsrc_start = res[0].start; -+ hcd->rsrc_len = res[0].end - res[0].start + 1; -+ } else -+#endif -+ { - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(&pdev->dev, -@@ -85,12 +110,6 @@ static int usb_hcd_fsl_probe(const struc - } - irq = res->start; - -- hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); -- if (!hcd) { -- retval = -ENOMEM; -- goto err1; -- } -- - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, -@@ -101,12 +120,15 @@ static int usb_hcd_fsl_probe(const struc - } - hcd->rsrc_start = res->start; - hcd->rsrc_len = res->end - res->start + 1; -+#ifndef CONFIG_USB_OTG - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - retval = -EBUSY; - goto err2; - } -+#endif -+ } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - - if (hcd->regs == NULL) { -@@ -124,22 +146,56 @@ static int usb_hcd_fsl_probe(const struc - retval = -ENODEV; - goto err3; - } -- -+#ifndef CONFIG_COLDFIRE - /* Enable USB controller, 83xx or 8536 */ - if (pdata->have_sysif_regs) - setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4); -- -+#endif - /* Don't need to set host mode here. It will be done by tdi_reset() */ -- -+#ifdef CONFIG_COLDFIRE -+ fsl_platform_set_host_mode(hcd); -+ hcd->power_budget = pdata->power_budget; -+#endif - retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); - if (retval != 0) - goto err4; -+#ifdef CONFIG_COLDFIRE -+ fsl_platform_set_vbus_power(pdata, 1); -+#endif -+#ifdef CONFIG_USB_OTG -+ if (pdata->operating_mode == FSL_USB2_DR_OTG) { -+ struct ehci_hcd *ehci = hcd_to_ehci(hcd); -+ -+ DBG("pdev=0x%p hcd=0x%p ehci=0x%p\n", pdev, hcd, ehci); -+ -+ ehci->transceiver = otg_get_transceiver(); -+ DBG("ehci->transceiver=0x%p\n", ehci->transceiver); -+ -+ if (ehci->transceiver) { -+ retval = otg_set_host(ehci->transceiver, -+ &ehci_to_hcd(ehci)->self); -+ if (retval) { -+ printk(KERN_INFO "otg transceiver set host failed\n"); -+ if (ehci->transceiver) -+ put_device(ehci->transceiver->dev); -+ goto err4; -+ } -+ } else { -+ printk(KERN_ERR "can't find transceiver\n"); -+ retval = -ENODEV; -+ goto err4; -+ } -+ } -+#endif -+ - return retval; - - err4: - iounmap(hcd->regs); - err3: -+#ifndef CONFIG_USB_OTG - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -+#endif - err2: - usb_put_hcd(hcd); - err1: -@@ -164,9 +220,24 @@ static void usb_hcd_fsl_remove(struct us - struct platform_device *pdev) - { - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+#ifdef CONFIG_COLDFIRE -+ struct ehci_hcd *ehci = hcd_to_ehci(hcd); - -+ /* DDD shouldn't we turn off the power here? */ -+ fsl_platform_set_vbus_power(pdata, 0); -+ -+ if (ehci->transceiver) { -+ (void)otg_set_host(ehci->transceiver, 0); -+ put_device(ehci->transceiver->dev); -+ } else { -+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -+ } -+ -+ -+#endif - usb_remove_hcd(hcd); - -+ usb_put_hcd(hcd); - /* - * do platform specific un-initialization: - * release iomux pins, disable clock, etc. -@@ -174,8 +245,6 @@ static void usb_hcd_fsl_remove(struct us - if (pdata->exit) - pdata->exit(pdev); - iounmap(hcd->regs); -- release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -- usb_put_hcd(hcd); - } - - static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, -@@ -238,7 +307,7 @@ static void ehci_fsl_usb_setup(struct eh - if ((pdata->operating_mode == FSL_USB2_DR_HOST) || - (pdata->operating_mode == FSL_USB2_DR_OTG)) - ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); -- -+#ifndef CONFIG_COLDFIRE - if (pdata->operating_mode == FSL_USB2_MPH_HOST) { - unsigned int chip, rev, svr; - -@@ -255,7 +324,7 @@ static void ehci_fsl_usb_setup(struct eh - if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) - ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1); - } -- -+#endif - if (pdata->have_sysif_regs) { - #ifdef CONFIG_PPC_85xx - out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); -@@ -271,7 +340,11 @@ static void ehci_fsl_usb_setup(struct eh - /* called after powerup, by probe or system-pm "wakeup" */ - static int ehci_fsl_reinit(struct ehci_hcd *ehci) - { -+#ifdef CONFIG_COLDFIRE -+ fsl_platform_usb_setup(ehci); -+#else - ehci_fsl_usb_setup(ehci); -+#endif - ehci_port_power(ehci, 0); - - return 0; -@@ -334,7 +407,6 @@ static struct ehci_fsl *hcd_to_ehci_fsl( - - return container_of(ehci, struct ehci_fsl, ehci); - } -- - static int ehci_fsl_drv_suspend(struct device *dev) - { - struct usb_hcd *hcd = dev_get_drvdata(dev); -@@ -371,7 +443,6 @@ static int ehci_fsl_drv_resume(struct de - - return 0; - } -- - static int ehci_fsl_drv_restore(struct device *dev) - { - struct usb_hcd *hcd = dev_get_drvdata(dev); -@@ -387,6 +458,144 @@ static struct dev_pm_ops ehci_fsl_pm_ops - }; - - #define EHCI_FSL_PM_OPS (&ehci_fsl_pm_ops) -+ -+/* suspend/resume, section 4.3 */ -+ -+/* These routines rely on the bus (pci, platform, etc) -+ * to handle powerdown and wakeup, and currently also on -+ * transceivers that don't need any software attention to set up -+ * the right sort of wakeup. -+ * -+ * They're also used for turning on/off the port when doing OTG. -+ */ -+static int ehci_fsl_suspend(struct device *dev, -+ pm_message_t message) -+{ -+ struct usb_hcd *hcd = dev_get_drvdata(dev); -+ struct ehci_hcd *ehci = hcd_to_ehci(hcd); -+ u32 tmp; -+ struct fsl_usb2_platform_data *pdata = dev->platform_data; -+ -+#ifdef DEBUG -+ u32 mode = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBMODE); -+ mode &= USBMODE_CM_MASK; -+ tmp = ehci_readl(ehci, hcd->regs + 0x140); /* usbcmd */ -+ -+ DBG(KERN_DEBUG "%s('%s'): suspend=%d already_suspended=%d " -+ "mode=%d usbcmd %08x\n", __func__, pdata->name, -+ pdata->suspended, pdata->already_suspended, mode, tmp); -+#endif -+ /* -+ * If the controller is already suspended, then this must be a -+ * PM suspend. Remember this fact, so that we will leave the -+ * controller suspended at PM resume time. -+ */ -+ if (pdata->suspended) { -+ pr_debug("%s: already suspended, leaving early\n", __func__); -+ pdata->already_suspended = 1; -+ return 0; -+ } -+ -+ pr_debug("%s: suspending...\n", __func__); -+ -+ DBG(KERN_INFO "USB Host suspended\n"); -+ -+ hcd->state = HC_STATE_SUSPENDED; -+ dev->power.power_state = PMSG_SUSPEND; -+ -+ /* ignore non-host interrupts */ -+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); -+ -+ /* stop the controller */ -+ tmp = ehci_readl(ehci, &ehci->regs->command); -+ tmp &= ~CMD_RUN; -+ ehci_writel(ehci, tmp, &ehci->regs->command); -+ -+ /* save EHCI registers */ -+ pdata->pm_command = ehci_readl(ehci, &ehci->regs->command); -+ pdata->pm_command &= ~CMD_RUN; -+ pdata->pm_status = ehci_readl(ehci, &ehci->regs->status); -+ pdata->pm_intr_enable = ehci_readl(ehci, &ehci->regs->intr_enable); -+ pdata->pm_frame_index = ehci_readl(ehci, &ehci->regs->frame_index); -+ pdata->pm_segment = ehci_readl(ehci, &ehci->regs->segment); -+ pdata->pm_frame_list = ehci_readl(ehci, &ehci->regs->frame_list); -+ pdata->pm_async_next = ehci_readl(ehci, &ehci->regs->async_next); -+ pdata->pm_configured_flag = -+ ehci_readl(ehci, &ehci->regs->configured_flag); -+ pdata->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]); -+ -+ /* clear the W1C bits */ -+ pdata->pm_portsc &= cpu_to_hc32(ehci, ~PORT_RWC_BITS); -+ -+ pdata->suspended = 1; -+#if 0 -+ /* clear PP to cut power to the port */ -+ tmp = ehci_readl(ehci, &ehci->regs->port_status[0]); -+ tmp &= ~PORT_POWER; -+ ehci_writel(ehci, tmp, &ehci->regs->port_status[0]); -+#endif -+ return 0; -+} -+ -+static int ehci_fsl_resume(struct device *dev) -+{ -+ struct usb_hcd *hcd = dev_get_drvdata(dev); -+ struct ehci_hcd *ehci = hcd_to_ehci(hcd); -+ u32 tmp; -+ struct fsl_usb2_platform_data *pdata = dev->platform_data; -+ -+ pr_debug("%s('%s'): suspend=%d already_suspended=%d\n", __func__, -+ pdata->name, pdata->suspended, pdata->already_suspended); -+ -+ /* -+ * If the controller was already suspended at suspend time, -+ * then don't resume it now. -+ */ -+ if (pdata->already_suspended) { -+ pr_debug("already suspended, leaving early\n"); -+ pdata->already_suspended = 0; -+ return 0; -+ } -+ -+ if (!pdata->suspended) { -+ pr_debug("not suspended, leaving early\n"); -+ return 0; -+ } -+ -+ DBG(KERN_INFO "USB Host resumed\n"); -+ -+ pdata->suspended = 0; -+ -+ pr_debug("%s resuming...\n", __func__); -+ -+ /* set host mode */ -+ fsl_platform_set_host_mode(hcd); -+ -+ -+ /* restore EHCI registers */ -+ ehci_writel(ehci, pdata->pm_command, &ehci->regs->command); -+ ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable); -+ ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index); -+ ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment); -+ ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list); -+ ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next); -+ ehci_writel(ehci, pdata->pm_configured_flag, -+ &ehci->regs->configured_flag); -+ ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]); -+ -+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); -+ hcd->state = HC_STATE_RUNNING; -+ dev->power.power_state = PMSG_ON; -+ -+ tmp = ehci_readl(ehci, &ehci->regs->command); -+ tmp |= CMD_RUN; -+ ehci_writel(ehci, tmp, &ehci->regs->command); -+ -+ usb_hcd_resume_root_hub(hcd); -+ -+ return 0; -+} -+ - #else - #define EHCI_FSL_PM_OPS NULL - #endif /* CONFIG_PM */ -@@ -431,7 +640,11 @@ static const struct hc_driver ehci_fsl_h - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, -+#ifndef CONFIG_COLDFIRE - .port_handed_over = ehci_port_handed_over, -+#else -+ .start_port_reset = ehci_start_port_reset, -+#endif - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, - }; -@@ -460,8 +673,16 @@ static struct platform_driver ehci_fsl_d - .probe = ehci_fsl_drv_probe, - .remove = ehci_fsl_drv_remove, - .shutdown = usb_hcd_platform_shutdown, -+#ifdef CONFIG_PM -+#ifndef CONFIG_COLDFIRE -+ .suspend = ehci_fsl_suspend, -+ .resume = ehci_fsl_resume, -+#endif -+#endif - .driver = { - .name = "fsl-ehci", - .pm = EHCI_FSL_PM_OPS, -+ .suspend = ehci_fsl_suspend, -+ .resume = ehci_fsl_resume, - }, - }; ---- a/drivers/usb/host/ehci-fsl.h -+++ b/drivers/usb/host/ehci-fsl.h -@@ -42,4 +42,11 @@ - #define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */ - #define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */ - #define SNOOP_SIZE_2GB 0x1e -+ -+#ifdef CONFIG_COLDFIRE -+#define FSL_SOC_USB_USBMODE 0x1a8 -+ -+#include <asm/fsl_usb_platform.h> -+#include <asm/fsl_usb_io.h> -+#endif - #endif /* _EHCI_FSL_H */ ---- a/drivers/usb/host/ehci-hub.c -+++ b/drivers/usb/host/ehci-hub.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2001-2004 by David Brownell -+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. - * - * 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 -@@ -41,6 +42,39 @@ static int ehci_hub_control( - u16 wLength - ); - -+#ifdef CONFIG_COLDFIRE -+ -+#ifdef CONFIG_USB_OTG -+static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port) -+{ -+ struct ehci_hcd *ehci = hcd_to_ehci(hcd); -+ u32 status; -+ -+ if (!port) -+ return -EINVAL; -+ port--; -+ -+ /* start port reset before HNP protocol time out */ -+ status = readl(&ehci->regs->port_status[port]); -+ if (!(status & PORT_CONNECT)) -+ return -ENODEV; -+ -+ /* khubd will finish the reset later */ -+ if (ehci_is_TDI(ehci)) -+ writel(PORT_RESET | (status & ~(PORT_CSC | PORT_PEC -+ | PORT_OCC)), &ehci->regs->port_status[port]); -+ else -+ writel(PORT_RESET, &ehci->regs->port_status[port]); -+ -+ return 0; -+} -+#else -+static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port) -+{ -+ return 0; -+} -+#endif /* CONFIG_USB_OTG */ -+#endif - /* After a power loss, ports that were owned by the companion must be - * reset so that the companion can still own them. - */ ---- a/drivers/usb/host/ehci.h -+++ b/drivers/usb/host/ehci.h -@@ -1,6 +1,7 @@ - /* - * Copyright (c) 2001-2002 by David Brownell -- * -+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * - * 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 -@@ -147,7 +148,9 @@ struct ehci_hcd { /* one per controlle - unsigned has_lpm:1; /* support link power management */ - unsigned has_ppcd:1; /* support per-port change bits */ - u8 sbrn; /* packed release number */ -- -+#if defined(CONFIG_COLDFIRE) -+ struct otg_transceiver *transceiver; -+#endif - /* irq statistics */ - #ifdef EHCI_STATS - struct ehci_stats stats; -@@ -617,6 +620,54 @@ ehci_port_speed(struct ehci_hcd *ehci, u - #define writel_be(val, addr) __raw_writel(val, (__force unsigned *)addr) - #endif - -+#if defined(CONFIG_COLDFIRE) -+ -+#if defined(CONFIG_MMU) -+#include <asm/fsl_usb_io.h> -+/* -+ * Sorry, include/asm-m68k/io.h is messed up. It will give you a -+ * BE readl or a LE readl depending on whether or not CONFIG_PCI is set. -+ * how broken is that? Do the right thing here. -+ */ -+#undef readl -+#undef writel -+ -+#define readl(addr) in_le32((__force unsigned *)(addr)) -+#define writel(val, addr) out_le32((__force unsigned *)(addr), (val)) -+ -+#define readl_be(addr) in_be32((__force unsigned *)(addr)) -+#define writel_be(val, addr) out_be32((__force unsigned *)(addr), (val)) -+ -+#else /* !CONFIG_MMU */ -+ -+#define readl_be(addr) \ -+ ({u32 __v = (*(__force volatile u32 *)addr); __v; }) -+#define writel_be(val, addr) \ -+ (void)((*(__force volatile u32 *)addr) = val) -+ -+#ifndef in_be32 -+#define in_be32(addr) \ -+ ({ u32 __v = (*(__force volatile u32 *)(addr)); __v; }) -+#endif -+ -+#ifndef in_le32 -+#define in_le32(addr) \ -+ ({ u32 __v = le32_to_cpu(*(__force volatile __le32 *)(addr)); __v; }) -+#endif -+ -+#ifndef out_be32 -+#define out_be32(addr, l) (void)((*(__force volatile u32 *)(addr)) = (l)) -+#endif -+ -+#ifndef out_le32 -+#define out_le32(addr, l) \ -+ (void)((*(__force volatile __le32 *)(addr)) = cpu_to_le32(l)) -+#endif -+ -+#endif -+ -+#endif /* CONFIG_COLDFIRE */ -+ - static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, - __u32 __iomem * regs) - { ---- a/drivers/usb/otg/Makefile -+++ b/drivers/usb/otg/Makefile -@@ -18,3 +18,10 @@ obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-x - obj-$(CONFIG_USB_ULPI) += ulpi.o - obj-$(CONFIG_USB_MSM_OTG_72K) += msm72k_otg.o - obj-$(CONFIG_AB8500_USB) += ab8500-usb.o -+ -+obj-$(CONFIG_USB_OTG) += usb.o -+fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o -+#ifneq ($(CONFIG_USB_OTG),) -+ifneq ($(CONFIG_USB_OTG),) -+obj-m += fsl_usb2_otg.o -+endif ---- /dev/null -+++ b/drivers/usb/otg/fsl_otg.c -@@ -0,0 +1,1212 @@ -+/* -+ * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * Author: Li Yang <LeoLi@freescale.com> -+ * Jerry Huang <Chang-Ming.Huang@freescale.com> -+ * -+ * Initialization based on code from Shlomi Gridish. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <linux/module.h> -+#include <linux/moduleparam.h> -+#include <linux/kernel.h> -+#include <linux/delay.h> -+#include <linux/ioport.h> -+#include <linux/sched.h> -+#include <linux/slab.h> -+#include <linux/smp_lock.h> -+#include <linux/proc_fs.h> -+#include <linux/errno.h> -+#include <linux/init.h> -+#include <linux/reboot.h> -+#include <linux/timer.h> -+#include <linux/list.h> -+#include <linux/usb.h> -+#include <linux/device.h> -+#include <linux/usb/ch9.h> -+#include <linux/usb/gadget.h> -+#include <linux/workqueue.h> -+#include <linux/time.h> -+#include <linux/fsl_devices.h> -+#include <linux/platform_device.h> -+ -+#include <linux/io.h> -+#include <asm/irq.h> -+#include <asm/system.h> -+#include <asm/byteorder.h> -+#include <linux/uaccess.h> -+#include <asm/unaligned.h> -+ -+#include "fsl_otg.h" -+ -+/* -+#undef DBG -+#undef VDBG -+#define DBG(x...) printk(x) -+#define VDBG(x...) printk(x) -+*/ -+ -+#define CONFIG_USB_OTG_DEBUG_FILES -+#define DRIVER_VERSION "$Revision: 1.55 $" -+#define DRIVER_AUTHOR "Jerry Huang/Li Yang" -+#define DRIVER_DESC "Freescale USB OTG Driver" -+#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC -+ -+MODULE_DESCRIPTION("Freescale USB OTG Transceiver Driver"); -+ -+static const char driver_name[] = "fsl-usb2-otg"; -+ -+const pm_message_t otg_suspend_state = { -+ .event = 1, -+}; -+ -+#define HA_DATA_PULSE 1 -+ -+volatile static struct usb_dr_mmap *usb_dr_regs; -+static struct fsl_otg *fsl_otg_dev; -+static int srp_wait_done; -+ -+/* FSM timers */ -+struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr, -+ *b_ase0_brst_tmr, *b_se0_srp_tmr; -+ -+/* Driver specific timers */ -+struct fsl_otg_timer *b_data_pulse_tmr, *b_vbus_pulse_tmr, *b_srp_fail_tmr, -+ *b_srp_wait_tmr, *a_wait_enum_tmr; -+ -+static struct list_head active_timers; -+ -+static struct fsl_otg_config fsl_otg_initdata = { -+ .otg_port = 1, -+}; -+ -+/* Routines to access transceiver ULPI registers */ -+u8 view_ulpi(u8 addr) -+{ -+ u32 temp; -+ -+ temp = 0x40000000 | (addr << 16); -+ temp = cpu_to_le32(temp); -+ fsl_writel(temp, &usb_dr_regs->ulpiview); -+ udelay(1000); -+ while (temp & 0x40) -+ temp = fsl_readl(&usb_dr_regs->ulpiview); -+ return (le32_to_cpu(temp) & 0x0000ff00) >> 8; -+} -+ -+int write_ulpi(u8 addr, u8 data) -+{ -+ u32 temp; -+ -+ temp = 0x60000000 | (addr << 16) | data; -+ temp = cpu_to_hc32(temp); -+ fsl_writel(temp, &usb_dr_regs->ulpiview); -+ return 0; -+} -+ -+/* -------------------------------------------------------------*/ -+/* Operations that will be called from OTG Finite State Machine */ -+ -+/* Charge vbus for vbus pulsing in SRP */ -+void fsl_otg_chrg_vbus(int on) -+{ -+ u32 tmp; -+ -+ tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; -+ -+ if (on) -+ /* stop discharging, start charging */ -+ tmp = (tmp & ~OTGSC_CTRL_VBUS_DISCHARGE) | -+ OTGSC_CTRL_VBUS_CHARGE; -+ else -+ /* stop charging */ -+ tmp &= ~OTGSC_CTRL_VBUS_CHARGE; -+ -+ fsl_writel(tmp, &usb_dr_regs->otgsc); -+} -+ -+/* Discharge vbus through a resistor to ground */ -+void fsl_otg_dischrg_vbus(int on) -+{ -+ u32 tmp; -+ -+ tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; -+ -+ if (on) -+ /* stop charging, start discharging */ -+ tmp = (tmp & ~OTGSC_CTRL_VBUS_CHARGE) | -+ OTGSC_CTRL_VBUS_DISCHARGE; -+ else -+ /* stop discharging */ -+ tmp &= ~OTGSC_CTRL_VBUS_DISCHARGE; -+ -+ fsl_writel(tmp, &usb_dr_regs->otgsc); -+} -+ -+/* A-device driver vbus, controlled through PP bit in PORTSC */ -+void fsl_otg_drv_vbus(int on) -+{ -+/* if (on) -+ usb_dr_regs->portsc = -+ cpu_to_le32((le32_to_cpu(usb_dr_regs->portsc) & -+ ~PORTSC_W1C_BITS) | PORTSC_PORT_POWER); -+ else -+ usb_dr_regs->portsc = -+ cpu_to_le32(le32_to_cpu(usb_dr_regs->portsc) & -+ ~PORTSC_W1C_BITS & ~PORTSC_PORT_POWER); -+*/ -+} -+ -+/* -+ * Pull-up D+, signalling connect by periperal. Also used in -+ * data-line pulsing in SRP -+ */ -+void fsl_otg_loc_conn(int on) -+{ -+ u32 tmp; -+ -+ tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; -+ -+ if (on) -+ tmp |= OTGSC_CTRL_DATA_PULSING; -+ else -+ tmp &= ~OTGSC_CTRL_DATA_PULSING; -+ -+ fsl_writel(tmp, &usb_dr_regs->otgsc); -+} -+ -+/* Generate SOF by host. This is controlled through suspend/resume the -+ * port. In host mode, controller will automatically send SOF. -+ * Suspend will block the data on the port. -+ */ -+void fsl_otg_loc_sof(int on) -+{ -+ u32 tmp; -+ -+ tmp = fsl_readl(&fsl_otg_dev->dr_mem_map->portsc) & ~PORTSC_W1C_BITS; -+ if (on) -+ tmp |= PORTSC_PORT_FORCE_RESUME; -+ else -+ tmp |= PORTSC_PORT_SUSPEND; -+ -+ fsl_writel(tmp, &fsl_otg_dev->dr_mem_map->portsc); -+ -+} -+ -+/* Start SRP pulsing by data-line pulsing, followed with v-bus pulsing. */ -+void fsl_otg_start_pulse(void) -+{ -+ u32 tmp; -+ -+ srp_wait_done = 0; -+#ifdef HA_DATA_PULSE -+ tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; -+ tmp |= OTGSC_HA_DATA_PULSE; -+ fsl_writel(tmp, &usb_dr_regs->otgsc); -+#else -+ fsl_otg_loc_conn(1); -+#endif -+ -+ fsl_otg_add_timer(b_data_pulse_tmr); -+} -+ -+void fsl_otg_pulse_vbus(void); -+ -+void b_data_pulse_end(unsigned long foo) -+{ -+#ifdef HA_DATA_PULSE -+#else -+ fsl_otg_loc_conn(0); -+#endif -+ -+ /* Do VBUS pulse after data pulse */ -+ fsl_otg_pulse_vbus(); -+} -+ -+void fsl_otg_pulse_vbus(void) -+{ -+ srp_wait_done = 0; -+ fsl_otg_chrg_vbus(1); -+ /* start the timer to end vbus charge */ -+ fsl_otg_add_timer(b_vbus_pulse_tmr); -+} -+ -+void b_vbus_pulse_end(unsigned long foo) -+{ -+ fsl_otg_chrg_vbus(0); -+ -+ /* As USB3300 using the same a_sess_vld and b_sess_vld voltage -+ * we need to discharge the bus for a while to distinguish -+ * residual voltage of vbus pulsing and A device pull up */ -+ fsl_otg_dischrg_vbus(1); -+ fsl_otg_add_timer(b_srp_wait_tmr); -+} -+ -+void b_srp_end(unsigned long foo) -+{ -+ fsl_otg_dischrg_vbus(0); -+ srp_wait_done = 1; -+ -+ if ((fsl_otg_dev->otg.state == OTG_STATE_B_SRP_INIT) && -+ fsl_otg_dev->fsm.b_sess_vld) -+ fsl_otg_dev->fsm.b_srp_done = 1; -+} -+ -+/* Workaround for a_host suspending too fast. When a_bus_req=0, -+ * a_host will start by SRP. It needs to set b_hnp_enable before -+ * actually suspending to start HNP -+ */ -+void a_wait_enum(unsigned long foo) -+{ -+ VDBG("a_wait_enum timeout\n"); -+ if (!fsl_otg_dev->otg.host->b_hnp_enable) -+ fsl_otg_add_timer(a_wait_enum_tmr); -+ else -+ otg_statemachine(&fsl_otg_dev->fsm); -+} -+ -+/* ------------------------------------------------------*/ -+ -+/* The timeout callback function to set time out bit */ -+void set_tmout(unsigned long indicator) -+{ -+ *(int *)indicator = 1; -+} -+ -+/* Initialize timers */ -+int fsl_otg_init_timers(struct otg_fsm *fsm) -+{ -+ /* FSM used timers */ -+ a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, -+ (unsigned long)&fsm->a_wait_vrise_tmout); -+ if (a_wait_vrise_tmr == NULL) -+ return -ENOMEM; -+ -+ a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON, -+ (unsigned long)&fsm->a_wait_bcon_tmout); -+ if (a_wait_bcon_tmr == NULL) -+ return -ENOMEM; -+ -+ a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, -+ (unsigned long)&fsm->a_aidl_bdis_tmout); -+ if (a_aidl_bdis_tmr == NULL) -+ return -ENOMEM; -+ -+ b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST, -+ (unsigned long)&fsm->b_ase0_brst_tmout); -+ if (b_ase0_brst_tmr == NULL) -+ return -ENOMEM; -+ -+ b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, -+ (unsigned long)&fsm->b_se0_srp); -+ if (b_se0_srp_tmr == NULL) -+ return -ENOMEM; -+ -+ b_srp_fail_tmr = otg_timer_initializer(&set_tmout, TB_SRP_FAIL, -+ (unsigned long)&fsm->b_srp_done); -+ if (b_srp_fail_tmr == NULL) -+ return -ENOMEM; -+ -+ a_wait_enum_tmr = otg_timer_initializer(&a_wait_enum, 10, -+ (unsigned long)&fsm); -+ if (a_wait_enum_tmr == NULL) -+ return -ENOMEM; -+ -+ /* device driver used timers */ -+ b_srp_wait_tmr = otg_timer_initializer(&b_srp_end, TB_SRP_WAIT, 0); -+ if (b_srp_wait_tmr == NULL) -+ return -ENOMEM; -+ -+ b_data_pulse_tmr = otg_timer_initializer(&b_data_pulse_end, -+ TB_DATA_PLS, 0); -+ if (b_data_pulse_tmr == NULL) -+ return -ENOMEM; -+ -+ b_vbus_pulse_tmr = otg_timer_initializer(&b_vbus_pulse_end, -+ TB_VBUS_PLS, 0); -+ if (b_vbus_pulse_tmr == NULL) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+/* Uninitialize timers */ -+void fsl_otg_uninit_timers(void) -+{ -+ /* FSM used timers */ -+ if (a_wait_vrise_tmr != NULL) -+ kfree(a_wait_vrise_tmr); -+ if (a_wait_bcon_tmr != NULL) -+ kfree(a_wait_bcon_tmr); -+ if (a_aidl_bdis_tmr != NULL) -+ kfree(a_aidl_bdis_tmr); -+ if (b_ase0_brst_tmr != NULL) -+ kfree(b_ase0_brst_tmr); -+ if (b_se0_srp_tmr != NULL) -+ kfree(b_se0_srp_tmr); -+ if (b_srp_fail_tmr != NULL) -+ kfree(b_srp_fail_tmr); -+ if (a_wait_enum_tmr != NULL) -+ kfree(a_wait_enum_tmr); -+ -+ /* device driver used timers */ -+ if (b_srp_wait_tmr != NULL) -+ kfree(b_srp_wait_tmr); -+ if (b_data_pulse_tmr != NULL) -+ kfree(b_data_pulse_tmr); -+ if (b_vbus_pulse_tmr != NULL) -+ kfree(b_vbus_pulse_tmr); -+} -+ -+/* Add timer to timer list */ -+void fsl_otg_add_timer(void *gtimer) -+{ -+ struct fsl_otg_timer *timer = (struct fsl_otg_timer *)gtimer; -+ struct fsl_otg_timer *tmp_timer; -+ -+ /* Check if the timer is already in the active list, -+ * if so update timer count -+ */ -+ list_for_each_entry(tmp_timer, &active_timers, list) -+ if (tmp_timer == timer) { -+ timer->count = timer->expires; -+ return; -+ } -+ timer->count = timer->expires; -+ list_add_tail(&timer->list, &active_timers); -+} -+ -+/* Remove timer from the timer list; clear timeout status */ -+void fsl_otg_del_timer(void *gtimer) -+{ -+ struct fsl_otg_timer *timer = (struct fsl_otg_timer *)gtimer; -+ struct fsl_otg_timer *tmp_timer, *del_tmp; -+ -+ list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) -+ if (tmp_timer == timer) -+ list_del(&timer->list); -+} -+ -+/* Reduce timer count by 1, and find timeout conditions. -+ * Called by fsl_otg 1ms timer interrupt -+ */ -+int fsl_otg_tick_timer(void) -+{ -+ struct fsl_otg_timer *tmp_timer, *del_tmp; -+ int expired = 0; -+ -+ list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { -+ tmp_timer->count--; -+ /* check if timer expires */ -+ if (!tmp_timer->count) { -+ list_del(&tmp_timer->list); -+ tmp_timer->function(tmp_timer->data); -+ expired = 1; -+ } -+ } -+ -+ return expired; -+} -+ -+/* Reset controller, not reset the bus */ -+void otg_reset_controller(void) -+{ -+ u32 command; -+ -+ command = fsl_readl(&usb_dr_regs->usbcmd); -+ command |= (1 << 1); -+ fsl_writel(command, &usb_dr_regs->usbcmd); -+ while (fsl_readl(&usb_dr_regs->usbcmd) & (1 << 1)) -+ ; -+} -+ -+/* Call suspend/resume routines in host driver */ -+int fsl_otg_start_host(struct otg_fsm *fsm, int on) -+{ -+ struct otg_transceiver *xceiv = fsm->transceiver; -+ struct device *dev; -+ struct fsl_otg *otg_dev = container_of(xceiv, struct fsl_otg, otg); -+ u32 retval = 0; -+ -+ if (!xceiv->host) -+ return -ENODEV; -+ dev = xceiv->host->controller; -+ -+ /* Update a_vbus_vld state as a_vbus_vld int is disabled -+ * in device mode -+ */ -+ fsm->a_vbus_vld = -+ !!(fsl_readl(&usb_dr_regs->otgsc) & OTGSC_STS_A_VBUS_VALID); -+ if (on) { -+ /* start fsl usb host controller */ -+ if (otg_dev->host_working) -+ goto end; -+ else { -+ otg_reset_controller(); -+ VDBG("host on......\n"); -+ if (dev->driver->resume) { -+ retval = dev->driver->resume(dev); -+ if (fsm->id) { -+ /* default-b */ -+ fsl_otg_drv_vbus(1); -+ /* Workaround: b_host can't driver -+ * vbus, but PP in PORTSC needs to -+ * be 1 for host to work. -+ * So we set drv_vbus bit in -+ * transceiver to 0 thru ULPI. */ -+ write_ulpi(0x0c, 0x20); -+ } -+ } -+ -+ otg_dev->host_working = 1; -+ } -+ } else { -+ /* stop fsl usb host controller */ -+ if (!otg_dev->host_working) -+ goto end; -+ else { -+ VDBG("host off......\n"); -+ if (dev && dev->driver) { -+ retval = dev->driver->suspend(dev, -+ otg_suspend_state); -+ if (fsm->id) -+ /* default-b */ -+ fsl_otg_drv_vbus(0); -+ } -+ otg_dev->host_working = 0; -+ } -+ } -+end: -+ return retval; -+} -+ -+/* Call suspend and resume function in udc driver -+ * to stop and start udc driver. -+ */ -+int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) -+{ -+ struct otg_transceiver *xceiv = fsm->transceiver; -+ struct device *dev; -+ -+ if (!xceiv->gadget || !xceiv->gadget->dev.parent) -+ return -ENODEV; -+ -+ VDBG("gadget %s\n", on ? "on" : "off"); -+ dev = xceiv->gadget->dev.parent; -+ -+ if (on) -+ dev->driver->resume(dev); -+ else -+ dev->driver->suspend(dev, otg_suspend_state); -+ -+ return 0; -+} -+ -+/* Called by initialization code of host driver. Register host controller -+ * to the OTG. Suspend host for OTG role detection. -+ */ -+static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) -+{ -+ struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); -+ -+ if (!otg_p || otg_dev != fsl_otg_dev) -+ return -ENODEV; -+ -+ DBG("%s\n", __func__); -+ otg_p->host = host; -+ -+ otg_dev->fsm.a_bus_drop = 0; -+ otg_dev->fsm.a_bus_req = 1; -+ -+ if (host) { -+ VDBG("host off......\n"); -+ -+ otg_p->host->otg_port = fsl_otg_initdata.otg_port; -+ otg_p->host->is_b_host = otg_dev->fsm.id; -+ /* must leave time for khubd to finish its thing -+ * before yanking the host driver out from under it, -+ * so suspend the host after a short delay. -+ */ -+ otg_dev->host_working = 1; -+ schedule_delayed_work(&otg_dev->otg_event, 100); -+ return 0; -+ } else { /* host driver going away */ -+ -+ if (!(fsl_readl(&otg_dev->dr_mem_map->otgsc) & -+ OTGSC_STS_USB_ID)) { -+ /* Mini-A cable connected */ -+ struct otg_fsm *fsm = &otg_dev->fsm; -+ -+ otg_p->state = OTG_STATE_UNDEFINED; -+ fsm->protocol = PROTO_UNDEF; -+ } -+ } -+ -+ otg_dev->host_working = 0; -+ -+ otg_statemachine(&otg_dev->fsm); -+ -+ return 0; -+} -+ -+/* Called by initialization code of udc. Register udc to OTG.*/ -+static int fsl_otg_set_peripheral(struct otg_transceiver *otg_p, -+ struct usb_gadget *gadget) -+{ -+ struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); -+ -+ DBG("%s\n", __func__); -+ VDBG("otg_dev 0x%x\n", (int)otg_dev); -+ VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev); -+ -+ if (!otg_p || otg_dev != fsl_otg_dev) -+ return -ENODEV; -+ -+ if (!gadget) { -+ if (!otg_dev->otg.default_a) -+ otg_p->gadget->ops->vbus_draw(otg_p->gadget, 0); -+ usb_gadget_vbus_disconnect(otg_dev->otg.gadget); -+ otg_dev->otg.gadget = 0; -+ otg_dev->fsm.b_bus_req = 0; -+ otg_statemachine(&otg_dev->fsm); -+ return 0; -+ } -+ -+ otg_p->gadget = gadget; -+ otg_p->gadget->is_a_peripheral = !otg_dev->fsm.id; -+ -+ otg_dev->fsm.b_bus_req = 1; -+ -+ /* start the gadget right away if the ID pin says Mini-B */ -+ DBG("ID pin=%d\n", otg_dev->fsm.id); -+ if (otg_dev->fsm.id == 1) { -+ fsl_otg_start_host(&otg_dev->fsm, 0); -+ otg_drv_vbus(&otg_dev->fsm, 0); -+ fsl_otg_start_gadget(&otg_dev->fsm, 1); -+ } -+ -+ return 0; -+} -+ -+/* Set OTG port power, only for B-device */ -+static int fsl_otg_set_power(struct otg_transceiver *otg_p, unsigned mA) -+{ -+ if (!fsl_otg_dev) -+ return -ENODEV; -+ if (otg_p->state == OTG_STATE_B_PERIPHERAL) -+ printk(KERN_INFO "FSL OTG:Draw %d mA\n", mA); -+ -+ return 0; -+} -+ -+/* Delayed pin detect interrupt processing. -+ * -+ * When the Mini-A cable is disconnected from the board, -+ * the pin-detect interrupt happens before the disconnnect -+ * interrupts for the connected device(s). In order to -+ * process the disconnect interrupt(s) prior to switching -+ * roles, the pin-detect interrupts are delayed, and handled -+ * by this routine. -+ */ -+static void fsl_otg_event(struct work_struct *work) -+{ -+ struct fsl_otg *og = container_of(work, struct fsl_otg, otg_event.work); -+ struct otg_fsm *fsm = &og->fsm; -+ -+ if (fsm->id) { /* switch to gadget */ -+ fsl_otg_start_host(fsm, 0); -+ otg_drv_vbus(fsm, 0); -+ fsl_otg_start_gadget(fsm, 1); -+ } -+} -+ -+/* B-device start SRP */ -+static int fsl_otg_start_srp(struct otg_transceiver *otg_p) -+{ -+ struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); -+ -+ if (!otg_p || otg_dev != fsl_otg_dev -+ || otg_p->state != OTG_STATE_B_IDLE) -+ return -ENODEV; -+ -+ otg_dev->fsm.b_bus_req = 1; -+ otg_statemachine(&otg_dev->fsm); -+ -+ return 0; -+} -+ -+/* A_host suspend will call this function to start hnp */ -+static int fsl_otg_start_hnp(struct otg_transceiver *otg_p) -+{ -+ struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); -+ -+ if (!otg_p || otg_dev != fsl_otg_dev) -+ return -ENODEV; -+ -+ /* printk("start_hnp.............\n"); */ -+ /* clear a_bus_req to enter a_suspend state */ -+ otg_dev->fsm.a_bus_req = 0; -+ otg_statemachine(&otg_dev->fsm); -+ -+ return 0; -+} -+ -+/* Interrupt handler. OTG/host/peripheral share the same int line. -+ * OTG driver clears OTGSC interrupts and leaves USB interrupts -+ * intact. It needs to have knowledge of some USB interrupts -+ * such as port change. -+ */ -+irqreturn_t fsl_otg_isr(int irq, void *dev_id) -+{ -+ struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm; -+ struct otg_transceiver *otg = &((struct fsl_otg *)dev_id)->otg; -+ u32 otg_int_src, otg_sc; -+ -+ otg_sc = fsl_readl(&usb_dr_regs->otgsc); -+ otg_int_src = otg_sc & OTGSC_INTSTS_MASK; -+ -+ /* Only clear otg interrupts */ -+ fsl_writel(otg_sc, &usb_dr_regs->otgsc); -+ -+ /*FIXME: ID change not generate when init to 0 */ -+ fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0; -+ otg->default_a = (fsm->id == 0); -+ -+ /* process OTG interrupts */ -+ if (otg_int_src) { -+ if (otg_int_src & OTGSC_INTSTS_USB_ID) { -+ fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0; -+ otg->default_a = (fsm->id == 0); -+ /* clear conn information */ -+ if (fsm->id) -+ fsm->b_conn = 0; -+ else -+ fsm->a_conn = 0; -+ -+ if (otg->host) -+ otg->host->is_b_host = fsm->id; -+ if (otg->gadget) -+ otg->gadget->is_a_peripheral = !fsm->id; -+ VDBG("ID int (ID is %d)\n", fsm->id); -+ -+ if (fsm->id) { /* switch to gadget */ -+ schedule_delayed_work(&((struct fsl_otg *) -+ dev_id)->otg_event, 100); -+ } else { /* switch to host */ -+ cancel_delayed_work(& -+ ((struct fsl_otg *)dev_id)-> -+ otg_event); -+ fsl_otg_start_gadget(fsm, 0); -+ otg_drv_vbus(fsm, 1); -+ fsl_otg_start_host(fsm, 1); -+ } -+ return IRQ_HANDLED; -+ } -+ } -+ return IRQ_NONE; -+} -+ -+static struct otg_fsm_ops fsl_otg_ops = { -+ .chrg_vbus = fsl_otg_chrg_vbus, -+ .drv_vbus = fsl_otg_drv_vbus, -+ .loc_conn = fsl_otg_loc_conn, -+ .loc_sof = fsl_otg_loc_sof, -+ .start_pulse = fsl_otg_start_pulse, -+ -+ .add_timer = fsl_otg_add_timer, -+ .del_timer = fsl_otg_del_timer, -+ -+ .start_host = fsl_otg_start_host, -+ .start_gadget = fsl_otg_start_gadget, -+}; -+ -+/* Initialize the global variable fsl_otg_dev and request IRQ for OTG */ -+static int fsl_otg_conf(struct platform_device *pdev) -+{ -+ int status; -+ struct fsl_otg *fsl_otg_tc; -+ struct fsl_usb2_platform_data *pdata; -+ -+ pdata = pdev->dev.platform_data; -+ -+ if (fsl_otg_dev) -+ return 0; -+ -+ /* allocate space to fsl otg device */ -+ fsl_otg_tc = kzalloc(sizeof(struct fsl_otg), GFP_KERNEL); -+ if (!fsl_otg_tc) -+ return -ENODEV; -+ -+ INIT_DELAYED_WORK(&fsl_otg_tc->otg_event, fsl_otg_event); -+ -+ INIT_LIST_HEAD(&active_timers); -+ status = fsl_otg_init_timers(&fsl_otg_tc->fsm); -+ if (status) { -+ printk(KERN_INFO "Couldn't init OTG timers\n"); -+ fsl_otg_uninit_timers(); -+ kfree(fsl_otg_tc); -+ return status; -+ } -+ spin_lock_init(&fsl_otg_tc->fsm.lock); -+ -+ /* Set OTG state machine operations */ -+ fsl_otg_tc->fsm.ops = &fsl_otg_ops; -+ -+ /* initialize the otg structure */ -+ fsl_otg_tc->otg.label = DRIVER_DESC; -+ fsl_otg_tc->otg.set_host = fsl_otg_set_host; -+ fsl_otg_tc->otg.set_peripheral = fsl_otg_set_peripheral; -+ fsl_otg_tc->otg.set_power = fsl_otg_set_power; -+ fsl_otg_tc->otg.start_hnp = fsl_otg_start_hnp; -+ fsl_otg_tc->otg.start_srp = fsl_otg_start_srp; -+ -+ fsl_otg_dev = fsl_otg_tc; -+ -+ /* Store the otg transceiver */ -+ status = otg_set_transceiver(&fsl_otg_tc->otg); -+ if (status) { -+ printk(KERN_WARNING ": unable to register OTG transceiver.\n"); -+ return status; -+ } -+ -+ return 0; -+} -+ -+/* OTG Initialization*/ -+int usb_otg_start(struct platform_device *pdev) -+{ -+ struct fsl_otg __iomem *p_otg; -+ struct otg_transceiver *otg_trans = otg_get_transceiver(); -+ struct otg_fsm *fsm; -+ volatile unsigned long *p; -+ int status; -+ struct resource *res; -+ u32 temp; -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ -+ p_otg = container_of(otg_trans, struct fsl_otg, otg); -+ fsm = &p_otg->fsm; -+ -+ /* Initialize the state machine structure with default values */ -+ SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED); -+ fsm->transceiver = &p_otg->otg; -+ -+ /* We don't require predefined MEM/IRQ resource index */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) -+ return -ENXIO; -+ -+ /* We don't request_mem_region here to enable resource sharing -+ * with host/device */ -+ -+ usb_dr_regs = ioremap(res->start, sizeof(struct usb_dr_mmap)); -+ p_otg->dr_mem_map = (struct usb_dr_mmap *)usb_dr_regs; -+ pdata->regs = (void *)usb_dr_regs; -+ -+ /* request irq */ -+ p_otg->irq = platform_get_irq(pdev, 0); -+ status = request_irq(p_otg->irq, fsl_otg_isr, -+ IRQF_SHARED, driver_name, p_otg); -+ if (status) { -+ dev_dbg(p_otg->otg.dev, "can't get IRQ %d, error %d\n", -+ p_otg->irq, status); -+ iounmap(p_otg->dr_mem_map); -+ kfree(p_otg); -+ return status; -+ } -+ -+ if (pdata->init && pdata->init(pdev) != 0) -+ return -EINVAL; -+ -+ -+ /* Export DR controller resources */ -+ otg_set_resources(pdev->resource); -+ -+ /* stop the controller */ -+ temp = fsl_readl(&p_otg->dr_mem_map->usbcmd); -+ temp &= ~USB_CMD_RUN_STOP; -+ fsl_writel(temp, &p_otg->dr_mem_map->usbcmd); -+ -+ /* reset the controller */ -+ temp = fsl_readl(&p_otg->dr_mem_map->usbcmd); -+ temp |= USB_CMD_CTRL_RESET; -+ fsl_writel(temp, &p_otg->dr_mem_map->usbcmd); -+ -+ /* wait reset completed */ -+ udelay(2); -+ while (fsl_readl(&p_otg->dr_mem_map->usbcmd) & USB_CMD_CTRL_RESET) -+ ; -+ -+ /* configure the VBUSHS as IDLE(both host and device) */ -+ temp = USB_MODE_STREAM_DISABLE | (pdata->es ? USB_MODE_ES : 0); -+ fsl_writel(temp, &p_otg->dr_mem_map->usbmode); -+ -+ /* configure PHY interface */ -+ temp = fsl_readl(&p_otg->dr_mem_map->portsc); -+ temp &= ~(PORTSC_PHY_TYPE_SEL | PORTSC_PTW); -+ switch (pdata->phy_mode) { -+ case FSL_USB2_PHY_ULPI: -+ temp |= PORTSC_PTS_ULPI; -+ break; -+ case FSL_USB2_PHY_UTMI_WIDE: -+ temp |= PORTSC_PTW_16BIT; -+ /* fall through */ -+ case FSL_USB2_PHY_UTMI: -+ temp |= PORTSC_PTS_UTMI; -+ /* fall through */ -+ default: -+ break; -+ } -+ fsl_writel(temp, &p_otg->dr_mem_map->portsc); -+ -+ if (pdata->have_sysif_regs) { -+ /* configure control enable IO output, big endian register */ -+ p = (volatile unsigned long *)(&p_otg->dr_mem_map->control); -+ temp = *p; -+ temp |= USB_CTRL_IOENB; -+ *p = temp; -+ } -+ -+ /* disable all interrupt and clear all OTGSC status */ -+ temp = fsl_readl(&p_otg->dr_mem_map->otgsc); -+ temp &= ~OTGSC_INTERRUPT_ENABLE_BITS_MASK; -+ temp |= OTGSC_INTERRUPT_STATUS_BITS_MASK | OTGSC_CTRL_VBUS_DISCHARGE; -+ fsl_writel(temp, &p_otg->dr_mem_map->otgsc); -+ -+ -+ /* -+ * The identification (id) input is FALSE when a Mini-A plug is inserted -+ * in the devices Mini-AB receptacle. Otherwise, this input is TRUE. -+ * Also: record initial state of ID pin -+ */ -+ if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) { -+ p_otg->otg.state = OTG_STATE_UNDEFINED; -+ p_otg->fsm.id = 1; -+ } else { -+ p_otg->otg.state = OTG_STATE_A_IDLE; -+ p_otg->fsm.id = 0; -+ } -+ -+ DBG("initial ID pin=%d\n", p_otg->fsm.id); -+ -+ /* enable OTG ID pin interrupt */ -+ temp = fsl_readl(&p_otg->dr_mem_map->otgsc); -+ temp |= OTGSC_INTR_USB_ID_EN; -+ temp &= ~(OTGSC_CTRL_VBUS_DISCHARGE | OTGSC_INTR_1MS_TIMER_EN); -+ fsl_writel(temp, &p_otg->dr_mem_map->otgsc); -+ -+ return 0; -+} -+ -+/*------------------------------------------------------------------------- -+ PROC File System Support -+-------------------------------------------------------------------------*/ -+#ifdef CONFIG_USB_OTG_DEBUG_FILES -+ -+#include <linux/seq_file.h> -+ -+static const char proc_filename[] = "driver/fsl_usb2_otg"; -+ -+static int otg_proc_read(char *page, char **start, off_t off, int count, -+ int *eof, void *_dev) -+{ -+ struct otg_fsm *fsm = &fsl_otg_dev->fsm; -+ char *buf = page; -+ char *next = buf; -+ unsigned size = count; -+ unsigned long flags; -+ int t; -+ u32 tmp_reg; -+ -+ if (off != 0) -+ return 0; -+ -+ spin_lock_irqsave(&fsm->lock, flags); -+ -+ /* ------basic driver infomation ---- */ -+ t = scnprintf(next, size, -+ DRIVER_DESC "\n" "fsl_usb2_otg version: %s\n\n", -+ DRIVER_VERSION); -+ size -= t; -+ next += t; -+ -+ /* ------ Registers ----- */ -+ tmp_reg = fsl_readl(&usb_dr_regs->otgsc); -+ t = scnprintf(next, size, "OTGSC reg: %08x\n", tmp_reg); -+ size -= t; -+ next += t; -+ -+ tmp_reg = fsl_readl(&usb_dr_regs->portsc); -+ t = scnprintf(next, size, "PORTSC reg: %08x\n", tmp_reg); -+ size -= t; -+ next += t; -+ -+ tmp_reg = fsl_readl(&usb_dr_regs->usbmode); -+ t = scnprintf(next, size, "USBMODE reg: %08x\n", tmp_reg); -+ size -= t; -+ next += t; -+ -+ tmp_reg = fsl_readl(&usb_dr_regs->usbcmd); -+ t = scnprintf(next, size, "USBCMD reg: %08x\n", tmp_reg); -+ size -= t; -+ next += t; -+ -+ tmp_reg = fsl_readl(&usb_dr_regs->usbsts); -+ t = scnprintf(next, size, "USBSTS reg: %08x\n", tmp_reg); -+ size -= t; -+ next += t; -+ -+ tmp_reg = fsl_readl(&usb_dr_regs->usbintr); -+ t = scnprintf(next, size, "USBINTR reg: %08x\n", tmp_reg); -+ size -= t; -+ next += t; -+ -+ /* ------ State ----- */ -+ t = scnprintf(next, size, -+ "OTG state: %s\n\n", -+ state_string(fsl_otg_dev->otg.state)); -+ size -= t; -+ next += t; -+ -+ /* ------ State Machine Variables ----- */ -+ t = scnprintf(next, size, "a_bus_req: %d\n", fsm->a_bus_req); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "b_bus_req: %d\n", fsm->b_bus_req); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "a_bus_resume: %d\n", fsm->a_bus_resume); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "a_bus_suspend: %d\n", fsm->a_bus_suspend); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "a_conn: %d\n", fsm->a_conn); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "a_sess_vld: %d\n", fsm->a_sess_vld); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "a_srp_det: %d\n", fsm->a_srp_det); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "a_vbus_vld: %d\n", fsm->a_vbus_vld); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "b_bus_resume: %d\n", fsm->b_bus_resume); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "b_bus_suspend: %d\n", fsm->b_bus_suspend); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "b_conn: %d\n", fsm->b_conn); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "b_se0_srp: %d\n", fsm->b_se0_srp); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "b_sess_end: %d\n", fsm->b_sess_end); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "b_sess_vld: %d\n", fsm->b_sess_vld); -+ size -= t; -+ next += t; -+ -+ t = scnprintf(next, size, "id: %d\n", fsm->id); -+ size -= t; -+ next += t; -+ -+ spin_unlock_irqrestore(&fsm->lock, flags); -+ -+ *eof = 1; -+ return count - size; -+} -+ -+#define create_proc_file() create_proc_read_entry(proc_filename, \ -+ 0, NULL, otg_proc_read, NULL) -+ -+#define remove_proc_file() remove_proc_entry(proc_filename, NULL) -+ -+#else /* !CONFIG_USB_OTG_DEBUG_FILES */ -+ -+#define create_proc_file() do {} while (0) -+#define remove_proc_file() do {} while (0) -+ -+#endif /*CONFIG_USB_OTG_DEBUG_FILES */ -+ -+/*----------------------------------------------------------*/ -+/* Char driver interface to control some OTG input */ -+ -+/* This function handle some ioctl command,such as get otg -+ * status and set host suspend -+ */ -+static long fsl_otg_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ u32 retval = 0; -+ -+ switch (cmd) { -+ case GET_OTG_STATUS: -+ retval = fsl_otg_dev->host_working; -+ break; -+ -+ case SET_A_SUSPEND_REQ: -+ fsl_otg_dev->fsm.a_suspend_req = arg; -+ break; -+ -+ case SET_A_BUS_DROP: -+ fsl_otg_dev->fsm.a_bus_drop = arg; -+ break; -+ -+ case SET_A_BUS_REQ: -+ fsl_otg_dev->fsm.a_bus_req = arg; -+ break; -+ -+ case SET_B_BUS_REQ: -+ fsl_otg_dev->fsm.b_bus_req = arg; -+ break; -+ -+ default: -+ break; -+ } -+ -+ otg_statemachine(&fsl_otg_dev->fsm); -+ -+ return retval; -+} -+ -+static int fsl_otg_open(struct inode *inode, struct file *file) -+{ -+ -+ return 0; -+} -+ -+static int fsl_otg_release(struct inode *inode, struct file *file) -+{ -+ -+ return 0; -+} -+ -+static struct file_operations otg_fops = { -+ .owner = THIS_MODULE, -+ .llseek = NULL, -+ .read = NULL, -+ .write = NULL, -+ .unlocked_ioctl = fsl_otg_ioctl, -+ .open = fsl_otg_open, -+ .release = fsl_otg_release, -+}; -+ -+static int __init fsl_otg_probe(struct platform_device *pdev) -+{ -+ int status; -+ struct fsl_usb2_platform_data *pdata; -+ -+ DBG("pdev=0x%p\n", pdev); -+ -+ if (!pdev) -+ return -ENODEV; -+ -+ if (!pdev->dev.platform_data) -+ return -ENOMEM; -+ -+ pdata = pdev->dev.platform_data; -+ fsl_set_usb_accessors(pdata); -+ -+ /* configure the OTG */ -+ status = fsl_otg_conf(pdev); -+ if (status) { -+ printk(KERN_INFO "Couldn't init OTG module\n"); -+ return -status; -+ } -+ -+ /* start OTG */ -+ status = usb_otg_start(pdev); -+ -+ if (register_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME, &otg_fops)) { -+ printk(KERN_WARNING FSL_OTG_NAME -+ ": unable to register FSL OTG device\n"); -+ return -EIO; -+ } -+ -+ create_proc_file(); -+ return status; -+} -+ -+static int __exit fsl_otg_remove(struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -+ -+ otg_set_transceiver(NULL); -+ free_irq(fsl_otg_dev->irq, fsl_otg_dev); -+ -+ iounmap((void *)usb_dr_regs); -+ -+ kfree(fsl_otg_dev); -+ -+ remove_proc_file(); -+ -+ unregister_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME); -+ -+ if (pdata->exit) -+ pdata->exit(pdev); -+ -+ return 0; -+} -+ -+struct platform_driver fsl_otg_driver = { -+ .probe = fsl_otg_probe, -+ .remove = __exit_p(fsl_otg_remove), -+ .driver = { -+ .name = driver_name, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int __init fsl_usb_otg_init(void) -+{ -+ printk(KERN_INFO DRIVER_DESC " loaded, %s\n", DRIVER_VERSION); -+ return platform_driver_register(&fsl_otg_driver); -+} -+ -+static void __exit fsl_usb_otg_exit(void) -+{ -+ platform_driver_unregister(&fsl_otg_driver); -+ printk(KERN_INFO DRIVER_DESC " unloaded\n"); -+} -+ -+module_init(fsl_usb_otg_init); -+module_exit(fsl_usb_otg_exit); -+ -+MODULE_DESCRIPTION(DRIVER_INFO); -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/drivers/usb/otg/fsl_otg.h -@@ -0,0 +1,423 @@ -+/* Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include "otg_fsm.h" -+#include <linux/usb/otg.h> -+#include <linux/ioctl.h> -+ -+#ifdef CONFIG_PPC32 -+#include <asm/fsl_usb_io.h> -+#elif CONFIG_COLDFIRE -+#include <asm/mcfsim.h> -+#include <asm/fsl_usb_io.h> -+#endif -+ -+#define hc32_to_cpu(x) (x) -+#define cpu_to_hc32(x) (x) -+ -+ /* USB Command Register Bit Masks */ -+#define USB_CMD_RUN_STOP (0x1<<0) -+#define USB_CMD_CTRL_RESET (0x1<<1) -+#define USB_CMD_PERIODIC_SCHEDULE_EN (0x1<<4) -+#define USB_CMD_ASYNC_SCHEDULE_EN (0x1<<5) -+#define USB_CMD_INT_AA_DOORBELL (0x1<<6) -+#define USB_CMD_ASP (0x3<<8) -+#define USB_CMD_ASYNC_SCH_PARK_EN (0x1<<11) -+#define USB_CMD_SUTW (0x1<<13) -+#define USB_CMD_ATDTW (0x1<<14) -+#define USB_CMD_ITC (0xFF<<16) -+ -+/* bit 15,3,2 are frame list size */ -+#define USB_CMD_FRAME_SIZE_1024 (0x0<<15 | 0x0<<2) -+#define USB_CMD_FRAME_SIZE_512 (0x0<<15 | 0x1<<2) -+#define USB_CMD_FRAME_SIZE_256 (0x0<<15 | 0x2<<2) -+#define USB_CMD_FRAME_SIZE_128 (0x0<<15 | 0x3<<2) -+#define USB_CMD_FRAME_SIZE_64 (0x1<<15 | 0x0<<2) -+#define USB_CMD_FRAME_SIZE_32 (0x1<<15 | 0x1<<2) -+#define USB_CMD_FRAME_SIZE_16 (0x1<<15 | 0x2<<2) -+#define USB_CMD_FRAME_SIZE_8 (0x1<<15 | 0x3<<2) -+ -+/* bit 9-8 are async schedule park mode count */ -+#define USB_CMD_ASP_00 (0x0<<8) -+#define USB_CMD_ASP_01 (0x1<<8) -+#define USB_CMD_ASP_10 (0x2<<8) -+#define USB_CMD_ASP_11 (0x3<<8) -+#define USB_CMD_ASP_BIT_POS (8) -+ -+/* bit 23-16 are interrupt threshold control */ -+#define USB_CMD_ITC_NO_THRESHOLD (0x00<<16) -+#define USB_CMD_ITC_1_MICRO_FRM (0x01<<16) -+#define USB_CMD_ITC_2_MICRO_FRM (0x02<<16) -+#define USB_CMD_ITC_4_MICRO_FRM (0x04<<16) -+#define USB_CMD_ITC_8_MICRO_FRM (0x08<<16) -+#define USB_CMD_ITC_16_MICRO_FRM (0x10<<16) -+#define USB_CMD_ITC_32_MICRO_FRM (0x20<<16) -+#define USB_CMD_ITC_64_MICRO_FRM (0x40<<16) -+#define USB_CMD_ITC_BIT_POS (16) -+ -+/* USB Status Register Bit Masks */ -+#define USB_STS_INT (0x1<<0) -+#define USB_STS_ERR (0x1<<1) -+#define USB_STS_PORT_CHANGE (0x1<<2) -+#define USB_STS_FRM_LST_ROLL (0x1<<3) -+#define USB_STS_SYS_ERR (0x1<<4) -+#define USB_STS_IAA (0x1<<5) -+#define USB_STS_RESET_RECEIVED (0x1<<6) -+#define USB_STS_SOF (0x1<<7) -+#define USB_STS_DCSUSPEND (0x1<<8) -+#define USB_STS_HC_HALTED (0x1<<12) -+#define USB_STS_RCL (0x1<<13) -+#define USB_STS_PERIODIC_SCHEDULE (0x1<<14) -+#define USB_STS_ASYNC_SCHEDULE (0x1<<15) -+ -+/* USB Interrupt Enable Register Bit Masks */ -+#define USB_INTR_INT_EN (0x1<<0) -+#define USB_INTR_ERR_INT_EN (0x1<<1) -+#define USB_INTR_PC_DETECT_EN (0x1<<2) -+#define USB_INTR_FRM_LST_ROLL_EN (0x1<<3) -+#define USB_INTR_SYS_ERR_EN (0x1<<4) -+#define USB_INTR_ASYN_ADV_EN (0x1<<5) -+#define USB_INTR_RESET_EN (0x1<<6) -+#define USB_INTR_SOF_EN (0x1<<7) -+#define USB_INTR_DEVICE_SUSPEND (0x1<<8) -+ -+/* Device Address bit masks */ -+#define USB_DEVICE_ADDRESS_MASK (0x7F<<25) -+#define USB_DEVICE_ADDRESS_BIT_POS (25) -+/* PORTSC Register Bit Masks,Only one PORT in OTG mode*/ -+#define PORTSC_CURRENT_CONNECT_STATUS (0x1<<0) -+#define PORTSC_CONNECT_STATUS_CHANGE (0x1<<1) -+#define PORTSC_PORT_ENABLE (0x1<<2) -+#define PORTSC_PORT_EN_DIS_CHANGE (0x1<<3) -+#define PORTSC_OVER_CURRENT_ACT (0x1<<4) -+#define PORTSC_OVER_CUURENT_CHG (0x1<<5) -+#define PORTSC_PORT_FORCE_RESUME (0x1<<6) -+#define PORTSC_PORT_SUSPEND (0x1<<7) -+#define PORTSC_PORT_RESET (0x1<<8) -+#define PORTSC_LINE_STATUS_BITS (0x3<<10) -+#define PORTSC_PORT_POWER (0x1<<12) -+#define PORTSC_PORT_INDICTOR_CTRL (0x3<<14) -+#define PORTSC_PORT_TEST_CTRL (0xF<<16) -+#define PORTSC_WAKE_ON_CONNECT_EN (0x1<<20) -+#define PORTSC_WAKE_ON_CONNECT_DIS (0x1<<21) -+#define PORTSC_WAKE_ON_OVER_CURRENT (0x1<<22) -+#define PORTSC_PHY_LOW_POWER_SPD (0x1<<23) -+#define PORTSC_PORT_FORCE_FULL_SPEED (0x1<<24) -+#define PORTSC_PORT_SPEED_MASK (0x3<<26) -+#define PORTSC_TRANSCEIVER_WIDTH (0x1<<28) -+#define PORTSC_PHY_TYPE_SEL (0x3<<30) -+/* bit 11-10 are line status */ -+#define PORTSC_LINE_STATUS_SE0 (0x0<<10) -+#define PORTSC_LINE_STATUS_JSTATE (0x1<<10) -+#define PORTSC_LINE_STATUS_KSTATE (0x2<<10) -+#define PORTSC_LINE_STATUS_UNDEF (0x3<<10) -+#define PORTSC_LINE_STATUS_BIT_POS (10) -+ -+/* bit 15-14 are port indicator control */ -+#define PORTSC_PIC_OFF (0x0<<14) -+#define PORTSC_PIC_AMBER (0x1<<14) -+#define PORTSC_PIC_GREEN (0x2<<14) -+#define PORTSC_PIC_UNDEF (0x3<<14) -+#define PORTSC_PIC_BIT_POS (14) -+ -+/* bit 19-16 are port test control */ -+#define PORTSC_PTC_DISABLE (0x0<<16) -+#define PORTSC_PTC_JSTATE (0x1<<16) -+#define PORTSC_PTC_KSTATE (0x2<<16) -+#define PORTSC_PTC_SEQNAK (0x3<<16) -+#define PORTSC_PTC_PACKET (0x4<<16) -+#define PORTSC_PTC_FORCE_EN (0x5<<16) -+#define PORTSC_PTC_BIT_POS (16) -+ -+/* bit 27-26 are port speed */ -+#define PORTSC_PORT_SPEED_FULL (0x0<<26) -+#define PORTSC_PORT_SPEED_LOW (0x1<<26) -+#define PORTSC_PORT_SPEED_HIGH (0x2<<26) -+#define PORTSC_PORT_SPEED_UNDEF (0x3<<26) -+#define PORTSC_SPEED_BIT_POS (26) -+ -+/* bit 28 is parallel transceiver width for UTMI interface */ -+#define PORTSC_PTW (0x1<<28) -+#define PORTSC_PTW_8BIT (0x0<<28) -+#define PORTSC_PTW_16BIT (0x1<<28) -+ -+/* bit 31-30 are port transceiver select */ -+#define PORTSC_PTS_UTMI (0x0<<30) -+#define PORTSC_PTS_ULPI (0x2<<30) -+#define PORTSC_PTS_FSLS_SERIAL (0x3<<30) -+#define PORTSC_PTS_BIT_POS (30) -+ -+#define PORTSC_W1C_BITS \ -+ (PORTSC_CONNECT_STATUS_CHANGE | \ -+ PORTSC_PORT_EN_DIS_CHANGE | \ -+ PORTSC_OVER_CUURENT_CHG) -+ -+/* OTG Status Control Register Bit Masks */ -+#define OTGSC_CTRL_VBUS_DISCHARGE (0x1<<0) -+#define OTGSC_CTRL_VBUS_CHARGE (0x1<<1) -+#define OTGSC_CTRL_OTG_TERMINATION (0x1<<3) -+#define OTGSC_CTRL_DATA_PULSING (0x1<<4) -+#define OTGSC_CTRL_ID_PULL_EN (0x1<<5) -+#define OTGSC_HA_DATA_PULSE (0x1<<6) -+#define OTGSC_HA_BA (0x1<<7) -+#define OTGSC_STS_USB_ID (0x1<<8) -+#define OTGSC_STS_A_VBUS_VALID (0x1<<9) -+#define OTGSC_STS_A_SESSION_VALID (0x1<<10) -+#define OTGSC_STS_B_SESSION_VALID (0x1<<11) -+#define OTGSC_STS_B_SESSION_END (0x1<<12) -+#define OTGSC_STS_1MS_TOGGLE (0x1<<13) -+#define OTGSC_STS_DATA_PULSING (0x1<<14) -+#define OTGSC_INTSTS_USB_ID (0x1<<16) -+#define OTGSC_INTSTS_A_VBUS_VALID (0x1<<17) -+#define OTGSC_INTSTS_A_SESSION_VALID (0x1<<18) -+#define OTGSC_INTSTS_B_SESSION_VALID (0x1<<19) -+#define OTGSC_INTSTS_B_SESSION_END (0x1<<20) -+#define OTGSC_INTSTS_1MS (0x1<<21) -+#define OTGSC_INTSTS_DATA_PULSING (0x1<<22) -+#define OTGSC_INTR_USB_ID_EN (0x1<<24) -+#define OTGSC_INTR_A_VBUS_VALID_EN (0x1<<25) -+#define OTGSC_INTR_A_SESSION_VALID_EN (0x1<<26) -+#define OTGSC_INTR_B_SESSION_VALID_EN (0x1<<27) -+#define OTGSC_INTR_B_SESSION_END_EN (0x1<<28) -+#define OTGSC_INTR_1MS_TIMER_EN (0x1<<29) -+#define OTGSC_INTR_DATA_PULSING_EN (0x1<<30) -+#define OTGSC_INTSTS_MASK (0x00ff0000) -+ -+/* USB MODE Register Bit Masks */ -+#define USB_MODE_CTRL_MODE_IDLE (0x0<<0) -+#define USB_MODE_CTRL_MODE_DEVICE (0x2<<0) -+#define USB_MODE_CTRL_MODE_HOST (0x3<<0) -+#define USB_MODE_CTRL_MODE_RSV (0x1<<0) -+#define USB_MODE_SETUP_LOCK_OFF (0x1<<3) -+#define USB_MODE_STREAM_DISABLE (0x1<<4) -+#define USB_MODE_ES (0x1<<2) /* (big) Endian Select */ -+ -+#define MPC8349_OTG_IRQ (38) -+#define CFG_IMMR_BASE (0xfe000000) -+#define MPC83xx_USB_DR_BASE (CFG_IMMR_BASE + 0x23000) -+ -+/* control Register Bit Masks */ -+#define USB_CTRL_IOENB (0x1<<2) -+#define USB_CTRL_ULPI_INT0EN (0x1<<0) -+ -+/* BCSR5 */ -+#define BCSR5_INT_USB (0x02) -+ -+/* USB module clk cfg */ -+#define SCCR_OFFS (0xA08) -+#define SCCR_USB_CLK_DISABLE (0x00000000) /* USB clk disable */ -+#define SCCR_USB_MPHCM_11 (0x00c00000) -+#define SCCR_USB_MPHCM_01 (0x00400000) -+#define SCCR_USB_MPHCM_10 (0x00800000) -+#define SCCR_USB_DRCM_11 (0x00300000) -+#define SCCR_USB_DRCM_01 (0x00100000) -+#define SCCR_USB_DRCM_10 (0x00200000) -+ -+#define SICRL_OFFS (0x114) -+#define SICRL_USB0 (0x40000000) -+#define SICRL_USB1 (0x20000000) -+ -+#define SICRH_OFFS (0x118) -+#define SICRH_USB_UTMI (0x00020000) -+ -+/* OTG interrupt enable bit masks */ -+#define OTGSC_INTERRUPT_ENABLE_BITS_MASK \ -+ (OTGSC_INTR_USB_ID_EN | \ -+ OTGSC_INTR_1MS_TIMER_EN | \ -+ OTGSC_INTR_A_VBUS_VALID_EN | \ -+ OTGSC_INTR_A_SESSION_VALID_EN | \ -+ OTGSC_INTR_B_SESSION_VALID_EN | \ -+ OTGSC_INTR_B_SESSION_END_EN | \ -+ OTGSC_INTR_DATA_PULSING_EN) -+ -+/* OTG interrupt status bit masks */ -+#define OTGSC_INTERRUPT_STATUS_BITS_MASK \ -+ (OTGSC_INTSTS_USB_ID | \ -+ OTGSC_INTR_1MS_TIMER_EN | \ -+ OTGSC_INTSTS_A_VBUS_VALID | \ -+ OTGSC_INTSTS_A_SESSION_VALID | \ -+ OTGSC_INTSTS_B_SESSION_VALID | \ -+ OTGSC_INTSTS_B_SESSION_END | \ -+ OTGSC_INTSTS_DATA_PULSING) -+ -+/* -+ * A-DEVICE timing constants -+ */ -+ -+/* Wait for VBUS Rise */ -+#define TA_WAIT_VRISE (100) /* a_wait_vrise 100 ms, section: 6.6.5.1 */ -+ -+/* Wait for B-Connect */ -+#define TA_WAIT_BCON (10000) /* a_wait_bcon > 1 sec, section: 6.6.5.2 -+ * This is only used to get out of -+ * OTG_STATE_A_WAIT_BCON state if there was -+ * no connection for these many milliseconds -+ */ -+ -+/* A-Idle to B-Disconnect */ -+/* It is necessary for this timer to be more than 750 ms because of a bug in OPT -+ * test 5.4 in which B OPT disconnects after 750 ms instead of 75ms as stated -+ * in the test description -+ */ -+#define TA_AIDL_BDIS (5000) /* a_suspend minimum 200 ms, section: 6.6.5.3 */ -+ -+/* B-Idle to A-Disconnect */ -+#define TA_BIDL_ADIS (12) /* 3 to 200 ms */ -+ -+/* B-device timing constants */ -+ -+ -+/* Data-Line Pulse Time*/ -+#define TB_DATA_PLS (10) /* b_srp_init,continue 5~10ms, section:5.3.3 */ -+#define TB_DATA_PLS_MIN (5) /* minimum 5 ms */ -+#define TB_DATA_PLS_MAX (10) /* maximum 10 ms */ -+ -+/* SRP Initiate Time */ -+#define TB_SRP_INIT (100) /* b_srp_init,maximum 100 ms, section:5.3.8 */ -+ -+/* SRP Fail Time */ -+#define TB_SRP_FAIL (7000) /* b_srp_init,Fail time 5~30s, section:6.8.2.2*/ -+ -+/* SRP result wait time */ -+#define TB_SRP_WAIT (60) -+ -+/* VBus time */ -+#define TB_VBUS_PLS (30) /* time to keep vbus pulsing asserted */ -+ -+/* Discharge time */ -+/* This time should be less than 10ms. It varies from system to system. */ -+#define TB_VBUS_DSCHRG (8) -+ -+/* A-SE0 to B-Reset */ -+#define TB_ASE0_BRST (20) /* b_wait_acon, mini 3.125 ms,section:6.8.2.4 */ -+ -+/* A bus suspend timer before we can switch to b_wait_aconn */ -+#define TB_A_SUSPEND (7) -+#define TB_BUS_RESUME (12) -+ -+/* SE0 Time Before SRP */ -+#define TB_SE0_SRP (2) /* b_idle,minimum 2 ms, section:5.3.2 */ -+ -+ -+#define SET_OTG_STATE(otg_ptr, newstate) ((otg_ptr)->state = newstate) -+ -+struct usb_dr_mmap { -+ /* Capability register */ -+ u8 res1[256]; -+ u16 caplength; /* Capability Register Length */ -+ u16 hciversion; /* Host Controller Interface Version */ -+ u32 hcsparams; /* Host Controller Structual Parameters */ -+ u32 hccparams; /* Host Controller Capability Parameters */ -+ u8 res2[20]; -+ u32 dciversion; /* Device Controller Interface Version */ -+ u32 dccparams; /* Device Controller Capability Parameters */ -+ u8 res3[24]; -+ /* Operation register */ -+ u32 usbcmd; /* USB Command Register */ -+ u32 usbsts; /* USB Status Register */ -+ u32 usbintr; /* USB Interrupt Enable Register */ -+ u32 frindex; /* Frame Index Register */ -+ u8 res4[4]; -+ u32 deviceaddr; /* Device Address */ -+ u32 endpointlistaddr; /* Endpoint List Address Register */ -+ u8 res5[4]; -+ u32 burstsize; /* Master Interface Data Burst Size Register */ -+ u32 txttfilltuning; /* Transmit FIFO Tuning Controls Register */ -+ u8 res6[8]; -+ u32 ulpiview; /* ULPI register access */ -+ u8 res7[12]; -+ u32 configflag; /* Configure Flag Register */ -+ u32 portsc; /* Port 1 Status and Control Register */ -+ u8 res8[28]; -+ u32 otgsc; /* On-The-Go Status and Control */ -+ u32 usbmode; /* USB Mode Register */ -+ u32 endptsetupstat; /* Endpoint Setup Status Register */ -+ u32 endpointprime; /* Endpoint Initialization Register */ -+ u32 endptflush; /* Endpoint Flush Register */ -+ u32 endptstatus; /* Endpoint Status Register */ -+ u32 endptcomplete; /* Endpoint Complete Register */ -+ u32 endptctrl[6]; /* Endpoint Control Registers */ -+ u8 res9[552]; -+ u32 snoop1; -+ u32 snoop2; -+ u32 age_cnt_thresh; /* Age Count Threshold Register */ -+ u32 pri_ctrl; /* Priority Control Register */ -+ u32 si_ctrl; /* System Interface Control Register */ -+ u8 res10[236]; -+ u32 control; /* General Purpose Control Register */ -+}; -+ -+ -+struct fsl_otg_timer { -+ unsigned long expires; /* Number of count increase to timeout */ -+ unsigned long count; /* Tick counter */ -+ void (*function)(unsigned long); /* Timeout function */ -+ unsigned long data; /* Data passed to function */ -+ struct list_head list; -+}; -+ -+static inline struct fsl_otg_timer *otg_timer_initializer -+(void (*function)(unsigned long), unsigned long expires, unsigned long data) -+{ -+ struct fsl_otg_timer *timer; -+ timer = kmalloc(sizeof(struct fsl_otg_timer), GFP_KERNEL); -+ if (timer == NULL) -+ return NULL; -+ timer->function = function; -+ timer->expires = expires; -+ timer->data = data; -+ return timer; -+} -+ -+struct fsl_otg { -+ struct otg_transceiver otg; -+ struct otg_fsm fsm; -+ struct usb_dr_mmap __iomem *dr_mem_map; -+ struct delayed_work otg_event; -+ -+ /* used for usb host */ -+ struct work_struct work_wq; -+ u8 host_working; -+ -+ int irq; -+}; -+ -+struct fsl_otg_config { -+ u8 otg_port; -+}; -+ -+/*For SRP and HNP handle*/ -+#define FSL_OTG_MAJOR 66 -+#define FSL_OTG_NAME "fsl-usb2-otg" -+/*Command to OTG driver(ioctl)*/ -+#define OTG_IOCTL_MAGIC FSL_OTG_MAJOR -+/*if otg work as host,it should return 1,otherwise it return 0*/ -+#define GET_OTG_STATUS _IOR(OTG_IOCTL_MAGIC, 1, int) -+#define SET_A_SUSPEND_REQ _IOW(OTG_IOCTL_MAGIC, 2, int) -+#define SET_A_BUS_DROP _IOW(OTG_IOCTL_MAGIC, 3, int) -+#define SET_A_BUS_REQ _IOW(OTG_IOCTL_MAGIC, 4, int) -+#define SET_B_BUS_REQ _IOW(OTG_IOCTL_MAGIC, 5, int) -+#define GET_A_SUSPEND_REQ _IOR(OTG_IOCTL_MAGIC, 6, int) -+#define GET_A_BUS_DROP _IOR(OTG_IOCTL_MAGIC, 7, int) -+#define GET_A_BUS_REQ _IOR(OTG_IOCTL_MAGIC, 8, int) -+#define GET_B_BUS_REQ _IOR(OTG_IOCTL_MAGIC, 9, int) -+ -+extern const char *state_string(enum usb_otg_state state); -+extern int otg_set_resources(struct resource *resources); -+/* prototype declaration */ -+extern void fsl_otg_add_timer(void *timer); -+extern void fsl_otg_del_timer(void *timer); ---- /dev/null -+++ b/drivers/usb/otg/otg_fsm.c -@@ -0,0 +1,371 @@ -+/* OTG Finite State Machine from OTG spec -+ * -+ * Copyright 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * Author: Li Yang <LeoLi@freescale.com> -+ * Jerry Huang <Chang-Ming.Huang@freescale.com> -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/usb/otg.h> -+#include <linux/spinlock.h> -+#include <linux/delay.h> -+#include <linux/usb.h> -+#include <linux/usb/gadget.h> -+ -+#include <linux/types.h> -+#include "otg_fsm.h" -+ -+ -+/* Defined by device specific driver, for different timer implementation */ -+extern void *a_wait_vrise_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr, -+ *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_fail_tmr, *a_wait_enum_tmr; -+ -+const char *state_string(enum usb_otg_state state) -+{ -+ switch (state) { -+ case OTG_STATE_A_IDLE: return "a_idle"; -+ case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise"; -+ case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon"; -+ case OTG_STATE_A_HOST: return "a_host"; -+ case OTG_STATE_A_SUSPEND: return "a_suspend"; -+ case OTG_STATE_A_PERIPHERAL: return "a_peripheral"; -+ case OTG_STATE_A_WAIT_VFALL: return "a_wait_vfall"; -+ case OTG_STATE_A_VBUS_ERR: return "a_vbus_err"; -+ case OTG_STATE_B_IDLE: return "b_idle"; -+ case OTG_STATE_B_SRP_INIT: return "b_srp_init"; -+ case OTG_STATE_B_PERIPHERAL: return "b_peripheral"; -+ case OTG_STATE_B_WAIT_ACON: return "b_wait_acon"; -+ case OTG_STATE_B_HOST: return "b_host"; -+ default: return "UNDEFINED"; -+ } -+} -+ -+/* Change USB protocol when there is a protocol change */ -+static int otg_set_protocol(struct otg_fsm *fsm, int protocol) -+{ -+ int ret = 0; -+ -+ if (fsm->protocol != protocol) { -+ VDBG("Changing role fsm->protocol= %d; new protocol= %d\n", -+ fsm->protocol, protocol); -+ /* stop old protocol */ -+ if (fsm->protocol == PROTO_HOST) -+ ret = fsm->ops->start_host(fsm, 0); -+ else if (fsm->protocol == PROTO_GADGET) -+ ret = fsm->ops->start_gadget(fsm, 0); -+ if (ret) -+ return ret; -+ -+ /* start new protocol */ -+ if (protocol == PROTO_HOST) -+ ret = fsm->ops->start_host(fsm, 1); -+ else if (protocol == PROTO_GADGET) -+ ret = fsm->ops->start_gadget(fsm, 1); -+ if (ret) -+ return ret; -+ -+ fsm->protocol = protocol; -+ return 0; -+ } -+ -+ return 0; -+} -+ -+static int state_changed; -+ -+/* Called when leaving a state. Do state clean up jobs here */ -+void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state) -+{ -+ switch (old_state) { -+ case OTG_STATE_B_IDLE: -+ otg_del_timer(fsm, b_se0_srp_tmr); -+ fsm->b_se0_srp = 0; -+ break; -+ case OTG_STATE_B_SRP_INIT: -+ fsm->b_srp_done = 0; -+ break; -+ case OTG_STATE_B_PERIPHERAL: -+ break; -+ case OTG_STATE_B_WAIT_ACON: -+ otg_del_timer(fsm, b_ase0_brst_tmr); -+ fsm->b_ase0_brst_tmout = 0; -+ break; -+ case OTG_STATE_B_HOST: -+ break; -+ case OTG_STATE_A_IDLE: -+ break; -+ case OTG_STATE_A_WAIT_VRISE: -+ otg_del_timer(fsm, a_wait_vrise_tmr); -+ fsm->a_wait_vrise_tmout = 0; -+ break; -+ case OTG_STATE_A_WAIT_BCON: -+ otg_del_timer(fsm, a_wait_bcon_tmr); -+ fsm->a_wait_bcon_tmout = 0; -+ break; -+ case OTG_STATE_A_HOST: -+ otg_del_timer(fsm, a_wait_enum_tmr); -+ break; -+ case OTG_STATE_A_SUSPEND: -+ otg_del_timer(fsm, a_aidl_bdis_tmr); -+ fsm->a_aidl_bdis_tmout = 0; -+ fsm->a_suspend_req = 0; -+ break; -+ case OTG_STATE_A_PERIPHERAL: -+ break; -+ case OTG_STATE_A_WAIT_VFALL: -+ otg_del_timer(fsm, a_wait_vrise_tmr); -+ break; -+ case OTG_STATE_A_VBUS_ERR: -+ break; -+ default: -+ break; -+ } -+} -+ -+/* Called when entering a state */ -+int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) -+{ -+ state_changed = 1; -+ if (fsm->transceiver->state == new_state) -+ return 0; -+ VDBG("Set state: %s\n", state_string(new_state)); -+ otg_leave_state(fsm, fsm->transceiver->state); -+ switch (new_state) { -+ case OTG_STATE_B_IDLE: -+ otg_drv_vbus(fsm, 0); -+ otg_chrg_vbus(fsm, 0); -+ otg_loc_conn(fsm, 0); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_UNDEF); -+ otg_add_timer(fsm, b_se0_srp_tmr); -+ break; -+ case OTG_STATE_B_SRP_INIT: -+ otg_start_pulse(fsm); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_UNDEF); -+ otg_add_timer(fsm, b_srp_fail_tmr); -+ break; -+ case OTG_STATE_B_PERIPHERAL: -+ otg_chrg_vbus(fsm, 0); -+ otg_loc_conn(fsm, 1); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_GADGET); -+ break; -+ case OTG_STATE_B_WAIT_ACON: -+ otg_chrg_vbus(fsm, 0); -+ otg_loc_conn(fsm, 0); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_HOST); -+ otg_add_timer(fsm, b_ase0_brst_tmr); -+ fsm->a_bus_suspend = 0; -+ break; -+ case OTG_STATE_B_HOST: -+ otg_chrg_vbus(fsm, 0); -+ otg_loc_conn(fsm, 0); -+ otg_loc_sof(fsm, 1); -+ otg_set_protocol(fsm, PROTO_HOST); -+ usb_bus_start_enum(fsm->transceiver->host, -+ fsm->transceiver->host->otg_port); -+ break; -+ case OTG_STATE_A_IDLE: -+ otg_drv_vbus(fsm, 0); -+ otg_chrg_vbus(fsm, 0); -+ otg_loc_conn(fsm, 0); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_HOST); -+ break; -+ case OTG_STATE_A_WAIT_VRISE: -+ otg_drv_vbus(fsm, 1); -+ otg_loc_conn(fsm, 0); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_HOST); -+ otg_add_timer(fsm, a_wait_vrise_tmr); -+ break; -+ case OTG_STATE_A_WAIT_BCON: -+ otg_drv_vbus(fsm, 1); -+ otg_loc_conn(fsm, 0); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_HOST); -+ otg_add_timer(fsm, a_wait_bcon_tmr); -+ break; -+ case OTG_STATE_A_HOST: -+ otg_drv_vbus(fsm, 1); -+ otg_loc_conn(fsm, 0); -+ otg_loc_sof(fsm, 1); -+ otg_set_protocol(fsm, PROTO_HOST); -+ /* When HNP is triggered while a_bus_req = 0, a_host will -+ * suspend too fast to complete a_set_b_hnp_en */ -+ if (!fsm->a_bus_req || fsm->a_suspend_req) -+ otg_add_timer(fsm, a_wait_enum_tmr); -+ break; -+ case OTG_STATE_A_SUSPEND: -+ otg_drv_vbus(fsm, 1); -+ otg_loc_conn(fsm, 0); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_HOST); -+ otg_add_timer(fsm, a_aidl_bdis_tmr); -+ -+ break; -+ case OTG_STATE_A_PERIPHERAL: -+ otg_loc_conn(fsm, 1); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_GADGET); -+ otg_drv_vbus(fsm, 1); -+ break; -+ case OTG_STATE_A_WAIT_VFALL: -+ otg_drv_vbus(fsm, 0); -+ otg_loc_conn(fsm, 0); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_HOST); -+ break; -+ case OTG_STATE_A_VBUS_ERR: -+ otg_drv_vbus(fsm, 0); -+ otg_loc_conn(fsm, 0); -+ otg_loc_sof(fsm, 0); -+ otg_set_protocol(fsm, PROTO_UNDEF); -+ break; -+ default: -+ break; -+ } -+ -+ fsm->transceiver->state = new_state; -+ return 0; -+} -+ -+/* State change judgement */ -+int otg_statemachine(struct otg_fsm *fsm) -+{ -+ enum usb_otg_state state; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&fsm->lock, flags); -+ -+ state = fsm->transceiver->state; -+ state_changed = 0; -+ /* State machine state change judgement */ -+ -+ switch (state) { -+ case OTG_STATE_UNDEFINED: -+ VDBG("fsm->id = %d\n", fsm->id); -+ if (fsm->id) -+ otg_set_state(fsm, OTG_STATE_B_IDLE); -+ else -+ otg_set_state(fsm, OTG_STATE_A_IDLE); -+ break; -+ case OTG_STATE_B_IDLE: -+ if (!fsm->id) -+ otg_set_state(fsm, OTG_STATE_A_IDLE); -+ else if (fsm->b_sess_vld && fsm->transceiver->gadget) -+ otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); -+ else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp) -+ otg_set_state(fsm, OTG_STATE_B_SRP_INIT); -+ break; -+ case OTG_STATE_B_SRP_INIT: -+ if (!fsm->id || fsm->b_srp_done) -+ otg_set_state(fsm, OTG_STATE_B_IDLE); -+ break; -+ case OTG_STATE_B_PERIPHERAL: -+ if (!fsm->id || !fsm->b_sess_vld) -+ otg_set_state(fsm, OTG_STATE_B_IDLE); -+ else if (fsm->b_bus_req && fsm->transceiver-> -+ gadget->b_hnp_enable && fsm->a_bus_suspend) -+ otg_set_state(fsm, OTG_STATE_B_WAIT_ACON); -+ break; -+ case OTG_STATE_B_WAIT_ACON: -+ if (fsm->a_conn) -+ otg_set_state(fsm, OTG_STATE_B_HOST); -+ else if (!fsm->id || !fsm->b_sess_vld) -+ otg_set_state(fsm, OTG_STATE_B_IDLE); -+ else if (fsm->a_bus_resume || fsm->b_ase0_brst_tmout) { -+ fsm->b_ase0_brst_tmout = 0; -+ otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); -+ } -+ break; -+ case OTG_STATE_B_HOST: -+ if (!fsm->id || !fsm->b_sess_vld) -+ otg_set_state(fsm, OTG_STATE_B_IDLE); -+ else if (!fsm->b_bus_req || !fsm->a_conn) -+ otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); -+ break; -+ case OTG_STATE_A_IDLE: -+ if (fsm->id) -+ otg_set_state(fsm, OTG_STATE_B_IDLE); -+ else if (!fsm->a_bus_drop && (fsm->a_bus_req || fsm->a_srp_det)) -+ otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE); -+ break; -+ case OTG_STATE_A_WAIT_VRISE: -+ if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld || -+ fsm->a_wait_vrise_tmout) { -+ otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); -+ } -+ break; -+ case OTG_STATE_A_WAIT_BCON: -+ if (!fsm->a_vbus_vld) -+ otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); -+ else if (fsm->b_conn) -+ otg_set_state(fsm, OTG_STATE_A_HOST); -+ else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout) -+ otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); -+ break; -+ case OTG_STATE_A_HOST: -+ if ((!fsm->a_bus_req || fsm->a_suspend_req) && -+ fsm->transceiver->host->b_hnp_enable) -+ otg_set_state(fsm, OTG_STATE_A_SUSPEND); -+ else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop) -+ otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); -+ else if (!fsm->a_vbus_vld) -+ otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); -+ break; -+ case OTG_STATE_A_SUSPEND: -+ if (!fsm->b_conn && fsm->transceiver->host->b_hnp_enable) -+ otg_set_state(fsm, OTG_STATE_A_PERIPHERAL); -+ else if (!fsm->b_conn && !fsm->transceiver->host->b_hnp_enable) -+ otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); -+ else if (fsm->a_bus_req || fsm->b_bus_resume) -+ otg_set_state(fsm, OTG_STATE_A_HOST); -+ else if (fsm->id || fsm->a_bus_drop || fsm->a_aidl_bdis_tmout) -+ otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); -+ else if (!fsm->a_vbus_vld) -+ otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); -+ break; -+ case OTG_STATE_A_PERIPHERAL: -+ if (fsm->id || fsm->a_bus_drop) -+ otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); -+ else if (fsm->b_bus_suspend) -+ otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); -+ else if (!fsm->a_vbus_vld) -+ otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); -+ break; -+ case OTG_STATE_A_WAIT_VFALL: -+ if (fsm->id || fsm->a_bus_req || (!fsm->a_sess_vld && -+ !fsm->b_conn)) -+ otg_set_state(fsm, OTG_STATE_A_IDLE); -+ break; -+ case OTG_STATE_A_VBUS_ERR: -+ if (fsm->id || fsm->a_bus_drop || fsm->a_clr_err) -+ otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); -+ break; -+ default: -+ break; -+ } -+ spin_unlock_irqrestore(&fsm->lock, flags); -+ -+ /*VDBG("quit statemachine, changed = %d\n", state_changed); */ -+ return state_changed; -+} ---- /dev/null -+++ b/drivers/usb/otg/otg_fsm.h -@@ -0,0 +1,151 @@ -+/* Copyright 2006-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#if 0 -+#define DEBUG 1 -+#define VERBOSE 1 -+#endif -+ -+#ifdef DEBUG -+#define DBG(fmt, args...) printk(KERN_DEBUG "[%s] " fmt , \ -+ __func__, ## args) -+#else -+#define DBG(fmt, args...) do {} while (0) -+#endif -+ -+#ifdef VERBOSE -+#define VDBG DBG -+#else -+#define VDBG(stuff...) do {} while (0) -+#endif -+ -+#ifdef VERBOSE -+#define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__) -+#else -+#define MPC_LOC do {} while (0) -+#endif -+ -+#define PROTO_UNDEF (0) -+#define PROTO_HOST (1) -+#define PROTO_GADGET (2) -+ -+/* OTG state machine according to the OTG spec */ -+struct otg_fsm { -+ /* Input */ -+ int a_bus_resume; -+ int a_bus_suspend; -+ int a_conn; -+ int a_sess_vld; -+ int a_srp_det; -+ int a_vbus_vld; -+ int b_bus_resume; -+ int b_bus_suspend; -+ int b_conn; -+ int b_se0_srp; -+ int b_sess_end; -+ int b_sess_vld; -+ int id; -+ -+ /* Internal variables */ -+ int a_set_b_hnp_en; -+ int b_srp_done; -+ int b_hnp_enable; -+ -+ /* Timeout indicator for timers */ -+ int a_wait_vrise_tmout; -+ int a_wait_bcon_tmout; -+ int a_aidl_bdis_tmout; -+ int b_ase0_brst_tmout; -+ -+ /* Informative variables */ -+ int a_bus_drop; -+ int a_bus_req; -+ int a_clr_err; -+ int a_suspend_req; -+ int b_bus_req; -+ -+ /* Output */ -+ int drv_vbus; -+ int loc_conn; -+ int loc_sof; -+ -+ struct otg_fsm_ops *ops; -+ struct otg_transceiver *transceiver; -+ -+ /* Current usb protocol used: 0:undefine; 1:host; 2:client */ -+ int protocol; -+ spinlock_t lock; -+}; -+ -+struct otg_fsm_ops { -+ void (*chrg_vbus)(int on); -+ void (*drv_vbus)(int on); -+ void (*loc_conn)(int on); -+ void (*loc_sof)(int on); -+ void (*start_pulse)(void); -+ void (*add_timer)(void *timer); -+ void (*del_timer)(void *timer); -+ int (*start_host)(struct otg_fsm *fsm, int on); -+ int (*start_gadget)(struct otg_fsm *fsm, int on); -+}; -+ -+ -+static inline void otg_chrg_vbus(struct otg_fsm *fsm, int on) -+{ -+ fsm->ops->chrg_vbus(on); -+} -+ -+static inline void otg_drv_vbus(struct otg_fsm *fsm, int on) -+{ -+ if (fsm->drv_vbus != on) { -+ fsm->drv_vbus = on; -+ fsm->ops->drv_vbus(on); -+ } -+} -+ -+static inline void otg_loc_conn(struct otg_fsm *fsm, int on) -+{ -+ if (fsm->loc_conn != on) { -+ fsm->loc_conn = on; -+ fsm->ops->loc_conn(on); -+ } -+} -+ -+static inline void otg_loc_sof(struct otg_fsm *fsm, int on) -+{ -+ if (fsm->loc_sof != on) { -+ fsm->loc_sof = on; -+ fsm->ops->loc_sof(on); -+ } -+} -+ -+static inline void otg_start_pulse(struct otg_fsm *fsm) -+{ -+ fsm->ops->start_pulse(); -+} -+ -+static inline void otg_add_timer(struct otg_fsm *fsm, void *timer) -+{ -+ fsm->ops->add_timer(timer); -+} -+ -+static inline void otg_del_timer(struct otg_fsm *fsm, void *timer) -+{ -+ fsm->ops->del_timer(timer); -+} -+ -+int otg_statemachine(struct otg_fsm *fsm); ---- /dev/null -+++ b/drivers/usb/otg/usb.c -@@ -0,0 +1,76 @@ -+/* Copyright 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * Author: Li Yang <LeoLi@freescale.com> -+ * Jerry Huang <Chang-Ming.Huang@freescale.com> -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <linux/init.h> -+#include <linux/device.h> -+#include <linux/usb/otg.h> -+ -+#include <linux/io.h> -+#include <asm/irq.h> -+#include <asm/system.h> -+ -+ -+static struct otg_transceiver *transceiver; -+static struct resource *otg_resources; -+ -+/* -+ * otg_get_transceiver - find the (single) OTG transceiver driver -+ * -+ * Returns the transceiver driver, after getting a refcount to it; or -+ * null if there is no such transceiver. The caller is responsible for -+ * releasing that count. -+ */ -+struct otg_transceiver *otg_get_transceiver(void) -+{ -+ pr_debug("%s transceiver=0x%p\n", __func__, transceiver); -+ if (transceiver) -+ get_device(transceiver->dev); -+ -+ return transceiver; -+} -+EXPORT_SYMBOL(otg_get_transceiver); -+ -+int otg_set_transceiver(struct otg_transceiver *otg) -+{ -+ if (transceiver && otg) -+ return -EBUSY; -+ -+ transceiver = otg; -+ -+ return 0; -+} -+EXPORT_SYMBOL(otg_set_transceiver); -+ -+struct resource *otg_get_resources(void) -+{ -+ return otg_resources; -+} -+EXPORT_SYMBOL(otg_get_resources); -+ -+int otg_set_resources(struct resource *resources) -+{ -+ otg_resources = resources; -+ return 0; -+} -+EXPORT_SYMBOL(otg_set_resources); ---- a/include/linux/fsl_devices.h -+++ b/include/linux/fsl_devices.h -@@ -72,6 +72,18 @@ struct fsl_usb2_platform_data { - void (*exit)(struct platform_device *); - void __iomem *regs; /* ioremap'd register base */ - struct clk *clk; -+#ifdef CONFIG_COLDFIRE -+ u32 xcvr_type; /* PORTSC_PTS_* */ -+ char *name; /* pretty print */ -+ char *transceiver; /* transceiver name */ -+ unsigned power_budget; /* for hcd->power_budget */ -+ struct platform_device *pdev; -+ struct fsl_xcvr_ops *xcvr_ops; -+ -+ int (*gpio_usb_active) (void); -+ void (*gpio_usb_inactive) (void); -+ -+#endif - unsigned big_endian_mmio:1; - unsigned big_endian_desc:1; - unsigned es:1; /* need USBMODE:ES */ -@@ -79,6 +91,20 @@ struct fsl_usb2_platform_data { - unsigned have_sysif_regs:1; - unsigned invert_drvvbus:1; - unsigned invert_pwr_fault:1; -+#ifdef CONFIG_COLDFIRE -+ unsigned suspended:1; -+ unsigned already_suspended:1; -+#endif -+ /* register save area for suspend/resume */ -+ u32 pm_command; -+ u32 pm_status; -+ u32 pm_intr_enable; -+ u32 pm_frame_index; -+ u32 pm_segment; -+ u32 pm_frame_list; -+ u32 pm_async_next; -+ u32 pm_configured_flag; -+ u32 pm_portsc; - }; - - /* Flags in fsl_usb2_mph_platform_data */ ---- /dev/null -+++ b/include/linux/usb/fsl_usb2.h -@@ -0,0 +1,410 @@ -+/* -+ * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * Freescale USB device/endpoint management registers -+ * -+ * 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. -+ */ -+#ifndef __FSL_USB2_H -+#define __FSL_USB2_H -+ -+ -+ /* USB DR device mode registers (Little Endian) */ -+struct fsl_usb_device_regs { -+ /* Capability register */ -+ u32 id; -+ u32 res1[63]; -+ u16 caplength; /* Capability Register Length */ -+ u16 hciversion; /* Host Controller Interface Version */ -+ u32 hcsparams; /* Host Controller Structual Parameters */ -+ u32 hccparams; /* Host Controller Capability Parameters */ -+ u32 res2[5]; -+ u32 dciversion; /* Device Controller Interface Version */ -+ u32 dccparams; /* Device Controller Capability Parameters */ -+ u32 res3[6]; -+ /* Operation register */ -+ u32 usbcmd; /* USB Command Register */ -+ u32 usbsts; /* USB Status Register */ -+ u32 usbintr; /* USB Interrupt Enable Register */ -+ u32 frindex; /* Frame Index Register */ -+ u32 res4; -+ u32 deviceaddr; /* Device Address */ -+ u32 endpointlistaddr; /* Endpoint List Address Register */ -+ u32 res5; -+ u32 burstsize; /* Master Interface Data Burst Size Register */ -+ u32 txttfilltuning; /* Transmit FIFO Tuning Controls Register */ -+ u32 res6[2]; -+ u32 ulpiview; -+ u32 res7[3]; -+ u32 configflag; /* Configure Flag Register */ -+ u32 portsc1; /* Port 1 Status and Control Register */ -+ u32 res8[7]; -+ u32 otgsc; /* On-The-Go Status and Control */ -+ u32 usbmode; /* USB Mode Register */ -+ u32 endptsetupstat; /* Endpoint Setup Status Register */ -+ u32 endpointprime; /* Endpoint Initialization Register */ -+ u32 endptflush; /* Endpoint Flush Register */ -+ u32 endptstatus; /* Endpoint Status Register */ -+ u32 endptcomplete; /* Endpoint Complete Register */ -+ /* DCCPARAMS:DEN has the real number of device endpoints. */ -+ u32 endptctrl[16]; /* Endpoint Control Registers */ -+}; -+ -+ /* USB DR host mode registers (Little Endian) */ -+struct fsl_usb_host_regs { -+ /* Capability register */ -+ u32 id; -+ u32 res1[63]; -+ u16 caplength; /* Capability Register Length */ -+ u16 hciversion; /* Host Controller Interface Version */ -+ u32 hcsparams; /* Host Controller Structual Parameters */ -+ u32 hccparams; /* Host Controller Capability Parameters */ -+ u32 res2[5]; -+ u32 dciversion; /* Device Controller Interface Version */ -+ u32 dccparams; /* Device Controller Capability Parameters */ -+ u32 res3[6]; -+ /* Operation register */ -+ u32 usbcmd; /* USB Command Register */ -+ u32 usbsts; /* USB Status Register */ -+ u32 usbintr; /* USB Interrupt Enable Register */ -+ u32 frindex; /* Frame Index Register */ -+ u32 res4; -+ u32 periodiclistbase; /* Periodic Frame List Base Address Register */ -+ u32 asynclistaddr; /* Current Asynchronous List Address Register */ -+ u32 res5; -+ u32 burstsize; /* Master Interface Data Burst Size Register */ -+ u32 txttfilltuning; /* Transmit FIFO Tuning Controls Register */ -+ u32 res6[2]; -+ u32 ulpiview; -+ u32 res7[3]; -+ u32 configflag; /* Configure Flag Register */ -+ u32 portsc1; /* Port 1 Status and Control Register */ -+ u32 res8[7]; -+ u32 otgsc; /* On-The-Go Status and Control */ -+ u32 usbmode; /* USB Mode Register */ -+ u32 endptsetupstat; /* Endpoint Setup Status Register */ -+ u32 endpointprime; /* Endpoint Initialization Register */ -+ u32 endptflush; /* Endpoint Flush Register */ -+ u32 endptstatus; /* Endpoint Status Register */ -+ u32 endptcomplete; /* Endpoint Complete Register */ -+ /* DCCPARAMS:DEN has the real number of device endpoints. */ -+ u32 endptctrl[16]; /* Endpoint Control Registers */ -+}; -+ -+ /* non-EHCI USB system interface registers (Big Endian) */ -+struct usb_sys_interface { -+ u32 snoop1; -+ u32 snoop2; -+ u32 age_cnt_thresh; /* Age Count Threshold Register */ -+ u32 pri_ctrl; /* Priority Control Register */ -+ u32 si_ctrl; /* System Interface Control Register */ -+ u32 res[59]; -+ u32 control; /* General Purpose Control Register */ -+}; -+ -+/* ep0 transfer state */ -+#define WAIT_FOR_SETUP 0 -+#define DATA_STATE_XMIT 1 -+#define DATA_STATE_NEED_ZLP 2 -+#define WAIT_FOR_OUT_STATUS 3 -+#define DATA_STATE_RECV 4 -+ -+/* Frame Index Register Bit Masks */ -+#define USB_FRINDEX_MASKS 0x3fff -+ -+ -+ -+/* USBCMD Register Bit Masks */ -+#define USB_CMD_RUN_STOP 0x00000001 -+#define USB_CMD_CTRL_RESET 0x00000002 -+#define USB_CMD_PERIODIC_SCHEDULE_EN 0x00000010 -+#define USB_CMD_ASYNC_SCHEDULE_EN 0x00000020 -+#define USB_CMD_INT_AA_DOORBELL 0x00000040 -+#define USB_CMD_ASP 0x00000300 -+#define USB_CMD_ASYNC_SCH_PARK_EN 0x00000800 -+#define USB_CMD_SUTW 0x00002000 -+#define USB_CMD_ATDTW 0x00004000 -+#define USB_CMD_ITC 0x00FF0000 -+ -+/* bit 15,3,2 are frame list size */ -+#define USB_CMD_FRAME_SIZE_1024 0x00000000 -+#define USB_CMD_FRAME_SIZE_512 0x00000004 -+#define USB_CMD_FRAME_SIZE_256 0x00000008 -+#define USB_CMD_FRAME_SIZE_128 0x0000000C -+#define USB_CMD_FRAME_SIZE_64 0x00008000 -+#define USB_CMD_FRAME_SIZE_32 0x00008004 -+#define USB_CMD_FRAME_SIZE_16 0x00008008 -+#define USB_CMD_FRAME_SIZE_8 0x0000800C -+ -+/* bit 9-8 are async schedule park mode count */ -+#define USB_CMD_ASP_00 0x00000000 -+#define USB_CMD_ASP_01 0x00000100 -+#define USB_CMD_ASP_10 0x00000200 -+#define USB_CMD_ASP_11 0x00000300 -+#define USB_CMD_ASP_BIT_POS 8 -+ -+/* bit 23-16 are interrupt threshold control */ -+#define USB_CMD_ITC_NO_THRESHOLD 0x00000000 -+#define USB_CMD_ITC_1_MICRO_FRM 0x00010000 -+#define USB_CMD_ITC_2_MICRO_FRM 0x00020000 -+#define USB_CMD_ITC_4_MICRO_FRM 0x00040000 -+#define USB_CMD_ITC_8_MICRO_FRM 0x00080000 -+#define USB_CMD_ITC_16_MICRO_FRM 0x00100000 -+#define USB_CMD_ITC_32_MICRO_FRM 0x00200000 -+#define USB_CMD_ITC_64_MICRO_FRM 0x00400000 -+#define USB_CMD_ITC_BIT_POS 16 -+ -+ -+ -+ -+/* USB STS Register Bit Masks */ -+#define USB_STS_INT 0x00000001 -+#define USB_STS_ERR 0x00000002 -+#define USB_STS_PORT_CHANGE 0x00000004 -+#define USB_STS_FRM_LST_ROLL 0x00000008 -+#define USB_STS_SYS_ERR 0x00000010 -+#define USB_STS_IAA 0x00000020 -+#define USB_STS_RESET 0x00000040 -+#define USB_STS_SOF 0x00000080 -+#define USB_STS_SUSPEND 0x00000100 -+#define USB_STS_HC_HALTED 0x00001000 -+#define USB_STS_RCL 0x00002000 -+#define USB_STS_PERIODIC_SCHEDULE 0x00004000 -+#define USB_STS_ASYNC_SCHEDULE 0x00008000 -+ -+/* USB INTR Register Bit Masks */ -+#define USB_INTR_INT_EN 0x00000001 -+#define USB_INTR_ERR_INT_EN 0x00000002 -+#define USB_INTR_PTC_DETECT_EN 0x00000004 -+#define USB_INTR_FRM_LST_ROLL_EN 0x00000008 -+#define USB_INTR_SYS_ERR_EN 0x00000010 -+#define USB_INTR_ASYN_ADV_EN 0x00000020 -+#define USB_INTR_RESET_EN 0x00000040 -+#define USB_INTR_SOF_EN 0x00000080 -+#define USB_INTR_DEVICE_SUSPEND 0x00000100 -+ -+/* Device Address bit masks */ -+#define USB_DEVICE_ADDRESS_MASK 0xFE000000 -+#define USB_DEVICE_ADDRESS_BIT_POS 25 -+ -+/* endpoint list address bit masks */ -+#define USB_EP_LIST_ADDRESS_MASK 0xfffff800 -+ -+ -+/* x_PORTSCx */ -+/* bit 31-30 are port transceiver select */ -+#define PORTSCX_PTS_MASK (3 << 30) /* parallel xcvr select mask */ -+#define PORTSCX_PHY_TYPE_SEL PORTSCX_PTS_MASK -+#define PORTSCX_PTS_UTMI (0 << 30) /* UTMI/UTMI+ */ -+#define PORTSCX_PTS_PHILIPS (1 << 30) /* Philips classic */ -+#define PORTSCX_PTS_ULPI (2 << 30) /* ULPI */ -+#define PORTSCX_PTS_SERIAL (3 << 30) /* serial */ -+#define PORTSCX_PTS_FSLS PORTSCX_PTS_SERIAL -+#define PORTSCX_PTS_ONCHIP PORTSCX_PTS_FSLS -+ -+#define PORTSCX_STS (1 << 29) /* serial xcvr select */ -+ -+/* bit 28 is parallel transceiver width for UTMI interface */ -+#define PORTSCX_PTW_8BIT (0 << 28) /* 8 bit parallel xcvr */ -+#define PORTSCX_PTW_16BIT (1 << 28) /* 16 bi parallel xcvr */ -+ -+/* bit 27-26 are port speed */ -+#define PORTSCX_PORT_SPEED_FULL (0 << 26) -+#define PORTSCX_PORT_SPEED_LOW (1 << 26) -+#define PORTSCX_PORT_SPEED_HIGH (2 << 26) -+#define PORTSCX_PORT_SPEED_UNDEF (3 << 26) -+#define PORTSCX_PORT_SPEED_MASK (3 << 26) -+ -+/* phy low pwr suspend/clk disable */ -+#define PORTSCX_PHY_LOW_POWER_SPD (1 << 23) -+ -+/* bit 19-16 are port test control */ -+#define PORTSCX_PTC_DISABLE (0 << 16) -+#define PORTSCX_PTC_JSTATE (1 << 16) -+#define PORTSCX_PTC_KSTATE (2 << 16) -+#define PORTSCX_PTC_SEQNAK (3 << 16) /* SE0 (host)/NAK (device)*/ -+#define PORTSCX_PTC_PACKET (4 << 16) -+#define PORTSCX_PTC_FORCE_EN_HS (5 << 16) -+#define PORTSCX_PTC_FORCE_EN_FS (6 << 16) -+#define PORTSCX_PTC_FORCE_EN_LS (7 << 16) -+ -+ -+/* bit 15-14 are port indicator control */ -+#define PORTSCX_PIC_OFF (0 << 14) -+#define PORTSCX_PIC_AMBER (1 << 14) -+#define PORTSCX_PIC_GREEN (2 << 14) -+#define PORTSCX_PIC_UNDEF (3 << 14) -+ -+#define PORTSCX_PORT_POWER (1 << 12) /* port power */ -+ -+/* bit 11-10 are line status */ -+#define PORTSCX_LS_MASK (3 << 10) /* Line State mask */ -+#define PORTSCX_LS_SE0 (0 << 10) /* SE0 */ -+#define PORTSCX_LS_K_STATE (1 << 10) /* K-state */ -+#define PORTSCX_LS_J_STATE (2 << 10) /* J-state */ -+ -+#define PORTSCX_PORT_RESET (1 << 8) /* Port reset */ -+#define PORTSCX_PORT_SUSPEND (1 << 7) /* Suspend */ -+#define PORTSCX_PORT_FORCE_RESUME (1 << 6) /* Force port resume */ -+#define PORTSCX_OVER_CURRENT_CHG (1 << 5) /* over current change */ -+#define PORTSCX_OVER_CURRENT_ACT (1 << 4) /* over currrent active */ -+#define PORTSCX_PORT_EN_DIS_CHANGE (1 << 3) /* port {en,dis}able change*/ -+#define PORTSCX_PORT_ENABLE (1 << 2) /* port enabled */ -+#define PORTSCX_CONNECT_STATUS_CHANGE (1 << 1) /* connect status change */ -+#define PORTSCX_CURRENT_CONNECT_STATUS (1 << 0) /* current connect status */ -+ -+#define PORTSCX_W1C_BITS \ -+ (PORTSCX_CONNECT_STATUS_CHANGE | \ -+ PORTSCX_PORT_EN_DIS_CHANGE | \ -+ PORTSCX_OVER_CURRENT_CHG) -+ -+ -+ -+/* UOG_OTGSC Register Bits */ -+/* control bits: */ -+#define OTGSC_CTRL_VBUS_DISCHARGE (1 << 0) -+#define OTGSC_CTRL_VBUS_CHARGE (1 << 1) -+#define OTGSC_CTRL_OTG_TERM (1 << 3)/* controls DM pulldown */ -+#define OTGSC_CTRL_DATA_PULSING (1 << 4) -+#define OTGSC_CTRL_USB_ID_PU (1 << 5) /* enable ID pullup */ -+/* current status: (R/O) */ -+#define OTGSC_STS_USB_ID (1 << 8)/* 0=A-device 1=B-device */ -+#define OTGSC_STS_A_VBUS_VALID (1 << 9) -+#define OTGSC_STS_A_SESSION_VALID (1 << 10) -+#define OTGSC_STS_B_SESSION_VALID (1 << 11) -+#define OTGSC_STS_B_SESSION_END (1 << 12) -+#define OTGSC_STS_1ms_TIMER (1 << 13) -+#define OTGSC_STS_DATA_PULSE (1 << 14) -+/* interrupt status: (write to clear) */ -+#define OTGSC_INTSTS_MASK (0x7f << 16) -+#define OTGSC_INTSTS_USB_ID (1 << 16) -+#define OTGSC_INTSTS_A_VBUS_VALID (1 << 17) -+#define OTGSC_INTSTS_A_SESSION_VALID (1 << 18) -+#define OTGSC_INTSTS_B_SESSION_VALID (1 << 19) -+#define OTGSC_INTSTS_B_SESSION_END (1 << 20) -+#define OTGSC_INTSTS_1MS_TIMER (1 << 21) -+#define OTGSC_INTSTS_DATA_PULSE (1 << 22) -+/* interrupt enables: */ -+#define OTGSC_IE_MASK (0x7f << 24) -+#define OTGSC_IE_USB_ID (1 << 24) -+#define OTGSC_IE_A_VBUS_VALID (1 << 25) -+#define OTGSC_IE_A_SESSION_VALID (1 << 26) -+#define OTGSC_IE_B_SESSION_VALID (1 << 27) -+#define OTGSC_IE_B_SESSION_END (1 << 28) -+#define OTGSC_IE_1ms_TIMER (1 << 29) -+#define OTGSC_IE_DATA_PULSE (1 << 30) -+ -+#if 1 /* DDD FIXME these here for compatibility between my names and Leo's */ -+/* OTG interrupt enable bit masks */ -+#define OTGSC_INTERRUPT_ENABLE_BITS_MASK OTGSC_IE_MASK -+ -+/* OTG interrupt status bit masks */ -+#define OTGSC_INTERRUPT_STATUS_BITS_MASK OTGSC_INTSTS_MASK -+#endif -+ -+ -+ -+/* x_USBMODE */ -+#undef USBMODE_SDIS /* defined as bit 3 in drivers/usb/host/ehci.h */ -+#define USBMODE_SDIS (1 << 4) /* stream disable mode */ -+#define USBMODE_SLOM (1 << 3) /* setup lockout mode */ -+#define USBMODE_ES (1 << 2) /* (big) endian select */ -+#define USBMODE_CM_MASK (3 << 0) /* controller mode mask */ -+#define USBMODE_CM_HOST (3 << 0) /* host */ -+#define USBMODE_CM_DEVICE (2 << 0) /* device */ -+ -+/* DDD for compatibility for now */ -+#define USB_MODE_CTRL_MODE_IDLE USBMODE_CM_IDLE -+#define USB_MODE_CTRL_MODE_DEVICE USBMODE_CM_DEVICE -+#define USB_MODE_CTRL_MODE_HOST USBMODE_CM_HOST -+#define USB_MODE_SETUP_LOCK_OFF USBMODE_SLOM -+#define USB_MODE_STREAM_DISABLE USBMODE_SDIS -+ -+ -+/* 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 -+ -+ -+/* Endpoint Flush Register */ -+#define EPFLUSH_TX_OFFSET 0x00010000 -+#define EPFLUSH_RX_OFFSET 0x00000000 -+ -+/* Endpoint Setup Status bit masks */ -+#define EP_SETUP_STATUS_MASK 0x0000003F -+#define EP_SETUP_STATUS_EP0 0x00000001 -+ -+/* ENDPOINTCTRLx Register Bit Masks */ -+#define EPCTRL_TX_ENABLE 0x00800000 -+#define EPCTRL_TX_DATA_TOGGLE_RST 0x00400000 /* Not EP0 */ -+#define EPCTRL_TX_DATA_TOGGLE_INH 0x00200000 /* Not EP0 */ -+#define EPCTRL_TX_TYPE 0x000C0000 -+#define EPCTRL_TX_DATA_SOURCE 0x00020000 /* Not EP0 */ -+#define EPCTRL_TX_EP_STALL 0x00010000 -+#define EPCTRL_RX_ENABLE 0x00000080 -+#define EPCTRL_RX_DATA_TOGGLE_RST 0x00000040 /* Not EP0 */ -+#define EPCTRL_RX_DATA_TOGGLE_INH 0x00000020 /* Not EP0 */ -+#define EPCTRL_RX_TYPE 0x0000000C -+#define EPCTRL_RX_DATA_SINK 0x00000002 /* Not EP0 */ -+#define EPCTRL_RX_EP_STALL 0x00000001 -+ -+/* bit 19-18 and 3-2 are endpoint type */ -+#define EPCTRL_EP_TYPE_CONTROL 0 -+#define EPCTRL_EP_TYPE_ISO 1 -+#define EPCTRL_EP_TYPE_BULK 2 -+#define EPCTRL_EP_TYPE_INTERRUPT 3 -+#define EPCTRL_TX_EP_TYPE_SHIFT 18 -+#define EPCTRL_RX_EP_TYPE_SHIFT 2 -+ -+/* pri_ctrl Register Bit Masks */ -+#define PRI_CTRL_PRI_LVL1 0x0000000C -+#define PRI_CTRL_PRI_LVL0 0x00000003 -+ -+/* si_ctrl Register Bit Masks */ -+#define SI_CTRL_ERR_DISABLE 0x00000010 -+#define SI_CTRL_IDRC_DISABLE 0x00000008 -+#define SI_CTRL_RD_SAFE_EN 0x00000004 -+#define SI_CTRL_RD_PREFETCH_DISABLE 0x00000002 -+#define SI_CTRL_RD_PREFEFETCH_VAL 0x00000001 -+ -+ -+/* control Register Bit Masks */ -+#define USB_CTRL_IOENB 0x00000004 -+#define USB_CTRL_ULPI_INT0EN 0x00000001 -+ -+ -+/* Endpoint Transfer Descriptor bit Masks */ -+#define DTD_NEXT_TERMINATE 0x00000001 -+#define DTD_IOC 0x00008000 -+#define DTD_STATUS_ACTIVE 0x00000080 -+#define DTD_STATUS_HALTED 0x00000040 -+#define DTD_STATUS_DATA_BUFF_ERR 0x00000020 -+#define DTD_STATUS_TRANSACTION_ERR 0x00000008 -+#define DTD_RESERVED_FIELDS 0x80007300 -+#define DTD_ADDR_MASK 0xFFFFFFE0 -+#define DTD_PACKET_SIZE 0x7FFF0000 -+#define DTD_LENGTH_BIT_POS 16 -+#define DTD_ERROR_MASK (DTD_STATUS_HALTED | \ -+ DTD_STATUS_DATA_BUFF_ERR | \ -+ DTD_STATUS_TRANSACTION_ERR) -+/* Alignment requirements; must be a power of two */ -+#define DTD_ALIGNMENT 0x20 -+#define QH_ALIGNMENT 2048 -+ -+/* Controller dma boundary */ -+#define UDC_DMA_BOUNDARY 0x1000 -+ -+#endif /* __FSL_USB2_H */ ---- /dev/null -+++ b/include/linux/usb/fsl_xcvr.h -@@ -0,0 +1,36 @@ -+/* -+ * Copyright 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * 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. -+ */ -+ -+/** -+ * struct fsl_xcvr_ops - USB transceiver operations -+ * -+ * @xcvr_type: one of PORTSCX_PTS_{UTMI,SERIAL,ULPI} -+ * @init: transceiver- and board-specific initialization function -+ * @uninit: transceiver- and board-specific uninitialization function -+ * @set_host: -+ * @set_device: -+ * -+ */ -+struct fsl_xcvr_ops { -+ char *name; -+ u32 xcvr_type; -+ struct fsl_usb2_platform_data *pdata; -+ -+ void (*init)(struct fsl_xcvr_ops *ops); -+ void (*uninit)(struct fsl_xcvr_ops *ops); -+ void (*suspend)(struct fsl_xcvr_ops *ops); -+ void (*set_host)(void); -+ void (*set_device)(void); -+ void (*set_vbus_power)(struct fsl_xcvr_ops *ops, int on); -+ void (*set_remote_wakeup)(u32 *view); -+ void (*pullup)(int on); -+}; -+ -+extern void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops); -+extern void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops); ---- a/include/linux/usb/otg.h -+++ b/include/linux/usb/otg.h -@@ -164,7 +164,7 @@ otg_shutdown(struct otg_transceiver *otg - } - - /* for usb host and peripheral controller drivers */ --#ifdef CONFIG_USB_OTG_UTILS -+#if defined(CONFIG_USB_OTG_UTILS) || defined(CONFIG_COLDFIRE) - extern struct otg_transceiver *otg_get_transceiver(void); - extern void otg_put_transceiver(struct otg_transceiver *); - #else |