Hi,

Here's an update to OMAP's OHCI support, matching the latest for
the linux-omap BK tree.

Please merge.

- Dave
This updates the OMAP OHCI support to match the latest from the
Linux-OMAP tree.  Notable changes from the preceding version:

  - Use the new USB init model (arch/arm/mach-omap/usb.c).

  - The OMAP-specific bus is gone; it now uses platform_device.
    (Update from Tony Lindgren.)

  - Works on the H2 board, which requires the external isp1301
    transceiver even in non-OTG configurations.

  - Adds OTG support.

  - Adds basic power management calls.

The mach-omap/Kconfig file in the main Linux tree is a bit out of
date, it doesn't know about CONFIG_ARCH_OMAP_OTG (for the OMAPs that
have OTG silicon).

Signed-off-by: David Brownell <[EMAIL PROTECTED]>


--- xu26/drivers/usb/host/Kconfig	2004-04-14 18:26:38.000000000 -0700
+++ gadget-2.6/drivers/usb/host/Kconfig	2004-08-24 13:37:26.084799192 -0700
@@ -52,6 +52,7 @@
 config USB_OHCI_HCD
 	tristate "OHCI HCD support"
 	depends on USB
+	select ISP1301_OMAP if MACH_OMAP_H2
 	---help---
 	  The Open Host Controller Interface (OHCI) is a standard for accessing
 	  USB 1.1 host controller hardware.  It does more in hardware than Intel's
--- xu26/drivers/usb/host/ohci.h	2004-06-18 14:14:20.000000000 -0700
+++ gadget-2.6/drivers/usb/host/ohci.h	2004-08-24 13:38:00.769526312 -0700
@@ -360,6 +360,13 @@
  	struct ed		*periodic [NUM_INTS];	/* shadow int_table */
 
 	/*
+	 * OTG controllers and transceivers need software interaction;
+	 * other external transceivers should be software-transparent 
+	 */
+	struct otg_transceiver	*transceiver;
+	unsigned		power_budget;
+
+	/*
 	 * memory management for queue data structures
 	 */
 	struct dma_pool		*td_cache;
--- xu26/drivers/usb/host/ohci-hcd.c	2004-07-14 21:42:05.000000000 -0700
+++ gadget-2.6/drivers/usb/host/ohci-hcd.c	2004-08-24 13:38:00.759527832 -0700
@@ -97,6 +97,7 @@
 #include <linux/list.h>
 #include <linux/interrupt.h>  /* for in_interrupt () */
 #include <linux/usb.h>
+#include <linux/usb_otg.h>
 #include "../core/hcd.h"
 #include <linux/dma-mapping.h> 
 #include <linux/dmapool.h>    /* needed by ohci-mem.c when no PCI */
@@ -693,7 +694,7 @@
 
 /* must not be called from interrupt context */
 
