Hi, here's my now working patch - I've still a bit of work to do on it
obviously, but it should suffice as a proof of concept

-- 
unsubscribe: android-kernel+unsubscr...@googlegroups.com
website: http://groups.google.com/group/android-kernel
--- kernel_hero/arch/arm/mach-msm/devices.c	2009-10-22 07:39:39.000000000 +0100
+++ kernel_hero.patched/arch/arm/mach-msm/devices.c	2010-01-31 17:55:42.835673987 +0000
@@ -158,6 +158,7 @@
 /* adjust eye diagram, disable vbusvalid interrupts */
 static int hsusb_phy_init_seq[] = { 0x40, 0x31, 0x1, 0x0D, 0x1, 0x10, -1 };
 
+#ifdef CONFIG_USB_FUNCTION
 static char *usb_functions[] = {
 
 #if defined(CONFIG_USB_FUNCTION_MASS_STORAGE) || defined(CONFIG_USB_FUNCTION_UMS)
@@ -227,10 +228,12 @@
 	},
 
 };
+#endif
 
 struct msm_hsusb_platform_data msm_hsusb_pdata = {
 	.phy_reset = internal_phy_reset,
 	.phy_init_seq = hsusb_phy_init_seq,
+#ifdef CONFIG_USB_FUNCTION
 	.vendor_id = 0x0bb4,
 	.product_id = 0x0c02,
 	.version = 0x0100,
@@ -241,6 +244,7 @@
 	.num_functions = ARRAY_SIZE(usb_functions),
 	.products = usb_products,
 	.num_products = ARRAY_SIZE(usb_products),
+#endif
 };
 
 static struct resource resources_hsusb[] = {
@@ -1123,6 +1127,7 @@
 	return mfg_mode;
 }
 
+#ifdef CONFIG_USB_FUNCTION
 static int __init board_serialno_setup(char *serialno)
 {
 	if (board_mfg_mode() || !strlen(serialno))
@@ -1133,6 +1138,7 @@
 }
 
 __setup("androidboot.serialno=", board_serialno_setup);
+#endif
 
 EXPORT_SYMBOL(board_mfg_mode);
 static char *keycap_tag = NULL;
--- kernel_hero/arch/arm/mach-msm/htc_battery.c	2009-10-22 07:39:39.000000000 +0100
+++ kernel_hero.patched/arch/arm/mach-msm/htc_battery.c	2010-01-31 17:57:51.915655870 +0000
@@ -205,12 +205,14 @@
 	},
 };
 
-static void usb_status_notifier_func(int online);
 static int g_usb_online;
+#ifdef CONFIG_USB_FUNCTION
+static void usb_status_notifier_func(int online);
 static struct t_usb_status_notifier usb_status_notifier = {
 	.name = "htc_battery",
 	.func = usb_status_notifier_func,
 };
+#endif
 
 /* -------------------------------------------------------------------------- */
 /* For sleep charging screen. */
@@ -476,6 +478,7 @@
 	return rc;
 }
 
+#ifdef CONFIG_USB_FUNCTION
 /* A9 reports USB charging when helf AC cable in and China AC charger. */
 /* Work arround: notify userspace AC charging first,
 and notify USB charging again when receiving usb connected notificaiton from usb driver. */
@@ -496,6 +499,8 @@
 	}
 	mutex_unlock(&htc_batt_info.lock);
 }