-#ifdef CONFIG_PM
+#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
 
 static void mark_children_gone (struct usb_device *dev)
 {
--- xu26/drivers/usb/host/ohci-omap.c	2004-08-24 13:11:22.000000000 -0700
+++ gadget-2.6/drivers/usb/host/ohci-omap.c	2004-08-24 12:27:05.000000000 -0700
@@ -2,27 +2,30 @@
  * OHCI HCD (Host Controller Driver) for USB.
  *
  * (C) Copyright 1999 Roman Weissgaerber <[EMAIL PROTECTED]>
- * (C) Copyright 2000-2002 David Brownell <[EMAIL PROTECTED]>
+ * (C) Copyright 2000-2004 David Brownell <[EMAIL PROTECTED]>
  * (C) Copyright 2002 Hewlett-Packard Company
  * 
  * OMAP Bus Glue
  *
  * Written by Christopher Hoover <[EMAIL PROTECTED]>
- * Based on fragments of previous driver by Rusell King et al.
+ * Based on fragments of previous driver by Russell King et al.
  *
  * Modified for OMAP from ohci-sa1111.c by Tony Lindgren <[EMAIL PROTECTED]>
  * Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc.
  *
  * This file is licenced under the GPL.
  */
- 
+
 #include <asm/hardware.h>
 #include <asm/io.h>
+#include <asm/mach-types.h>
 
-#include <asm/arch/bus.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/irqs.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/fpga.h>
+#include <asm/arch/usb.h>
 
 #include "ohci-omap.h"
 
@@ -34,122 +37,53 @@
 extern int ocpi_enable(void);
 
 /*
- * Use the first port only by default. Override with hmc_mode option.
- *
- * NOTE: Many OMAP-1510 Innovators supposedly have bad wiring for the USB ports
- *       1 & 2, so only port 0 will work. To use the OHCI on the first port, use 
- *       the Innovator USB client cable with a client-to-client connector and modify
- *       either the cable or the hub to feed 5V VBUS back to Innovator. VBUS should
- *       be the red lead in the cable.
- *
- *       To mount USB hard disk as root, see the patch for do_mounts.c that tries 
- *       remounting the root, and use root=0801 if your root is on sda1. Does not 
- *       work with devfs.
- */
-static int default_hmc_mode = 16;
-static int hmc_mode = 1234;
-
-/*
- * Set the USB host pin multiplexing and the selected HMC mode
- */
-static int omap_usb_set_hmc_mode(int hmc_mode)
-{
-	unsigned int val;
-
-	switch (hmc_mode) {
-	case 0:
-		/* 0: function, 1: disabled, 2: disabled */
-		omap_cfg_reg(W4_USB_PUEN);
-		omap_cfg_reg(R18_1510_USB_GPIO0);
-		break;
-	case 4:
-		/* 0: function 1: host 2: host */
-		omap_cfg_reg(usb1_speed);
-		omap_cfg_reg(usb1_susp);
-		omap_cfg_reg(usb1_seo);
-		omap_cfg_reg(usb1_txen);
-		omap_cfg_reg(usb1_txd);
-		omap_cfg_reg(usb1_vp);
-		omap_cfg_reg(usb1_vm);
-		omap_cfg_reg(usb1_rcv);
-		omap_cfg_reg(usb2_susp);
-		omap_cfg_reg(usb2_seo);
-		omap_cfg_reg(usb2_txen);
-		omap_cfg_reg(usb2_txd);
-		omap_cfg_reg(usb2_vp);
-		omap_cfg_reg(usb2_vm);
-		omap_cfg_reg(usb2_rcv);
-		break;
-	case 16:
-		/* 0: host, 1: disabled, 2: disabled */
-		omap_cfg_reg(W9_USB0_TXEN);
-		omap_cfg_reg(AA9_USB0_VP);
-		omap_cfg_reg(Y5_USB0_RCV);
-		omap_cfg_reg(R9_USB0_VM);
-		omap_cfg_reg(V6_USB0_TXD);
-		omap_cfg_reg(W5_USB0_SE0);
-		break;
-	default:
-		printk("Unknown USB host configuration: %i\n", hmc_mode);
-		return -ENODEV;
-	}
-
-	/* Write the selected HMC mode */
-	val = readl(MOD_CONF_CTRL_0) & ~HMC_CLEAR;
-	val |= (hmc_mode << 1);
-	writel(val, MOD_CONF_CTRL_0);
-
-	return 0;
-}
-
-/*
  * OHCI clock initialization for OMAP-1510 and 1610
  */
 static int omap_ohci_clock_power(int on)
 {
 	if (on) {
-		if (cpu_is_omap_1510()) {
+		if (cpu_is_omap1510()) {
 			/* Use DPLL, not APLL */
-			writel(readl(ULPD_APLL_CTRL_REG) & ~APLL_NDPLL_SWITCH,
-			       ULPD_APLL_CTRL_REG);
+			omap_writel(omap_readl(ULPD_APLL_CTRL) & ~APLL_NDPLL_SWITCH,
+			       ULPD_APLL_CTRL);
 
 			/* Enable DPLL */
-			writel(readl(ULPD_DPLL_CTRL_REG) | DPLL_PLL_ENABLE,
-			       ULPD_DPLL_CTRL_REG);
+			omap_writel(omap_readl(ULPD_DPLL_CTRL) | DPLL_PLL_ENABLE,
+			       ULPD_DPLL_CTRL);
 
 			/* Software request for USB 48MHz clock */
-			writel(readl(ULPD_SOFT_REQ_REG) | SOFT_REQ_REG_REQ,
-			       ULPD_SOFT_REQ_REG);
+			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_REQ_REG_REQ,
+			       ULPD_SOFT_REQ);
 
-			while (!(readl(ULPD_DPLL_CTRL_REG) & DPLL_LOCK));
+			while (!(omap_readl(ULPD_DPLL_CTRL) & DPLL_LOCK));
 		}
 
-		if (cpu_is_omap_1610()) {
+		if (cpu_is_omap16xx()) {
 			/* Enable OHCI */
-			writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_OTG_REQ,
-				ULPD_SOFT_REQ_REG);
+			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_OTG_REQ,
+				ULPD_SOFT_REQ);
 
 			/* USB host clock request if not using OTG */
-			writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_REQ,
-				ULPD_SOFT_REQ_REG);
+			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_REQ,
+				ULPD_SOFT_REQ);
 
-			writel(readl(ULPD_STATUS_REQ_REG) | USB_HOST_DPLL_REQ,
-			     ULPD_STATUS_REQ_REG);
+			omap_writel(omap_readl(ULPD_STATUS_REQ) | USB_HOST_DPLL_REQ,
+			     ULPD_STATUS_REQ);
 		}
 
 		/* Enable 48MHz clock to USB */
-		writel(readl(ULPD_CLOCK_CTRL_REG) | USB_MCLK_EN,
-		       ULPD_CLOCK_CTRL_REG);
+		omap_writel(omap_readl(ULPD_CLOCK_CTRL) | USB_MCLK_EN,
+		       ULPD_CLOCK_CTRL);
 
-		writel(readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK),
+		omap_writel(omap_readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK),
 		       ARM_IDLECT2);
 
-		writel(readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN,
+		omap_writel(omap_readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN,
 		       MOD_CONF_CTRL_0);
 	} else {
 		/* Disable 48MHz clock to USB */
-		writel(readl(ULPD_CLOCK_CTRL_REG) & ~USB_MCLK_EN,
-		       ULPD_CLOCK_CTRL_REG);
+		omap_writel(omap_readl(ULPD_CLOCK_CTRL) & ~USB_MCLK_EN,
+		       ULPD_CLOCK_CTRL);
 
 		/* FIXME: The DPLL stays on for now */
 	}
@@ -163,13 +97,19 @@
 static int omap_ohci_transceiver_power(int on)
 {
 	if (on) {
-		if (omap_is_innovator())
-			writel(readl(OMAP1510_FPGA_HOST_CTRL) | 0x20, 
-			       OMAP1510_FPGA_HOST_CTRL);
+		if (machine_is_omap_innovator() && cpu_is_omap1510())
+			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) | 0x20, 
+			       INNOVATOR_FPGA_CAM_USB_CONTROL);
+		else if (machine_is_omap_osk()) {
+			/* FIXME: GPIO1 -> 1 on the TPS65010 I2C chip */
+		}
 	} else {
-		if (omap_is_innovator())
-			writel(readl(OMAP1510_FPGA_HOST_CTRL) & ~0x20, 
-			       OMAP1510_FPGA_HOST_CTRL);
+		if (machine_is_omap_innovator() && cpu_is_omap1510())
+			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) & ~0x20, 
+			       INNOVATOR_FPGA_CAM_USB_CONTROL);
+		else if (machine_is_omap_osk()) {
+			/* FIXME: GPIO1 -> 0 on the TPS65010 I2C chip */
+		}
 	}
 
 	return 0;
@@ -181,10 +121,10 @@
 static int omap_1510_local_bus_power(int on)
 {
 	if (on) {
-		writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL);
+		omap_writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL);
 		udelay(200);
 	} else {
-		writel(0, OMAP1510_LB_MMU_CTL);
+		omap_writel(0, OMAP1510_LB_MMU_CTL);
 	}
 
 	return 0;
@@ -193,8 +133,8 @@
 /*
  * OMAP-1510 specific Local Bus initialization
  * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE.
- *       See also arch/mach-omap/memory.h for __virt_to_bus() and 
- *       __bus_to_virt() which need to match with the physical 
+ *       See also arch/mach-omap/memory.h for __virt_to_dma() and 
+ *       __dma_to_virt() which need to match with the physical 
  *       Local Bus address below.
  */
 static int omap_1510_local_bus_init(void)
@@ -202,125 +142,115 @@
 	unsigned int tlb;
 	unsigned long lbaddr, physaddr;
 
-	writel((readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, 
+	omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, 
 	       OMAP1510_LB_CLOCK_DIV);
 
 	/* Configure the Local Bus MMU table */
 	for (tlb = 0; tlb < OMAP1510_LB_MEMSIZE; tlb++) {
 		lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET;
 		physaddr = tlb * 0x00100000 + PHYS_OFFSET;
-		writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
-		writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, 
+		omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
+		omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, 
 		       OMAP1510_LB_MMU_CAM_L);
-		writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
-		writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
-		writel(tlb << 4, OMAP1510_LB_MMU_LCK);
-		writel(0x1, OMAP1510_LB_MMU_LD_TLB);
+		omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
+		omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
+		omap_writel(tlb << 4, OMAP1510_LB_MMU_LCK);
+		omap_writel(0x1, OMAP1510_LB_MMU_LD_TLB);
 	}
 
 	/* Enable the walking table */
-	writel(readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL);
+	omap_writel(omap_readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL);
 	udelay(200);
 
 	return 0;
 }
 