+#endif
+
 static int htc_get_batt_info(struct battery_info_reply *buffer)
 {
 	struct rpc_request_hdr req;
@@ -1231,7 +1236,9 @@
 	wake_lock_init(&vbus_wake_lock, WAKE_LOCK_SUSPEND, "vbus_present");
 	mutex_init(&htc_batt_info.lock);
 	mutex_init(&htc_batt_info.rpc_lock);
+#ifdef CONFIG_USB_FUNCTION
 	usb_register_notifier(&usb_status_notifier);
+#endif
 	msm_rpc_create_server(&battery_server);
 	platform_driver_register(&htc_battery_driver);
 	batt_register_client(&batt_notify);
--- kernel_hero/drivers/usb/function/Kconfig	2009-10-22 07:39:58.000000000 +0100
+++ kernel_hero.patched/drivers/usb/function/Kconfig	2010-02-07 18:50:28.137447755 +0000
@@ -14,7 +14,7 @@
 	
 config USB_FUNCTION_MSM_HSUSB
 	boolean "MSM7K Highspeed USB Peripheral Controller"
-	depends on ARCH_MSM7XXX
+	depends on ARCH_MSM7XXX && (!USB_EHCI_MSM7201)
 
 endchoice
 
--- kernel_hero/drivers/usb/host/ehci-hcd.c	2009-10-22 07:39:59.000000000 +0100
+++ kernel_hero.patched/drivers/usb/host/ehci-hcd.c	2010-02-09 20:06:33.162966732 +0000
@@ -1040,6 +1040,11 @@
 #define	PLATFORM_DRIVER		ixp4xx_ehci_driver
 #endif
 
+#ifdef CONFIG_ARCH_MSM7XXX
+#include "ehci-msm7201.c"
+#define	PLATFORM_DRIVER		ehci_msm7201_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
 #error "missing bus glue for ehci-hcd"
--- kernel_hero/drivers/usb/host/ehci-msm7201.c	1970-01-01 01:00:00.000000000 +0100
+++ kernel_hero.patched/drivers/usb/host/ehci-msm7201.c	2010-02-09 20:09:10.556297861 +0000
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2010 Andrew de Quincey
+ *
+ * (heavily) based on ehci-fsl.c, which is:
+ * 
+ * Copyright (c) 2005 MontaVista Software
+ *
+ * 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.
+ *
+ * Ported to 834x by Randy Vinson <rvin...@mvista.com> using code provided
+ * by Hunter Wu.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <mach/msm_hsusb.h>
+
+#include "ehci-msm7201.h"
+
+static void ulpi_write(struct usb_hcd *hcd, unsigned val, unsigned reg)
+{
+	unsigned timeout = 10000;
+
+	/* initiate write operation */
+	writel(ULPI_RUN | ULPI_WRITE |
+	       ULPI_ADDR(reg) | ULPI_DATA(val),
+	       USB_ULPI_VIEWPORT);
+
+	/* wait for completion */
+	while ((readl(USB_ULPI_VIEWPORT) & ULPI_RUN) && (--timeout)) ;
+
+	if (timeout == 0)
+		printk(KERN_WARNING "%s: timeout: reg: 0x%X, var: 0x%X\n",
+		__func__, reg, val);
+}
+
+static void msm7201_setup_phy(struct usb_hcd *hcd)
+{
+	struct msm7201_usb_priv *msm7201 = hcd_to_msm7201(hcd);
+
+  	int *seq = msm7201->phy_init_seq;
+
+	if (!seq)
+		return;
+
+	while (seq[0] >= 0) {
+		ulpi_write(hcd, seq[0], seq[1]);
+		seq += 2;
+	}
+}
+
+static void msm7201_shutdown_phy(struct usb_hcd *hcd)
+{
+	struct msm7201_usb_priv *msm7201 = hcd_to_msm7201(hcd);
+
+	if (msm7201->phy_shutdown)
+		msm7201->phy_shutdown();
+	
+	/* disable interface protect circuit to drop current consumption */
+	ulpi_write(hcd, (1 << 7), 0x08);
+	/* clear the SuspendM bit -> suspend the PHY */
+	ulpi_write(hcd, 1 << 6, 0x06);
+}
+
+static void msm7201_usb_setup(struct usb_hcd *hcd)
+{
+	struct msm7201_usb_priv *msm7201 = hcd_to_msm7201(hcd);
+	int i;
+
+	/* INCR8 BURST mode */
+	writel(0x02, USB_SBUSCFG);	/*boost performance to fix CRC error.*/
+
+	/* select ULPI phy */
+	writel(0x80000000, USB_PORTSC);
+
+	if (msm7201->phy_reset)
+		msm7201->phy_reset();
+	msm7201_setup_phy(hcd);
+}
+
+/* called after powerup, by probe or system-pm "wakeup" */
+static int ehci_msm7201_reinit(struct ehci_hcd *ehci)
+{
+	msm7201_usb_setup(ehci_to_hcd(ehci));
+	ehci_port_power(ehci, 0);
+
+	return 0;
+}
+
+/* called during probe() after chip reset completes */
+static int ehci_msm7201_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	/* EHCI registers start at offset 0x100 */
+	ehci->caps = hcd->regs + 0x100;
+	ehci->regs = hcd->regs + 0x100 +
+	    HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
+	/* configure other settings */
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+	hcd->has_tt = 1;
+	ehci->sbrn = 0x20;
+
+	/* reset and halt controller */
+	ehci_reset(ehci);
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	/* data structure init */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+        
+	ehci_reset(ehci);
+
+	retval = ehci_msm7201_reinit(ehci);
+	return retval;
+}
+
+static const struct hc_driver ehci_msm7201_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "Qualcomm MSM7201 On-Chip EHCI Host Controller",
+	.hcd_priv_size = sizeof(struct ehci_hcd) + sizeof(struct msm7201_usb_priv),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = ehci_irq,
+	.flags = HCD_USB2 | HCD_MEMORY | HCD_LOCAL_MEM,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset = ehci_msm7201_setup,
+	.start = ehci_run,
+	.stop = ehci_stop,
+	.shutdown = ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue = ehci_urb_enqueue,
+	.urb_dequeue = ehci_urb_dequeue,
+	.endpoint_disable = ehci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number = ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = ehci_hub_status_data,
+	.hub_control = ehci_hub_control,
+	.bus_suspend = ehci_bus_suspend,
+	.bus_resume = ehci_bus_resume,
+	.relinquish_port = ehci_relinquish_port,
+	.port_handed_over = ehci_port_handed_over,
+};
+
+/**
+ * usb_hcd_msm7201_remove - shutdown processing for MSM7201-based HCDs
+ * @pdev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_msm7201_probe().
+ *
+ */
+static int usb_hcd_msm7201_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct msm7201_usb_priv *msm7201 = hcd_to_msm7201(hcd);
+
+	usb_remove_hcd(hcd);
+	msm7201_shutdown_phy(hcd);
+	clk_put(msm7201->clk);
+	clk_put(msm7201->pclk);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	
+	return 0;
+}
+
+/**
+ * usb_hcd_msm7201_probe - initialize MSM7201-based HCDs
+ * @pdev: USB Host Controller being probed
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller.
+ *
+ */
+static int usb_hcd_msm7201_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res;
+	struct msm7201_usb_priv *msm7201;
+	int irq;
+	int retval;
+	const struct hc_driver *driver = &ehci_msm7201_hc_driver;
+	struct msm_hsusb_platform_data *pdata = pdev->dev.platform_data;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_debug("initializing MSM7201 USB Controller\n");
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no IRQ. Check %s setup!\n",
+			dev_name(&pdev->dev));
+		return -ENODEV;
+	}
+	irq = res->start;
+
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		retval = -ENOMEM;
+		goto err1;
+	}
+	
+	msm7201 = hcd_to_msm7201(hcd);
+	if (pdata) {
+		msm7201->phy_reset = pdata->phy_reset;
+		msm7201->phy_shutdown = pdata->phy_shutdown;
+		msm7201->phy_init_seq = pdata->phy_init_seq;
+	}
+	
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no register addr. Check %s setup!\n",
+			dev_name(&pdev->dev));
+		retval = -ENODEV;
+		goto err2;
+	}
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+	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;
+	}
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+
+	if (hcd->regs == NULL) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		retval = -EFAULT;
+		goto err3;
+	}
+	
+	msm7201->clk = clk_get(&pdev->dev, "usb_hs_clk");
+	if (IS_ERR(msm7201->clk)) {
+		dev_dbg(&pdev->dev, "error getting usb_hs_clk\n");
+		retval = -EFAULT;
+		goto err4;	  
+	}
+
+	msm7201->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
+	if (IS_ERR(msm7201->pclk)) {
+		dev_dbg(&pdev->dev, "error getting usb_hs_pclk\n");
+		retval = -EFAULT;
+		goto err5;	  
+	}
+
+        clk_enable(msm7201->clk);
+        clk_enable(msm7201->pclk);
+
+        /* wait for a while after enable usb clk*/
+        msleep(5);
+
+	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+	if (retval != 0)
+		goto err6;
+	return retval;
+
+      err6:
+	clk_put(msm7201->pclk);
+      err5:
+	clk_put(msm7201->clk);
+      err4:
+	iounmap(hcd->regs);	
+      err3:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+      err2:
+	usb_put_hcd(hcd);
+      err1:
+	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
+	return retval;
+}
+
+MODULE_ALIAS("platform:msm_hsusb");
+
+static struct platform_driver ehci_msm7201_driver = {
+	.probe = usb_hcd_msm7201_probe,
+	.remove = usb_hcd_msm7201_remove,
+	.shutdown = usb_hcd_platform_shutdown,
+	.driver = {
+		   .name = "msm_hsusb",
+	},
+};
--- kernel_hero/drivers/usb/host/ehci-msm7201.h	1970-01-01 01:00:00.000000000 +0100
+++ kernel_hero.patched/drivers/usb/host/ehci-msm7201.h	2010-02-09 18:22:32.530257554 +0000
@@ -0,0 +1,88 @@
+/* 
+ * Copyright (c) 2010 Andrew de Quincey
+ *
+ * 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 _EHCI_MSM7201_H
+#define _EHCI_MSM7201_H
+
+struct msm7201_usb_priv 
+{
+	struct clk *clk;
+	struct clk *pclk;
+
+	int *phy_init_seq;
+	void (*phy_reset)(void);
+	void (*phy_shutdown)(void);
+};
+
+static inline struct msm7201_usb_priv *hcd_to_msm7201(struct usb_hcd *hcd)
+{
+	return (struct msm7201_usb_priv *) (hcd->hcd_priv) + sizeof(struct ehci_hcd);
+}
+
+#define MSM_USB_BASE	     ((unsigned) hcd->regs)
+
+#define USB_ID               (MSM_USB_BASE + 0x0000)
+#define USB_HWGENERAL        (MSM_USB_BASE + 0x0004)
+#define USB_HWHOST           (MSM_USB_BASE + 0x0008)
+#define USB_HWDEVICE         (MSM_USB_BASE + 0x000C)
+#define USB_HWTXBUF          (MSM_USB_BASE + 0x0010)
+#define USB_HWRXBUF          (MSM_USB_BASE + 0x0014)
+#define USB_SBUSCFG          (MSM_USB_BASE + 0x0090)
+
+#define USB_CAPLENGTH        (MSM_USB_BASE + 0x0100) /* 8 bit */
+#define USB_HCIVERSION       (MSM_USB_BASE + 0x0102) /* 16 bit */
+#define USB_HCSPARAMS        (MSM_USB_BASE + 0x0104)
+#define USB_HCCPARAMS        (MSM_USB_BASE + 0x0108)
+#define USB_DCIVERSION       (MSM_USB_BASE + 0x0120) /* 16 bit */
+#define USB_USBCMD           (MSM_USB_BASE + 0x0140)
+#define USB_USBSTS           (MSM_USB_BASE + 0x0144)
+#define USB_USBINTR          (MSM_USB_BASE + 0x0148)
+#define USB_FRINDEX          (MSM_USB_BASE + 0x014C)
+#define USB_DEVICEADDR       (MSM_USB_BASE + 0x0154)
+#define USB_ENDPOINTLISTADDR (MSM_USB_BASE + 0x0158)
+#define USB_BURSTSIZE        (MSM_USB_BASE + 0x0160)
+#define USB_TXFILLTUNING     (MSM_USB_BASE + 0x0164)
+#define USB_ULPI_VIEWPORT    (MSM_USB_BASE + 0x0170)
+#define USB_ENDPTNAK         (MSM_USB_BASE + 0x0178)
+#define USB_ENDPTNAKEN       (MSM_USB_BASE + 0x017C)
+#define USB_PORTSC           (MSM_USB_BASE + 0x0184)
+#define USB_OTGSC            (MSM_USB_BASE + 0x01A4)
+#define USB_USBMODE          (MSM_USB_BASE + 0x01A8)
+#define USB_ENDPTSETUPSTAT   (MSM_USB_BASE + 0x01AC)
+#define USB_ENDPTPRIME       (MSM_USB_BASE + 0x01B0)
+#define USB_ENDPTFLUSH       (MSM_USB_BASE + 0x01B4)
+#define USB_ENDPTSTAT        (MSM_USB_BASE + 0x01B8)
+#define USB_ENDPTCOMPLETE    (MSM_USB_BASE + 0x01BC)
+#define USB_ENDPTCTRL(n)     (MSM_USB_BASE + 0x01C0 + (4 * (n)))
+
+#define USBCMD_RESET   2
+#define USBCMD_ATTACH  1
+#define USBCMD_ATDTW   (1 << 14)
+
+#define USBMODE_DEVICE 2
+#define USBMODE_HOST   3
+
+#define ULPI_WAKEUP           (1 << 31)
+#define ULPI_RUN              (1 << 30)
+#define ULPI_WRITE            (1 << 29)
+#define ULPI_READ             (0 << 29)
+#define ULPI_STATE_NORMAL     (1 << 27)
+#define ULPI_ADDR(n)          (((n) & 255) << 16)
+#define ULPI_DATA(n)          ((n) & 255)
+#define ULPI_DATA_READ(n)     (((n) >> 8) & 255)
+
+#endif				/* _EHCI_MSM7201_H */
--- kernel_hero/drivers/usb/host/Kconfig	2009-10-22 07:39:59.000000000 +0100
+++ kernel_hero.patched/drivers/usb/host/Kconfig	2010-02-07 18:27:17.314978017 +0000
@@ -88,6 +88,13 @@
 	---help---
 	  Variation of ARC USB block used in some Freescale chips.
 
+config USB_EHCI_MSM7201
+	bool "Support for Qualcomm MSM7201 on-chip EHCI USB controller"
+	depends on USB_EHCI_HCD && ARCH_MSM7XXX && (!USB_FUNCTION)
+	select USB_EHCI_ROOT_HUB_TT
+	---help---
+	  Variation of ARC USB block used in Qualcomm MSM7201 chips.
+
 config USB_EHCI_HCD_PPC_OF
 	bool "EHCI support for PPC USB controller on OF platform bus"
 	depends on USB_EHCI_HCD && PPC_OF

Reply via email to