-/*
- * OMAP-1610 specific hardware initialization
- *
- * Intended to configure OMAP-1610 USB host and OTG ports depending on 
- * the HMC mode selected.
- *
- * FIXME: Currently only supports alternate ping group 2 mode, should
- *        be easy to modify for other configurations once there is some
- *        hardware to test with.
- */
-static int omap_1610_usb_init(int mode)
-{
-	u_int val = 0;
-
-	/* Configure the OMAP transceiver settings */
-	val |= (1 << 8); /* CONF_USB2_UNI TRM p 15-205*/
-	val |= (4 << 4); /* TRM p 5-59, p 15-157 (1224) */
-
-	//val |= (1 << 3); /* Isolate integrated transceiver from port 0 */
-	val |= (1 << 2); /* Disable pulldown on integrated transceiver DM */
-	val |= (1 << 1); /* Disable pulldown on integraded transceiver DP */
-
-	writel(val, USB_TRANSCEIVER_CTRL);
-
-	/* Set the USB0_TRX_MODE */
-	val = 0;
-	val &= ~OTG_IDLE_EN;
-	val &= ~DEV_IDLE_EN;
-	val &= ~(7 << 16);	/* Clear USB0_TRX_MODE */
-	val |= (3 << 16);	/* 0 or 3, 6-wire DAT/SE0, TRM p 15-159 */
-	writel(val, OTG_SYSCON_1);
-
-	/* 
-	 * Control via OTG, see TRM p 15-163
-	 */
-	val = 0;
-	//val |= 1;		/* REVISIT: Enable OTG = 1 */
+#ifdef	CONFIG_USB_OTG
 
-	/* Control via OTG */
-	val &= ~HMC_PADEN;
-	val &= ~OTG_PADEN;
-	val |= UHOST_EN;	
-
-	val &= ~0x3f;		/* Clear HMC mode */
-	val |= mode;		/* Set HMC mode */
-	val &= ~(7 << 16);	/* Clear ASE0_BRST */
-	val |= (4 << 16);	/* Must be 4 */
-	val |= USBX_SYNCHRO;	/* Must be set */
-	val |= SRP_VBUS;
-	writel(val, OTG_SYSCON_2);
+static void start_hnp(struct ohci_hcd *ohci)
+{
+	const unsigned	port = ohci->hcd.self.otg_port - 1;
+	unsigned long	flags;
 
-	/* Enable OTG idle */
-	//writel(readl(OTG_SYSCON_1) | OTG_IDLE_EN, OTG_SYSCON_1);
+	otg_start_hnp(ohci->transceiver);
 
-	return 0;
+	local_irq_save(flags);
+	ohci->transceiver->state = OTG_STATE_A_SUSPEND;
+	writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [port]);
+	OTG_CTRL_REG &= ~OTG_A_BUSREQ;
+	local_irq_restore(flags);
 }
 
+#endif
+
 /*-------------------------------------------------------------------------*/
 
-static void omap_start_hc(struct omap_dev *dev)
+static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
 {
-	printk(KERN_DEBUG __FILE__ 
-	       ": starting OMAP OHCI USB Controller\n");
+	struct omap_usb_config	*config = pdev->dev.platform_data;
+	int			need_transceiver = (config->otg != 0);
 
-	/* 
-	 * Set the HMC mode for the USB ports
-	 */
-#if 0
-	/* See note about the Innovator wiring above */
-	if (omap_is_innovator())
-		hmc_mode = 4;	/* 0: function 1: host 2: host */
-#endif
+	dev_dbg(&pdev->dev, "starting USB Controller\n");
+
+	if (config->otg) {
+		ohci->hcd.self.otg_port = config->otg;
+		/* default/minimum OTG power budget:  8 mA */
+		ohci->power_budget = 8;
+	}
 
-	if (cpu_is_omap_1610())
+	/* boards can use OTG transceivers in non-OTG modes */
+	need_transceiver = need_transceiver
+			|| machine_is_omap_h2();
+
+	if (cpu_is_omap16xx())
 		ocpi_enable();
 
-	omap_usb_set_hmc_mode(hmc_mode);
+#ifdef	CONFIG_ARCH_OMAP_OTG
+	if (need_transceiver) {
+		ohci->transceiver = otg_get_transceiver();
+		if (ohci->transceiver) {
+			int	status = otg_set_host(ohci->transceiver,
+						&ohci->hcd.self);
+			dev_dbg(&pdev->dev, "init %s transceiver, status %d\n",
+					ohci->transceiver->label, status);
+			if (status) {
+				if (ohci->transceiver)
+					put_device(ohci->transceiver->dev);
+				return status;
+			}
+		} else {
+			dev_err(&pdev->dev, "can't find transceiver\n");
+			return -ENODEV;
+		}
+	}
+#endif
+
+	if (machine_is_omap_osk()) {
+		omap_request_gpio(9);
+		omap_set_gpio_direction(9, 1);
+		omap_set_gpio_dataout(9, 1);
+	}
 
 	omap_ohci_clock_power(1);
+
 	omap_ohci_transceiver_power(1);
 
-	if (cpu_is_omap_1510()) {
+	if (cpu_is_omap1510()) {
 		omap_1510_local_bus_power(1);
 		omap_1510_local_bus_init();
 	}
 
-	if (cpu_is_omap_1610())
-		omap_1610_usb_init(hmc_mode);
+	/* board init will have already handled HMC and mux setup.
+	 * any external transceiver should already be initialized
+	 * too, so all configured ports use the right signaling now.
+	 */
 
-	//omap_enable_device(dev);
+	return 0;
 }
 
-static void omap_stop_hc(struct omap_dev *dev)
+static void omap_stop_hc(struct platform_device *pdev)
 {
-	printk(KERN_DEBUG __FILE__ 
-	       ": stopping OMAP OHCI USB Controller\n");
+	dev_dbg(&pdev->dev, "stopping USB Controller\n");
 
 	/*
 	 * FIXME: Put the USB host controller into reset.
@@ -336,16 +266,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static irqreturn_t usb_hcd_omap_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
-{
-	struct usb_hcd *hcd = __hcd;
-
-	return usb_hcd_irq(irq, hcd, r);
-}
-
-/*-------------------------------------------------------------------------*/
-
-void usb_hcd_omap_remove (struct usb_hcd *, struct omap_dev *);
+void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
 
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
@@ -358,59 +279,71 @@
  * Allocates basic resources for this USB host controller, and
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
- *
- * Store this function in the HCD's struct pci_driver as probe().
  */
 int usb_hcd_omap_probe (const struct hc_driver *driver,
-			  struct usb_hcd **hcd_out,
-			  struct omap_dev *dev)
+			  struct platform_device *pdev)
 {
 	int retval;
 	struct usb_hcd *hcd = 0;
+	struct ohci_hcd *ohci;
 
-	if (!request_mem_region(dev->res.start, 
-				dev->res.end - dev->res.start + 1, hcd_name)) {
-		dbg("request_mem_region failed");
-		return -EBUSY;
+	if (pdev->num_resources != 2) {
+		printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", 
+		       pdev->num_resources);
+		return -ENODEV;
+	}
+
+	if (pdev->resource[0].flags != IORESOURCE_MEM 
+	    || pdev->resource[1].flags != IORESOURCE_IRQ) {
+		printk(KERN_ERR "hcd probe: invalid resource type\n");
+		return -ENODEV;
 	}
 
-	omap_start_hc(dev);
+	if (!request_mem_region(pdev->resource[0].start, 
+				pdev->resource[0].end - pdev->resource[0].start + 1, hcd_name)) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		return -EBUSY;
+	}
 
 	hcd = driver->hcd_alloc ();
 	if (hcd == NULL){
-		dbg ("hcd_alloc failed");
+		dev_dbg(&pdev->dev, "hcd_alloc failed\n");
 		retval = -ENOMEM;
 		goto err1;
 	}
+	dev_set_drvdata(&pdev->dev, hcd);
+	ohci = hcd_to_ohci(hcd);
 
 	hcd->driver = (struct hc_driver *) driver;
 	hcd->description = driver->description;
-	hcd->irq = dev->irq[0];
-	hcd->regs = dev->mapbase;
-	hcd->self.controller = &dev->dev;
+	hcd->irq = pdev->resource[1].start;
+	hcd->regs = (void *)pdev->resource[0].start;
+	hcd->self.controller = &pdev->dev;
+
+	retval = omap_start_hc(ohci, pdev);
+	if (retval < 0)
+		goto err2;
 
 	retval = hcd_buffer_create (hcd);
 	if (retval != 0) {
-		dbg ("pool alloc fail");
+		dev_dbg(&pdev->dev, "pool alloc fail\n");
 		goto err1;
 	}
 
-	retval = request_irq (hcd->irq, 
-			      usb_hcd_omap_hcim_irq, 
+	retval = request_irq (hcd->irq, usb_hcd_irq, 
 			      SA_INTERRUPT, hcd->description, hcd);
 	if (retval != 0) {
-		dbg("request_irq failed");
+		dev_dbg(&pdev->dev, "request_irq failed\n");
 		retval = -EBUSY;
 		goto err2;
 	}
 
-	info ("%s (OMAP) at 0x%p, irq %d\n",
-	      hcd->description, hcd->regs, hcd->irq);
+	dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
 
 	usb_bus_init (&hcd->self);
 	hcd->self.op = &usb_hcd_operations;
 	hcd->self.hcpriv = (void *) hcd;
-	hcd->self.bus_name = "omap";
+	hcd->self.bus_name = pdev->dev.bus_id;
 	hcd->product_desc = "OMAP OHCI";
 
 	INIT_LIST_HEAD (&hcd->dev_list);
@@ -418,11 +351,10 @@
 
 	if ((retval = driver->start (hcd)) < 0) 
 	{
-		usb_hcd_omap_remove(hcd, dev);
+		usb_hcd_omap_remove(hcd, pdev);
 		return retval;
 	}
 
-	*hcd_out = hcd;
 	return 0;
 
  err2:
@@ -430,10 +362,12 @@
 	if (hcd)
 		driver->hcd_free(hcd);
  err1:
-	omap_stop_hc(dev);
+	omap_stop_hc(pdev);
 
-	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
+	release_mem_region(pdev->resource[0].start, 
+			   pdev->resource[0].end - pdev->resource[0].start + 1);
 
+	dev_set_drvdata(&pdev->dev, 0);
 	return retval;
 }
 
@@ -451,24 +385,27 @@
  * context, normally "rmmod", "apmd", or something similar.
  *
  */
-void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
+void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
 	void *base;
 
-	info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
+	dev_info(&pdev->dev, "remove: state %x\n", hcd->state);
 
 	if (in_interrupt ())
 		BUG ();
 
 	hcd->state = USB_STATE_QUIESCING;
 
-	dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
+	dev_dbg(&pdev->dev, "roothub graceful disconnect\n");
 	usb_disconnect (&hcd->self.root_hub);
 
 	hcd->driver->stop (hcd);
 	hcd_buffer_destroy (hcd);
 	hcd->state = USB_STATE_HALT;
 
+	if (machine_is_omap_osk())
+		omap_free_gpio(9);
+
 	free_irq (hcd->irq, hcd);
 
 	usb_deregister_bus (&hcd->self);
@@ -476,9 +413,10 @@
 	base = hcd->regs;
 	hcd->driver->hcd_free (hcd);
 
-	omap_stop_hc(dev);
+	omap_stop_hc(pdev);
 
-	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
+	release_mem_region(pdev->resource[0].start, 
+			   pdev->resource[0].end - pdev->resource[0].start + 1);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -486,11 +424,13 @@
 static int __devinit
 ohci_omap_start (struct usb_hcd *hcd)
 {
+	struct omap_usb_config *config;
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		ret;
 
-	ohci->hcca = dma_alloc_consistent (hcd->self.controller,
-			sizeof *ohci->hcca, &ohci->hcca_dma);
+	config = hcd->self.controller->platform_data;
+	ohci->hcca = dma_alloc_coherent (hcd->self.controller,
+			sizeof *ohci->hcca, &ohci->hcca_dma, 0);
 	if (!ohci->hcca)
 		return -ENOMEM;
 
@@ -500,6 +440,10 @@
 		return ret;
 	}
 	ohci->regs = hcd->regs;
+
+	if (config->otg || config->rwc)
+		writel(OHCI_CTRL_RWC, &ohci->regs->control);
+
 	if (hc_reset (ohci) < 0) {
 		ohci_stop (hcd);
 		return -ENODEV;
@@ -510,6 +454,9 @@
 		ohci_stop (hcd);
 		return -EBUSY;
 	}
+	if (ohci->power_budget)
+		hub_set_power_budget(ohci->hcd.self.root_hub,
+					ohci->power_budget);
 	create_debug_files (ohci);
 
 #ifdef	DEBUG
@@ -533,10 +480,6 @@
 	 * basic lifecycle operations
 	 */
 	.start =		ohci_omap_start,
-#ifdef	CONFIG_PM
-	/* suspend:		ohci_omap_suspend,  -- tbd */
-	/* resume:		ohci_omap_resume,   -- tbd */
-#endif
 	.stop =			ohci_stop,
 
 	/*
@@ -571,100 +514,125 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int ohci_hcd_omap_drv_probe(struct omap_dev *dev)
+static int ohci_hcd_omap_drv_probe(struct device *dev)
 {
-	struct usb_hcd *hcd = NULL;
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
+	return usb_hcd_omap_probe(&ohci_omap_hc_driver,
+				to_platform_device(dev));
+}
 
-	ret = usb_hcd_omap_probe(&ohci_omap_hc_driver, &hcd, dev);
+static int ohci_hcd_omap_drv_remove(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct usb_hcd		*hcd = dev_get_drvdata(dev);
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 
-	if (ret == 0)
-		omap_set_drvdata(dev, hcd);
+	usb_hcd_omap_remove(hcd, pdev);
+	if (ohci->transceiver) {
+		(void) otg_set_host(ohci->transceiver, 0);
+		put_device(ohci->transceiver->dev);
+	}
+	dev_set_drvdata(dev, NULL);
 
-	return ret;
+	return 0;
 }
 
-static int ohci_hcd_omap_drv_remove(struct omap_dev *dev)
+/*-------------------------------------------------------------------------*/
+
+#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+
+/* states match PCI usage, always suspending the root hub except that
+ * 4 ~= D3cold (ACPI D3) with clock off (resume sees reset).
+ */
+
+static int ohci_omap_suspend(struct device *dev, u32 state, u32 level)
 {
-	struct usb_hcd *hcd = omap_get_drvdata(dev);
+	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
+	int		status = -EINVAL;
 
-	usb_hcd_omap_remove(hcd, dev);
+	if (state <= dev->power.power_state)
+		return 0;
 
-	omap_set_drvdata(dev, NULL);
+	dev_dbg(dev, "suspend to %d\n", state);
+	down(&ohci->hcd.self.root_hub->serialize);
+	status = ohci_hub_suspend(&ohci->hcd);
+	if (status == 0) {
+		if (state >= 4) {
+			/* power off + reset */
+			OTG_SYSCON_2_REG &= ~UHOST_EN;
+			ohci->hcd.self.root_hub->state = USB_STATE_SUSPENDED;
+			state = 4;
+		}
+		ohci->hcd.state = HCD_STATE_SUSPENDED;
+		dev->power.power_state = state;
+	}
+	up(&ohci->hcd.self.root_hub->serialize);
+	return status;
+}
 
-	return 0;
+static int ohci_omap_resume(struct device *dev, u32 level)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
+	int		status = 0;
+
+	switch (dev->power.power_state) {
+	case 0:
+		break;
+	case 4:
+		if (time_before(jiffies, ohci->next_statechange))
+			msleep(5);
+		ohci->next_statechange = jiffies;
+		OTG_SYSCON_2_REG |= UHOST_EN;
+		/* FALLTHROUGH */
+	default:
+		dev_dbg(dev, "resume from %d\n", dev->power.power_state);
+#ifdef	CONFIG_USB_SUSPEND
+		/* get extra cleanup even if remote wakeup isn't in use */
+		status = usb_resume_device(ohci->hcd.self.root_hub);
+#else
+		down(&ohci->hcd.self.root_hub->serialize);
+		status = ohci_hub_resume(&ohci->hcd);
+		up(&ohci->hcd.self.root_hub->serialize);
+#endif
+		if (status == 0)
+			dev->power.power_state = 0;
+		break;
+	}
+	return status;
 }
 
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 /*
  * Driver definition to register with the OMAP bus
  */
-static struct omap_driver ohci_hcd_omap_driver = {
-	.drv = {
-		.name	= OMAP_OHCI_NAME,
-	},
-	.devid		= OMAP_OCP_DEVID_USB,
-	.busid		= OMAP_BUS_OCP,
-	.clocks		= 0,
+static struct device_driver ohci_hcd_omap_driver = {
+	.name		= "ohci",
+	.bus		= &platform_bus_type,
 	.probe		= ohci_hcd_omap_drv_probe,
 	.remove		= ohci_hcd_omap_drv_remove,
-};
-
-/* Any dma_mask must be set for OHCI to work */
-static u64 omap_dmamask = 0xffffffffUL;	
-
-/*
- * Device definition to match the driver above
- */
-static struct omap_dev ohci_hcd_omap_device = {
-	.name		= OMAP_OHCI_NAME,
-	.devid		= OMAP_OCP_DEVID_USB,
-	.busid		= OMAP_BUS_OCP,
-	.mapbase	= (void *)OMAP_OHCI_BASE,
-	.dma_mask	= &omap_dmamask,	/* Needed only for OHCI */
-	.res = {
-		.start	= OMAP_OHCI_BASE,
-		.end	= OMAP_OHCI_BASE + OMAP_OHCI_SIZE,
-	},
-	.irq = {
-		INT_USB_HHC_1,
-	},
+#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+	.suspend	= ohci_omap_suspend,
+	.resume		= ohci_omap_resume,
+#endif
 };
 
 static int __init ohci_hcd_omap_init (void)
 {
-	int ret;
-
-	dbg (DRIVER_INFO " (OMAP)");
-	dbg ("block sizes: ed %d td %d\n",
-		sizeof (struct ed), sizeof (struct td));
-
-	if (hmc_mode < 0 || hmc_mode > 25)
-		hmc_mode = default_hmc_mode;
-
-	/* Register the driver with OMAP bus */
-	ret = omap_driver_register(&ohci_hcd_omap_driver);
-	if (ret != 0)
+	printk (KERN_DEBUG "%s: " DRIVER_INFO " (OMAP)\n", hcd_name);
+	if (usb_disabled())
 		return -ENODEV;
 
-	/* Register the device with OMAP bus */
-	ret = omap_device_register(&ohci_hcd_omap_device);
-	if (ret != 0) {
-		omap_driver_unregister(&ohci_hcd_omap_driver);
-		return -ENODEV;
-	}
+	pr_debug("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+		sizeof (struct ed), sizeof (struct td));
 
-	return ret;
+	return driver_register(&ohci_hcd_omap_driver);
 }
 
-module_param(hmc_mode, int, 0);
-
 static void __exit ohci_hcd_omap_cleanup (void)
 {
-	omap_device_unregister(&ohci_hcd_omap_device);
-	omap_driver_unregister(&ohci_hcd_omap_driver);
+	driver_unregister(&ohci_hcd_omap_driver);
 }
 
 module_init (ohci_hcd_omap_init);
--- xu26/drivers/usb/host/ohci-omap.h	2004-01-29 11:37:20.000000000 -0800
+++ gadget-2.6/drivers/usb/host/ohci-omap.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,57 +0,0 @@
-/*
- * linux/drivers/usb/host/ohci-omap.h
- *
- * OMAP OHCI USB controller specific defines
- */
-
-/* OMAP USB OHCI common defines */
-#define OMAP_OHCI_NAME		"omap-ohci"
-#define OMAP_OHCI_BASE		0xfffba000
-#define OMAP_OHCI_SIZE		4096
-
-#define HMC_CLEAR		(0x3f << 1)
-#define APLL_NDPLL_SWITCH	0x0001
-#define DPLL_PLL_ENABLE		0x0010
-#define DPLL_LOCK		0x0001
-#define SOFT_REQ_REG_REQ	0x0001
-#define USB_MCLK_EN		0x0010
-#define USB_HOST_HHC_UHOST_EN	0x00000200
-#define SOFT_USB_OTG_REQ	(1 << 8)
-#define SOFT_USB_REQ		(1 << 3)
-#define STATUS_REQ_REG		0xfffe0840
-#define USB_HOST_DPLL_REQ	(1 << 8)
-#define SOFT_DPLL_REQ		(1 << 0)
-
-/* OMAP-1510 USB OHCI defines */
-#define OMAP1510_LB_MEMSIZE	32		/* Should be same as SDRAM size */
-#define OMAP1510_LB_CLOCK_DIV	0xfffec10c
-#define OMAP1510_LB_MMU_CTL	0xfffec208	
-#define OMAP1510_LB_MMU_LCK	0xfffec224
-#define OMAP1510_LB_MMU_LD_TLB	0xfffec228
-#define OMAP1510_LB_MMU_CAM_H	0xfffec22c
-#define OMAP1510_LB_MMU_CAM_L	0xfffec230
-#define OMAP1510_LB_MMU_RAM_H	0xfffec234
-#define OMAP1510_LB_MMU_RAM_L	0xfffec238
-
-/* OMAP-1610 USB OHCI defines */
-#define USB_TRANSCEIVER_CTRL	0xfffe1064
-#define OTG_REV			0xfffb0400
-
-#define OTG_SYSCON_1		0xfffb0404
-#define OTG_IDLE_EN		(1 << 15)
-#define DEV_IDLE_EN		(1 << 13)
-
-#define OTG_SYSCON_2		0xfffb0408
-#define OTG_CTRL		0xfffb040c
-#define OTG_IRQ_EN		0xfffb0410
-#define OTG_IRQ_SRC		0xfffb0414
-
-#define OTG_EN			(1 << 31)
-#define USBX_SYNCHRO		(1 << 30)
-#define SRP_VBUS		(1 << 12)
-#define OTG_PADEN		(1 << 10)
-#define HMC_PADEN		(1 << 9)
-#define UHOST_EN		(1 << 8)
-
-/* Hardware specific defines */
-#define OMAP1510_FPGA_HOST_CTRL	0xe800020c

Reply via email to