[PATCH] MPC8349 MDS USB HOST support

Li Yang-r58472 LeoLi at freescale.com
Tue Dec 20 14:57:36 EST 2005


Hi,

Here is the patch we have in Freescale released BSP.  I post it here in case anyone may need it without the BSP.  It's for kernel 2.6.11, and won't have big problem for newer kernel, I think.  The patch is not done by myself, and maybe submitted later formally after merge with OTG and clean up.  Here goes the patch.


diff -Nur linux/drivers/usb/core/hcd.c linux-8349-2.6/drivers/usb/core/hcd.c
--- linux/drivers/usb/core/hcd.c	2005-03-02 15:38:10.000000000 +0800
+++ linux-8349-2.6/drivers/usb/core/hcd.c	2005-08-15 13:54:13.000000000 +0800
@@ -1116,13 +1116,20 @@
 	if (hcd->self.controller->dma_mask) {
 		if (usb_pipecontrol (urb->pipe)
 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+#ifdef CONFIG_FSL_USB20
+        		urb->setup_dma = (unsigned long)urb->setup_packet;
+#else
 			urb->setup_dma = dma_map_single (
 					hcd->self.controller,
 					urb->setup_packet,
 					sizeof (struct usb_ctrlrequest),
 					DMA_TO_DEVICE);
+#endif
 		if (urb->transfer_buffer_length != 0
 			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+#ifdef CONFIG_FSL_USB20
+            		urb->transfer_dma = (unsigned long)urb->transfer_buffer;
+#else
 			urb->transfer_dma = dma_map_single (
 					hcd->self.controller,
 					urb->transfer_buffer,
@@ -1130,6 +1137,7 @@
 					usb_pipein (urb->pipe)
 					    ? DMA_FROM_DEVICE
 					    : DMA_TO_DEVICE);
+#endif
 	}
 
 	status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
@@ -1469,6 +1477,8 @@
 	// It would catch exit/unlink paths for all urbs.
 
 	/* lower level hcd code should use *_dma exclusively */
+#ifdef CONFIG_FSL_USB20
+#else
 	if (hcd->self.controller->dma_mask) {
 		if (usb_pipecontrol (urb->pipe)
 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
@@ -1484,7 +1494,7 @@
 					    ? DMA_FROM_DEVICE
 					    : DMA_TO_DEVICE);
 	}
-
+#endif
 	/* pass ownership to the completion handler */
 	urb->complete (urb, regs);
 	atomic_dec (&urb->use_count);
diff -Nur linux/drivers/usb/core/hub.c linux-8349-2.6/drivers/usb/core/hub.c
--- linux/drivers/usb/core/hub.c	2005-03-02 15:38:08.000000000 +0800
+++ linux-8349-2.6/drivers/usb/core/hub.c	2005-08-15 13:56:05.000000000 +0800
@@ -2155,7 +2155,11 @@
 	} else if (udev->speed != USB_SPEED_HIGH
 			&& hdev->speed == USB_SPEED_HIGH) {
 		udev->tt = &hub->tt;
+#ifdef CONFIG_FSL_USB20
+		udev->ttport = port1+1;
+#else
 		udev->ttport = port1;
+#endif
 	}
  
 	/* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?
diff -Nur linux/drivers/usb/host/ehci.h linux-8349-2.6/drivers/usb/host/ehci.h
--- linux/drivers/usb/host/ehci.h	2005-03-02 15:38:25.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/ehci.h	2005-08-15 10:25:52.000000000 +0800
@@ -59,6 +59,9 @@
 #define	DEFAULT_I_TDPS		1024		/* some HCs can do less */
 	unsigned		periodic_size;
 	__le32			*periodic;	/* hw periodic table */
+#ifdef CONFIG_FSL_USB20
+	u32		        orig_periodic;
+#endif
 	dma_addr_t		periodic_dma;
 	unsigned		i_thresh;	/* uframes HC might cache */
 
@@ -70,11 +73,17 @@
 	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
 
 	/* per-HC memory pools (could be per-bus, but ...) */
+#ifdef CONFIG_FSL_USB20
+	t_MemorySegment   *qh_pool;     /* qh per active urb      */
+	t_MemorySegment   *qtd_pool;    /* one or more per qh     */
+	t_MemorySegment   *itd_pool;    /* itd per iso urb        */
+	t_MemorySegment   *sitd_pool;   /* sitd per split iso urb */
+#else
 	struct dma_pool		*qh_pool;	/* qh per active urb */
 	struct dma_pool		*qtd_pool;	/* one or more per qh */
 	struct dma_pool		*itd_pool;	/* itd per iso urb */
 	struct dma_pool		*sitd_pool;	/* sitd per split iso urb */
-
+#endif
 	struct timer_list	watchdog;
 	struct notifier_block	reboot_notifier;
 	unsigned long		actions;
@@ -230,9 +239,26 @@
 	u32		frame_list; 	/* points to periodic list */
 	/* ASYNCLISTADDR: offset 0x18 */
 	u32		async_next;	/* address of next async queue head */
-
+#ifdef CONFIG_FSL_USB20
+        /* ASYNCTTSTS: offset 0x1c */
+	u32	        async_tt_status;    /* async queue status for embedded TT */
+    	/* BURSTSIZE: offset 0x20 */
+	u32     	burst_size;         /* programmable burst size */
+    	/* TXFILLTUNING: offset 0x24 */
+	u32        	txfilltuning;       /* host transmit pre-buffer packet tuning */
+    	/* TXTTFILLTUNING: offset 0x28 */
+	u32        	txttfilltuning;     /* host TT transmit pre-buffer packet tuning */
+	u32        	reserved0;
+    	/* ULPIVIEWPORT: offset 0x30 */
+	u32        	ulpi_view_port;     /* ULPI view port */
+    	/* ENDPTNAK: offset 0x34 */
+	u32        	endpoint_nack;      /* endpoint nack */
+    	/* ENDPTNAKEN: offset 0x38 */
+	u32        	endpoint_nack_en;   /* endpoint nack enable */
+	u32        	reserved1;
+#else
 	u32		reserved [9];
-
+#endif
 	/* CONFIGFLAG: offset 0x40 */
 	u32		configured_flag;
 #define FLAG_CF		(1<<0)		/* true: we'll support "high speed" */
diff -Nur linux/drivers/usb/host/ehci-hcd.c linux-8349-2.6/drivers/usb/host/ehci-hcd.c
--- linux/drivers/usb/host/ehci-hcd.c	2005-03-02 15:38:38.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/ehci-hcd.c	2005-08-15 10:40:35.000000000 +0800
@@ -16,6 +16,13 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifdef CONFIG_FSL_USB20
+#ifdef CONFIG_USB_DEBUG	
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+#else
 #include <linux/config.h>
 
 #ifdef CONFIG_USB_DEBUG
@@ -101,8 +108,17 @@
 #define DRIVER_AUTHOR "David Brownell"
 #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
 
-static const char	hcd_name [] = "ehci_hcd";
+#endif
 
+#ifdef CONFIG_FSL_USB20
+#if defined (CONFIG_MPH_USB_SUPPORT)
+static const char	hcd_name [] = "fsl-usb2-mph";
+#elif defined (CONFIG_DR_USB_SUPPORT)
+static const char	hcd_name [] = "fsl-usb2-dr";
+#endif
+#else
+static const char	hcd_name [] = "ehci_hcd";
+#endif
 
 #undef EHCI_VERBOSE_DEBUG
 #undef EHCI_URB_TRACE
@@ -112,6 +128,7 @@
 #endif
 
 /* magic numbers that can affect system performance */
+
 #define	EHCI_TUNE_CERR		3	/* 0-3 qtd retries; 0 == don't stop */
 #define	EHCI_TUNE_RL_HS		4	/* nak throttle; see 4.9 */
 #define	EHCI_TUNE_RL_TT		0
@@ -126,13 +143,18 @@
 
 /* Initial IRQ latency:  faster than hw default */
 static int log2_irq_thresh = 0;		// 0 to 6
+#ifdef CONFIG_FSL_USB20
+#else
 module_param (log2_irq_thresh, int, S_IRUGO);
 MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
-
+#endif
 /* initial park setting:  slower than hw default */
 static unsigned park = 0;
+#ifdef CONFIG_FSL_USB20
+#else
 module_param (park, uint, S_IRUGO);
 MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
+#endif
 
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
@@ -190,7 +212,27 @@
 	writel (temp, &ehci->regs->command);
 	return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125);
 }
+#ifdef CONFIG_FSL_USB20
+static void mpc8349_usb_reset(void);
+/* reset a non-running (STS_HALT == 1) controller */
+static int ehci_reset (struct ehci_hcd *ehci)
+{
+	int retval;
+	u32	command = readl (&ehci->regs->command);
 
+	command |= CMD_RESET;
+	dbg_cmd (ehci, "reset", command);
+	writel (command, &ehci->regs->command);
+	ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+	ehci->next_statechange = jiffies;
+	retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
+
+	if (retval)
+		return retval;
+	mpc8349_usb_reset ();
+	return retval;
+}
+#else
 /* reset a non-running (STS_HALT == 1) controller */
 static int ehci_reset (struct ehci_hcd *ehci)
 {
@@ -203,7 +245,7 @@
 	ehci->next_statechange = jiffies;
 	return handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
 }
-
+#endif
 /* idle the controller (from running) */
 static void ehci_quiesce (struct ehci_hcd *ehci)
 {
@@ -276,7 +318,7 @@
 	spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
-#ifdef	CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(CONFIG_FSL_USB20)
 
 /* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
  * off the controller (maybe it can boot from highspeed USB disks).
@@ -285,18 +327,22 @@
 {
 	if (cap & (1 << 16)) {
 		int msec = 5000;
+
 		struct pci_dev *pdev =
 				to_pci_dev(ehci_to_hcd(ehci)->self.controller);
 
 		/* request handoff to OS */
 		cap |= 1 << 24;
+
 		pci_write_config_dword(pdev, where, cap);
 
 		/* and wait a while for it to happen */
 		do {
 			msleep(10);
 			msec -= 10;
+
 			pci_read_config_dword(pdev, where, &cap);
+
 		} while ((cap & (1 << 16)) && msec);
 		if (cap & (1 << 16)) {
 			ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n",
@@ -332,7 +378,10 @@
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			temp;
+#ifdef CONFIG_FSL_USB20
+#else
 	unsigned		count = 256/4;
+#endif
 
 	spin_lock_init (&ehci->lock);
 
@@ -340,8 +389,14 @@
 	ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase));
 	dbg_hcs_params (ehci, "reset");
 	dbg_hcc_params (ehci, "reset");
+	
 
-#ifdef	CONFIG_PCI
+#ifdef CONFIG_FSL_USB20
+	mpc8349_usb_reset ();
+	ehci->is_arc_rh_tt = 1;
+#endif
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_FSL_USB20)
 	/* EHCI 0.96 and later may have "extended capabilities" */
 	if (hcd->self.controller->bus == &pci_bus_type) {
 		struct pci_dev	*pdev = to_pci_dev(hcd->self.controller);
@@ -395,7 +450,7 @@
 			HCS_N_PCC(ehci->hcs_params),
 			HCS_N_PORTS(ehci->hcs_params));
 
-#ifdef	CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(CONFIG_FSL_USB20)
 		if (hcd->self.controller->bus == &pci_bus_type) {
 			struct pci_dev	*pdev;
 
@@ -465,7 +520,7 @@
 	}
 	writel (ehci->periodic_dma, &ehci->regs->frame_list);
 
-#ifdef	CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(CONFIG_FSL_USB20)
 	if (hcd->self.controller->bus == &pci_bus_type) {
 		struct pci_dev		*pdev;
 		u16			port_wake;
@@ -829,7 +884,7 @@
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			status;
 	int			bh;
-
+	
 	spin_lock (&ehci->lock);
 
 	status = readl (&ehci->regs->status);
@@ -1181,6 +1236,9 @@
 /*-------------------------------------------------------------------------*/
 
 /* EHCI 1.0 doesn't require PCI */
+#ifdef CONFIG_FSL_USB20
+
+#else
 
 #ifdef	CONFIG_PCI
 
@@ -1236,3 +1294,4 @@
 	pci_unregister_driver (&ehci_pci_driver);
 }
 module_exit (cleanup);
+#endif
diff -Nur linux/drivers/usb/host/ehci-mem.c linux-8349-2.6/drivers/usb/host/ehci-mem.c
--- linux/drivers/usb/host/ehci-mem.c	2005-03-02 15:38:26.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/ehci-mem.c	2005-08-15 10:46:53.000000000 +0800
@@ -49,8 +49,13 @@
 {
 	struct ehci_qtd		*qtd;
 	dma_addr_t		dma;
-
+#ifdef CONFIG_FSL_USB20
+	qtd = MEM_Get( ehci->qtd_pool);
+	dma = virt_to_phys(qtd);
+	memset(qtd, 0, sizeof(*qtd));
+#else
 	qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma);
+#endif
 	if (qtd != NULL) {
 		ehci_qtd_init (qtd, dma);
 	}
@@ -59,7 +64,11 @@
 
 static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 {
+#ifdef CONFIG_FSL_USB20
+	MEM_Put(ehci->qtd_pool, qtd);
+#else
 	dma_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma);
+#endif
 }
 
 
@@ -75,8 +84,12 @@
 	}
 	if (qh->dummy)
 		ehci_qtd_free (ehci, qh->dummy);
+#ifdef CONFIG_FSL_USB20
+	MEM_Put(ehci->qh_pool, qh);
+#else
 	usb_put_dev (qh->dev);
 	dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+#endif
 }
 
 static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
@@ -84,8 +97,14 @@
 	struct ehci_qh		*qh;
 	dma_addr_t		dma;
 
+#ifdef CONFIG_FSL_USB20
+	qh = (struct ehci_qh *) MEM_Get(ehci->qh_pool);
+	dma = virt_to_phys(qh);
+	memset(qh, 0, sizeof(*qh));
+#else
 	qh = (struct ehci_qh *)
 		dma_pool_alloc (ehci->qh_pool, flags, &dma);
+#endif
 	if (!qh)
 		return qh;
 
@@ -100,7 +119,11 @@
 	qh->dummy = ehci_qtd_alloc (ehci, flags);
 	if (qh->dummy == NULL) {
 		ehci_dbg (ehci, "no dummy td\n");
+#ifdef CONFIG_FSL_USB20
+		MEM_Put(ehci->qh_pool, qh);
+#else
 		dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+#endif
 		qh = NULL;
 	}
 	return qh;
@@ -133,26 +156,46 @@
 
 	/* DMA consistent memory and pools */
 	if (ehci->qtd_pool)
+#ifdef CONFIG_FSL_USB20
+		MEM_Free(ehci->qtd_pool);
+#else
 		dma_pool_destroy (ehci->qtd_pool);
+#endif
 	ehci->qtd_pool = NULL;
 
 	if (ehci->qh_pool) {
+#ifdef CONFIG_FSL_USB20
+		MEM_Free(ehci->qh_pool);
+#else
 		dma_pool_destroy (ehci->qh_pool);
+#endif
 		ehci->qh_pool = NULL;
 	}
 
 	if (ehci->itd_pool)
+#ifdef CONFIG_FSL_USB20
+		MEM_Free(ehci->itd_pool);
+#else	
 		dma_pool_destroy (ehci->itd_pool);
+#endif
 	ehci->itd_pool = NULL;
 
 	if (ehci->sitd_pool)
+#ifdef CONFIG_FSL_USB20
+		MEM_Free(ehci->sitd_pool);
+#else	
 		dma_pool_destroy (ehci->sitd_pool);
+#endif
 	ehci->sitd_pool = NULL;
 
 	if (ehci->periodic)
+#ifdef CONFIG_FSL_USB20
+		kfree((void *)ehci->orig_periodic);
+#else
 		dma_free_coherent (ehci_to_hcd(ehci)->self.controller,
 			ehci->periodic_size * sizeof (u32),
 			ehci->periodic, ehci->periodic_dma);
+#endif
 	ehci->periodic = NULL;
 
 	/* shadow periodic table */
@@ -165,23 +208,31 @@
 static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
 {
 	int i;
+	int err;
 
 	/* QTDs for control/bulk/intr transfers */
+#ifdef CONFIG_FSL_USB20
+	err = MEM_Init("ehci_qtd_pool", (void **)&ehci->qtd_pool, 128, sizeof(struct ehci_qtd), 0, 0, 32);
+#else
 	ehci->qtd_pool = dma_pool_create ("ehci_qtd", 
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof (struct ehci_qtd),
 			32 /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
+#endif
 	if (!ehci->qtd_pool) {
 		goto fail;
 	}
-
+#ifdef CONFIG_FSL_USB20
+	err = MEM_Init("ehci_qh_pool", (void **)&ehci->qh_pool, 128, sizeof(struct ehci_qh), 0, 0, 64);
+#else
 	/* QHs for control/bulk/intr transfers */
 	ehci->qh_pool = dma_pool_create ("ehci_qh", 
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof (struct ehci_qh),
 			32 /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
+#endif
 	if (!ehci->qh_pool) {
 		goto fail;
 	}
@@ -191,30 +242,47 @@
 	}
 
 	/* ITD for high speed ISO transfers */
+#ifdef CONFIG_FSL_USB20
+	err = MEM_Init("ehci_itd_pool", (void **)&ehci->itd_pool, 128, sizeof(struct ehci_itd), 0, 0, 32);
+#else
 	ehci->itd_pool = dma_pool_create ("ehci_itd", 
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof (struct ehci_itd),
 			32 /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
+#endif
 	if (!ehci->itd_pool) {
 		goto fail;
 	}
 
 	/* SITD for full/low speed split ISO transfers */
+#ifdef CONFIG_FSL_USB20
+        err = MEM_Init("ehci_sitd_pool", (void**)&ehci->sitd_pool, 128, sizeof(struct ehci_sitd), 0, 0, 32);
+#else
 	ehci->sitd_pool = dma_pool_create ("ehci_sitd", 
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof (struct ehci_sitd),
 			32 /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
+#endif
 	if (!ehci->sitd_pool) {
 		goto fail;
 	}
 
 	/* Hardware periodic table */
+#ifdef CONFIG_FSL_USB20
+	ehci->orig_periodic =(u32)kmalloc((int)(ehci->periodic_size * sizeof (u32))+0x1000,GFP_KERNEL);
+	if(ehci->orig_periodic%0x1000)
+		ehci->periodic = (__le32 *)(((ehci->orig_periodic>>12)<<12)+0x1000);
+    	else
+		ehci->periodic = (__le32 *)ehci->orig_periodic;
+	ehci->periodic_dma = virt_to_phys(ehci->periodic);
+#else
 	ehci->periodic = (__le32 *)
 		dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller,
 			ehci->periodic_size * sizeof(__le32),
 			&ehci->periodic_dma, 0);
+#endif
 	if (ehci->periodic == NULL) {
 		goto fail;
 	}
diff -Nur linux/drivers/usb/host/ehci-q.c linux-8349-2.6/drivers/usb/host/ehci-q.c
--- linux/drivers/usb/host/ehci-q.c	2005-03-02 15:38:19.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/ehci-q.c	2005-08-15 10:50:13.000000000 +0800
@@ -500,7 +500,11 @@
 	is_input = usb_pipein (urb->pipe);
 	if (usb_pipecontrol (urb->pipe)) {
 		/* SETUP pid */
+#ifdef CONFIG_FSL_USB20
+		qtd_fill (qtd, virt_to_phys(urb->setup_packet), sizeof (struct usb_ctrlrequest),
+#else
 		qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
+#endif
 			token | (2 /* "setup" */ << 8), 8);
 
 		/* ... and always at least one more pid */
@@ -518,7 +522,11 @@
 	 * data transfer stage:  buffer setup
 	 */
 	if (likely (len > 0))
+#ifdef CONFIG_FSL_USB20
+		buf = virt_to_phys(urb->transfer_buffer);
+#else
 		buf = urb->transfer_dma;
+#endif
 	else
 		buf = 0;
 
@@ -712,8 +720,11 @@
 		info1 |= maxp << 16;
 
 		info2 |= (EHCI_TUNE_MULT_TT << 30);
+#ifdef CONFIG_FSL_USB20
+		info2 |= (urb->dev->ttport-1) << 23;
+#else
 		info2 |= urb->dev->ttport << 23;
-
+#endif
 		/* set the address of the TT; for ARC's integrated
 		 * root hub tt, leave it zeroed.
 		 */
@@ -863,7 +874,11 @@
 			dummy = qh->dummy;
 
 			dma = dummy->qtd_dma;
+#ifdef CONFIG_FSL_USB20
+			memcpy(dummy,qtd,sizeof(struct ehci_qtd));
+#else
 			*dummy = *qtd;
+#endif
 			dummy->qtd_dma = dma;
 
 			list_del (&qtd->qtd_list);
@@ -925,6 +940,7 @@
 	if (likely (qh != NULL)) {
 		if (likely (qh->qh_state == QH_STATE_IDLE))
 			qh_link_async (ehci, qh_get (qh));
+		
 	}
 	spin_unlock_irqrestore (&ehci->lock, flags);
 	if (unlikely (qh == NULL)) {
diff -Nur linux/drivers/usb/host/ehci-sched.c linux-8349-2.6/drivers/usb/host/ehci-sched.c
--- linux/drivers/usb/host/ehci-sched.c	2005-03-02 15:37:53.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/ehci-sched.c	2005-08-15 10:53:16.000000000 +0800
@@ -699,8 +699,11 @@
 
 	} else {
 		u32		addr;
-
+#ifdef CONFIG_FSL_USB20
+		addr = (u32)((dev->ttport-1) << 24);
+#else
 		addr = dev->ttport << 24;
+#endif
 		addr |= dev->tt->hub->devnum << 16;
 		addr |= epnum << 8;
 		addr |= dev->devnum;
@@ -759,15 +762,23 @@
 
 				itd = list_entry (entry, struct ehci_itd,
 						itd_list);
+#ifdef CONFIG_FSL_USB20
+				MEM_Put(ehci->itd_pool, itd);
+#else
 				dma_pool_free (ehci->itd_pool, itd,
 						itd->itd_dma);
+#endif
 			} else {
 				struct ehci_sitd	*sitd;
 
 				sitd = list_entry (entry, struct ehci_sitd,
 						sitd_list);
+#ifdef CONFIG_FSL_USB20
+   		                MEM_Put(ehci->sitd_pool, sitd);
+#else
 				dma_pool_free (ehci->sitd_pool, sitd,
 						sitd->sitd_dma);
+#endif
 			}
 		}
 
@@ -865,8 +876,11 @@
 )
 {
 	unsigned	i;
+#ifdef CONFIG_FSL_USB20
+	dma_addr_t      dma = virt_to_phys(urb->transfer_buffer);
+#else
 	dma_addr_t	dma = urb->transfer_dma;
-
+#endif
 	/* how many uframes are needed for these transfers */
 	iso_sched->span = urb->number_of_packets * stream->interval;
 
@@ -956,8 +970,14 @@
 
 		if (!itd) {
 			spin_unlock_irqrestore (&ehci->lock, flags);
+#ifdef CONFIG_FSL_USB20
+			itd = MEM_Get(ehci->itd_pool);
+			itd_dma = virt_to_phys(itd);
+
+#else
 			itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
 					&itd_dma);
+#endif
 			spin_lock_irqsave (&ehci->lock, flags);
 		}
 
@@ -1559,8 +1579,13 @@
 
 		if (!sitd) {
 			spin_unlock_irqrestore (&ehci->lock, flags);
+#ifdef CONFIG_FSL_USB20
+			sitd = MEM_Get (ehci->sitd_pool);
+			sitd_dma = virt_to_phys(sitd);
+#else
 			sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags,
 					&sitd_dma);
+#endif
 			spin_lock_irqsave (&ehci->lock, flags);
 		}
 
diff -Nur linux/drivers/usb/host/fsl-usb.c linux-8349-2.6/drivers/usb/host/fsl-usb.c
--- linux/drivers/usb/host/fsl-usb.c	1970-01-01 08:00:00.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/fsl-usb.c	2005-08-25 11:50:08.000000000 +0800
@@ -0,0 +1,303 @@
+/* 
+ * Copyright (c) 2005 freescale semiconductor
+ *
+ * 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/config.h>
+#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/errno.h>
+#include <linux/init.h>
+#include <linux/reboot.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <asm/unaligned.h>
+
+#include "../core/hcd.h"
+#include "fsl-usb.h"
+
+#define DRIVER_VERSION "$Revision: 1.11 $"
+#define DRIVER_AUTHOR "Hunter Wu"
+#define DRIVER_DESC "USB 2.0 Freescale EHCI Driver"
+#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
+
+MODULE_DESCRIPTION("MPC8249 USB Host Controller Driver");
+
+#include "ehci-hcd.c"
+
+void mpc8349_board_init(void)
+{
+	volatile unsigned char *bcsr5_p;
+
+	/* if SYS board is plug into PIB board, force to use the PHY on SYS board */
+	bcsr5_p = (volatile unsigned char *)(CFG_BCSR_BASE + 0x00000005); 
+	if ( (*bcsr5_p & BCSR5_INT_USB) == 0 ) 
+		*bcsr5_p = (*bcsr5_p | BCSR5_INT_USB);
+}
+
+void mpc8349_usb_clk_cfg(void)
+{
+	unsigned long sccr;
+	volatile unsigned long *p;
+	
+	p = (volatile unsigned long *)(CFG_IMMR_BASE + SCCR_OFFS); /* SCCR */
+	sccr = *p;
+		
+#if defined(CONFIG_MPH_USB_SUPPORT)
+	sccr &= ~SCCR_USB_MPHCM_11;
+	sccr |= SCCR_USB_MPHCM_11;  /* USB CLK 1:3 CSB CLK */
+	*p = sccr;
+#elif defined(CONFIG_DR_USB_SUPPORT)
+	sccr &= ~SCCR_USB_DRCM_11;
+	sccr |= SCCR_USB_DRCM_11;  /* USB CLK 1:3 CSB CLK */
+	*p = sccr;
+#endif
+
+}
+
+void mpc8349_usb_pin_cfg(void)
+{
+	unsigned long sicrl;
+	volatile unsigned long *p;
+	
+	p = (volatile unsigned long *)(CFG_IMMR_BASE + SICRL_OFFS); /* SCCR */
+	sicrl = *p;
+	
+#if defined(CONFIG_MPH_USB_SUPPORT)
+#ifdef CONFIG_MPH0_USB_ENABLE 
+	sicrl &= ~SICRL_USB0;
+	*p = sicrl;
+#endif
+
+#ifdef CONFIG_MPH1_USB_ENABLE
+	sicrl &= ~SICRL_USB1;
+	*p = sicrl;
+#endif
+#elif defined(CONFIG_DR_USB_SUPPORT)
+	sicrl &= ~SICRL_USB0;
+	sicrl |= SICRL_USB1 ;
+	*p = sicrl;
+#if defined(CONFIG_DR_UTMI)
+	sicrl &= ~SICRL_USB0;
+	sicrl |= SICRL_USB0;
+	*p = sicrl;
+#endif
+
+#endif
+}
+
+static void mpc8349_usb_reset(void)
+{
+	u32      portsc;
+    
+#if defined(CONFIG_MPH_USB_SUPPORT)    
+	t_USB_MPH_MAP *p_MphMemMap;
+	/* Enable PHY interface in the control reg. */
+	p_MphMemMap = (t_USB_MPH_MAP *)MPC83xx_USB_MPH_BASE;
+	p_MphMemMap->control = 0x00000004;
+	p_MphMemMap->snoop1 = 0x0000001b;
+#ifdef CONFIG_MPH0_USB_ENABLE
+	portsc = readl(&p_MphMemMap->port_status[0]);
+	portsc &= ~PORT_TS;
+#if defined(CONFIG_MPH0_ULPI)       
+	portsc |= PORT_TS_ULPI; 
+#elif defined (CONFIG_MPH0_SERIAL)
+	portsc |= PORT_TS_SERIAL;
+#endif	
+	writel(portsc,&p_MphMemMap->port_status[0]);
+#endif
+	
+#ifdef CONFIG_MPH1_USB_ENABLE
+	portsc = readl(&p_MphMemMap->port_status[1]);
+	portsc &= ~PORT_TS;
+#if defined(CONFIG_MPH1_ULPI)       
+	portsc |= PORT_TS_ULPI; 
+#elif defined (CONFIG_MPH1_SERIAL)
+	portsc |= PORT_TS_SERIAL;
+#endif	
+	writel(portsc,&p_MphMemMap->port_status[1]);
+#endif
+        
+	p_MphMemMap->pri_ctrl = 0x0000000c;
+	p_MphMemMap->age_cnt_thresh = 0x00000040;
+	p_MphMemMap->si_ctrl= 0x00000001;
+
+#elif defined(CONFIG_DR_USB_SUPPORT)
+	t_USB_DR_MAP *p_DrMemMap;
+	p_DrMemMap = (t_USB_DR_MAP *)MPC83xx_USB_DR_BASE;
+	p_DrMemMap->control = 0x00000004;
+	p_DrMemMap->snoop1 = 0x0000001b;
+	portsc = readl(&p_DrMemMap->port_status[0]);
+	portsc &= ~PORT_TS;
+#if defined(CONFIG_DR_ULPI)     
+	portsc |= PORT_TS_ULPI;
+#elif defined(CONFIG_DR_SERIAL)
+	portsc |= PORT_TS_SERIAL;
+#elif defined(CONFIG_DR_UTMI)
+	portsc |= PORT_TS_ULPI;
+#endif
+           
+	writel(portsc,&p_DrMemMap->port_status[0]);
+	writel(0x00000003,&p_DrMemMap->usbmode);
+	p_DrMemMap->pri_ctrl = 0x0000000c;
+	p_DrMemMap->age_cnt_thresh = 0x00000040;
+	p_DrMemMap->si_ctrl= 0x00000001;
+#endif
+}
+
+
+static int __init
+fsl_usb20_probe(struct device *dev)
+{
+	struct usb_hcd		*hcd;
+	struct ehci_hcd         *ehci;
+	int 			retval;
+#if defined (CONFIG_MPH_USB_SUPPORT)
+	t_USB_MPH_MAP 		*p_MphMemMap;
+#elif defined (CONFIG_DR_USB_SUPPORT)
+    	t_USB_DR_MAP 		*p_DrMemMap;
+#endif	
+	mpc8349_board_init();
+	mpc8349_usb_clk_cfg();
+	mpc8349_usb_pin_cfg();
+	
+	hcd = usb_create_hcd(&ehci_driver);
+	if (!hcd) {
+		retval = 0;
+		goto err1;
+	}
+
+	ehci = hcd_to_ehci(hcd);
+	dev_set_drvdata(dev, ehci);
+	
+#if defined(CONFIG_MPH_USB_SUPPORT)
+	p_MphMemMap = (t_USB_MPH_MAP *)MPC83xx_USB_MPH_BASE;
+        
+        hcd->regs = (void *)(&p_MphMemMap->hc_capbase);
+        hcd->irq = MPC83xx_USB_MPH_IVEC;
+
+#elif defined (CONFIG_DR_USB_SUPPORT)
+	/* Enable PHY interface in the control reg. */
+        p_DrMemMap = (t_USB_DR_MAP *)MPC83xx_USB_DR_BASE;
+    	hcd->regs = (void *)(&p_DrMemMap->hc_capbase);/* Set the interrupt that is called for this USB. */
+        hcd->irq = MPC83xx_USB_DR_IVEC;
+
+#endif
+
+	hcd->self.controller = dev;
+	hcd->self.bus_name = dev->bus_id;
+	hcd->product_desc ="fsl usb20";
+
+	retval = request_irq(hcd->irq, usb_hcd_irq, SA_INTERRUPT,hcd->driver->description, hcd);
+	if (retval != 0)
+		goto err2;
+	retval = usb_register_bus(&hcd->self);
+	if (retval < 0)
+		goto err3;
+
+	retval=ehci_hc_reset(hcd);
+
+	if (retval < 0)
+		goto err4;
+
+	if ((retval = ehci_start (hcd)) < 0) {
+		goto err4;
+	}
+
+	return 0;
+err4:
+	usb_deregister_bus(&hcd->self);
+err3:
+	free_irq(hcd->irq, hcd);
+err2:
+	usb_put_hcd(hcd);
+err1:
+	printk("init error, %d\n", retval);
+	return retval;	
+}
+
+static int __init_or_module
+fsl_usb20_remove(struct device *dev)
+{
+	struct ehci_hcd		*ehci = dev_get_drvdata(dev);
+	struct usb_hcd		*hcd = ehci_to_hcd(ehci);
+	
+
+	if (HCD_IS_RUNNING(hcd->state))
+		hcd->state = USB_STATE_QUIESCING;
+
+	usb_disconnect(&hcd->self.root_hub);
+	
+	hcd->driver->stop (hcd);
+	
+	usb_deregister_bus(&hcd->self);
+
+	free_irq(hcd->irq, hcd);
+
+	usb_put_hcd(hcd);
+	return 0;
+}
+	
+#define	fsl_usb20_suspend	NULL
+#define	fsl_usb20_resume	NULL
+
+static struct device_driver fsl_usb20_driver = {
+	.name =		(char *) hcd_name,
+	.bus =		&platform_bus_type,
+
+	.probe =	fsl_usb20_probe,
+	.remove =	fsl_usb20_remove,
+
+	.suspend =	fsl_usb20_suspend,
+	.resume =	fsl_usb20_resume,
+};
+
+/*-------------------------------------------------------------------------*/
+ 
+static int __init mpc8349_usb_hc_init(void) 
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	printk(KERN_INFO"driver %s, %s\n", hcd_name, DRIVER_VERSION);
+	return driver_register(&fsl_usb20_driver);
+}
+
+
+static void __exit mpc8349_usb_hc_deinit(void) 
+{	
+	driver_unregister(&fsl_usb20_driver);
+}
+MODULE_DESCRIPTION (DRIVER_INFO);
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_LICENSE ("GPL");
+module_init(mpc8349_usb_hc_init);
+module_exit(mpc8349_usb_hc_deinit);
diff -Nur linux/drivers/usb/host/fsl-usb.h linux-8349-2.6/drivers/usb/host/fsl-usb.h
--- linux/drivers/usb/host/fsl-usb.h	1970-01-01 08:00:00.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/fsl-usb.h	2005-08-25 11:49:00.000000000 +0800
@@ -0,0 +1,406 @@
+/* Copyright (c) 2005 freescale semiconductor
+ *
+ * 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 _MPC8349_USB_EHCI_H
+#define _MPC8349_USB_EHCI_H
+
+/**************************************************************************/
+/*@Description   t_USB_MPH_MAP - USB Multi-Port-Host internal memory map.*/
+/***************************************************************************/
+typedef   struct{
+	volatile u32    id;			/* Identification register */
+	volatile u32    hwgeneral;
+	volatile u32    hwhost;
+	volatile u8     RESERVED01[0x004];	/* Reserved area           */
+	volatile u32    hwtxbuf;
+	volatile u32    hwrxbuf;
+	volatile u8     RESERVED02[0x0e8];	/* Reserved area           */
+    
+	/* Capability Registers */
+	volatile u32    hc_capbase;
+	volatile u32    hcs_params;		/* HCSPARAMS - offset 0x4 */
+	volatile u32    hcc_params;		/* HCCPARAMS - offset 0x8 */
+	volatile u8     portroute [8];		/* nibbles for routing - offset 0xC */
+	volatile u8     RESERVED03[0x02c];	/* Reserved area           */
+
+	/* Operational Registers */
+	volatile u32    command;
+	volatile u32    status;
+	volatile u32    intr_enable;
+	volatile u32    frame_index;		/* current microframe number */
+	volatile u32    segment;		/* address bits 63:32 if needed */
+	volatile u32    frame_list;		/* points to periodic list */
+	volatile u32    async_next;		/* address of next async queue head */
+	volatile u32    async_tt_status;	/* async queue status for embedded TT */
+	volatile u32    burst_size;		/* programmable burst size */
+	volatile u32    txfilltuning;		/* host transmit pre-buffer packet tuning */
+	volatile u32    txttfilltuning;		/* host TT transmit pre-buffer packet tuning */
+	volatile u8     RESERVED04[4];
+	volatile u32    ulpi_view_port;		/* ULPI view port */
+	volatile u32    endpoint_nack;		/* endpoint nack */
+	volatile u32    endpoint_nack_en;	/* endpoint nack enable */
+	volatile u8     RESERVED05[4];
+	volatile u32    configured_flag;
+	volatile u32    port_status [2];	/* up to N_PORTS */
+   
+	volatile u8     RESERVED06[0x01c];	/* Reserved area           */
+	volatile u32    usbmode;
+	volatile u8     RESERVED07[0x254];	/* Reserved area           */
+	volatile u32    snoop1;
+	volatile u32    snoop2;
+	volatile u32    age_cnt_thresh;
+	volatile u32    si_ctrl;
+	volatile u32    pri_ctrl;
+	volatile u8     RESERVED08[0x0ec];	/* Reserved area           */
+	volatile u32    control;
+	volatile u8     RESERVED09[0xaf8];	/* Reserved area           */
+} t_USB_MPH_MAP;
+
+/**************************************************************************/
+/** @Description   t_USB_DR_MAP - USB Dual-Role internal memory map.      */
+/***************************************************************************/
+typedef   struct{
+	volatile u32    id;			/* Identification register */
+	volatile u32    hwgeneral;
+	volatile u32    hwhost;
+	volatile u32    hwdevice;
+	volatile u32    hwtxbuf;
+	volatile u32    hwrxbuf;
+	volatile u8     RESERVED01[0x0e8];	/* Reserved area           */
+   
+	/* Capability Registers */
+	volatile u32    hc_capbase;
+	volatile u32    hcs_params;		/* HCSPARAMS - offset 0x4 */
+	volatile u32    hcc_params;		/* HCCPARAMS - offset 0x8 */
+	volatile u8     portroute [8];		/* nibbles for routing - offset 0xC */
+	volatile u8     RESERVED02[0x00c];	/* Reserved area           */
+	volatile u32    dciversion;
+	volatile u32    dccparms;
+	volatile u8     RESERVED03[0x018];	/* Reserved area           */
+	   
+	/* Operational Registers */
+	volatile u32    command;
+	volatile u32    status;
+	volatile u32    intr_enable;
+	volatile u32    frame_index;		/* current microframe number */
+	union    t_host_slave_regs {
+		struct         t_ehci_regs 
+		{
+			volatile u32    segment;	/* address bits 63:32 if needed */
+			volatile u32    frame_list;	/* points to periodic list */
+			volatile u32    async_next;	/* address of next async queue head */
+		} host_regs;
+		struct         t_slave_regs {
+			volatile u8     RESERVED04 [0x04];
+			volatile u32    deviceaddr;
+			volatile u32    endpoint_list_addr;	/* points to periodic list */
+		} slave_regs;
+	} host_slave_regs;
+	volatile u32    async_tt_status;	/* async queue status for embedded TT */
+	volatile u32    burst_size;		/* programmable burst size */
+	volatile u32    txfilltuning;		/* host transmit pre-buffer packet tuning */
+	volatile u32    txttfilltuning;		/* host TT transmit pre-buffer packet tuning */
+	volatile u8     RESERVED04[4];
+	volatile u32    ulpi_view_port;		/* ULPI view port */
+	volatile u32    endpoint_nack;		/* endpoint nack */
+	volatile u32    endpoint_nack_en;	/* endpoint nack enable */
+	volatile u8     RESERVED05[4];
+	volatile u32    configured_flag;
+	volatile u32    port_status [1];	/* up to N_PORTS */
+	   
+	volatile u8     RESERVED06[0x01c];	/* Reserved area           */
+	volatile u32    otgsc;
+	volatile u32    usbmode;
+	volatile u32    endptsetupstat;
+	volatile u32    endptprime;
+	volatile u32    endptflush;
+	volatile u32    endptstatus;
+	volatile u32    endptcomplete;
+	volatile u32    endptctrl[6];
+	volatile u8     RESERVED07[0x228];	/* Reserved area           */
+	volatile u32    snoop1;
+	volatile u32    snoop2;
+	volatile u32    age_cnt_thresh;
+	volatile u32    si_ctrl;
+	volatile u32    pri_ctrl;
+	volatile u8     RESERVED08[0x0ec];	/* Reserved area           */
+	volatile u32    control;
+	volatile u8     RESERVED09[0xaf8];	/* Reserved area           */
+} __attribute__ ((packed)) t_USB_DR_MAP, * t_pUSB_DR_MAP;
+
+
+
+#define PORT_OFF        0
+#define PORT_ULPI       1
+#define PORT_UTMI       2
+#define PORT_SERIAL     3
+#define PORT_SERIAL_OTG 4
+
+
+#define PORT_TS          0xc0000000
+#define PORT_TS_UTMI     0x00000000
+#define PORT_TS_ULPI     0x80000000
+#define PORT_TS_SERIAL   0xc0000000
+#define PORT_TW          0x10000000
+#define PORT_SPD         0x0c000000
+#define PORT_FSC         0x01000000
+#define PORT_PP          0x00001000
+
+
+
+#define CFG_IMMR_BASE	        (0xfe000000)
+#define MPC83xx_USB_MPH_BASE    (CFG_IMMR_BASE + 0x22000)
+#define MPC83xx_USB_DR_BASE     (CFG_IMMR_BASE + 0x23000)
+#define MPC83xx_USB_DR_IVEC	(38)
+#define MPC83xx_USB_MPH_IVEC	(39)
+#define CFG_BCSR_BASE 		(0xfe100000)
+#define BCSR5_INT_USB		(0x02)
+
+#define e_USB_MPH 0
+#define e_USB_DR 1
+#define e_ULPI          0
+#define e_UTMI_8BIT     1 
+#define e_UTMI_16BIT    2
+#define e_SERIAL        3
+
+#define SCCR_OFFS          0xA08
+#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_USB1         0x40000000
+#define SICRL_USB0         0x20000000
+
+#define SICRH_OFFS         0x118
+#define SICRH_USB_UTMI     0x00020000
+
+#define SPCR_OFFS          0x00000110
+#define SPCR_TBEN          0x00400000
+
+#define POWER_OF_2(n)           (!(n & (n-1)))
+
+/*------------------------------------------------------*/
+
+typedef struct
+{
+	char		Name[4];	/* this segment's name          */
+	spinlock_t	lock;
+	u16		Num;	/* number of blocks in segment  */
+	int         Size;	/* size of blocks in segment    */
+				/* in case of TMP_DEF -         */
+				/* only the data                */
+	u32    	GetFailures;	/* number of times get failed   */
+	int	LocallyAllocated;	/* TRUE if memory was allocated */
+	/* at MEM_Init.	  */
+	u8   	*p_Base;	/* base address of segment      */
+	void  	**p_First;	/* first block in segment       */
+	void  	**p_Last;	/* last block in segment        */
+	int 	(*f_MemPut)(void* Handle, void *p_Block );
+				/* a routine for returning a memory block */
+
+	u16    	PrefixSize;	/* replaces B_OFFSET - how many     */
+				/* bytes to reserve before the data     */
+	u16    	PostfixSize ;	/* replaces B_TRAILER - how many   */
+				/* bytes to reserve after the data     */
+				/* Trailer also includes a pad needed for */
+				/* padding the entire block to 4 byte     */
+				/* alignment for faster access to the     */
+				/* control field                          */
+	u16    	Alignment;	/* requested alignment for the data field */
+	u16	AlignPad;	/* pad the offset field so that the data  */
+				/* field shall have the proper alignment  */
+	u16    	EndPad;		/* Pad to make entire block size a */
+				/* multiple of Alignment	*/
+} t_MemorySegment;
+
+#define PAD_ALIGNMENT( align, x ) ( ((x)%(align)) ? ((align)-((x)%(align))) : 0 )
+
+
+void *MEM_Get( void* Handle )
+{
+	unsigned long    	flags;	
+	u8            	*p_F;
+	t_MemorySegment 	*p ;
+	
+	p = (t_MemorySegment *)Handle;
+  
+	spin_lock_irqsave(&p->lock,flags);
+
+	/* check if the chain is not empty */
+	if( !(*(p->p_First)) )
+	{
+		p->GetFailures++;
+		spin_unlock_irqrestore(p->lock,flags);
+		return 0;
+	}
+	/* advance first pointer and return the old head of chain */
+	p_F = ((u8 *)p->p_First) + ( 4 + p->AlignPad + p->PrefixSize );   
+	p->p_First = (void **) *(p->p_First); /* skip the next pointer */
+
+	spin_unlock_irqrestore(&p->lock,flags);
+
+	return (void *)p_F;
+}
+
+
+int MEM_Put_Default( void * Handle, void *p_Block )
+{
+	unsigned long	flags;	
+	t_MemorySegment 	*p = (t_MemorySegment *)Handle;
+	u8            	*p_B = (u8 *)p_Block;
+   
+	/* if handle is NULL, use user's free routine */
+	if( Handle == 0 )
+	{
+		kfree( p_Block );
+		return 0;
+	}
+
+	spin_lock_irqsave(&p->lock,flags);
+
+	/* get the pointer to the start of the memory */
+	p_B -= ( 4 + p->AlignPad + p->PrefixSize );    /* skip back over next pointer */ 
+	/* chain to end and advance last pointer */
+	*((void **)p_B) = 0;
+	*(p->p_Last) = (void *)p_B;
+	p->p_Last = (void **)p_B;
+
+	spin_unlock_irqrestore(&p->lock,flags);
+	return 0;
+}
+
+int MEM_Init( char Name[], 
+	void* *p_Handle, 
+	u16 Num, 
+	u16 Size , 
+	u16 PrefixSize, 
+	u16 PostfixSize, 
+	u16 Alignment )
+{
+	t_MemorySegment 	*p;
+	u8            	*p_Blocks;
+	int              	i ;
+	int		     	blockSize;
+
+	/* always allocate a dummy block at the end */
+	Num++;
+
+	/* make sure size is always a multiple of 4 */
+	if( Size & 3 )
+	{
+		Size &= ~3;
+		Size += 4;
+	}
+
+	if (Alignment < 4 ) 
+		Alignment = 4;
+
+	/** make sure that the alignment is a power of two */
+	if( !POWER_OF_2(Alignment) ) 
+	{
+		printk("MEM_Init: requested alignment is not a power of two.\n");
+		return -EINVAL;
+	}                          
+
+	/* prepare in case of error */
+	*p_Handle = 0;
+
+	/* first allocate the segment descriptor */
+	p = (t_MemorySegment *)kmalloc( sizeof(t_MemorySegment),GFP_KERNEL );
+
+	if( !p )
+		return -ENOMEM;
+	/* calculate blockSize */
+  
+	/* store info about this segment */
+	spin_lock_init (&p->lock);
+	p->Num = (u16)(Num - 1);  
+	p->Size = Size;
+	p->GetFailures = 0L;
+	p->f_MemPut = MEM_Put_Default;
+	p->LocallyAllocated = 1;
+	p->PrefixSize = PrefixSize;
+	p->Alignment = Alignment; 
+	p->AlignPad  = (u16)PAD_ALIGNMENT((u16)4, (u16)PrefixSize+4); 
+	p->PostfixSize = PostfixSize;
+	/* Make sure the entire size is a multiple of Alignment */
+	p->EndPad = (u16)PAD_ALIGNMENT((u16)Alignment, 4 + p->AlignPad + PrefixSize + Size + PostfixSize); 
+
+	blockSize = 4 + p->AlignPad + PrefixSize + Size + PostfixSize + p->EndPad;
+
+	p_Blocks = (u8 *)kmalloc(( Alignment +  Num * blockSize ),GFP_KERNEL);
+
+	if( !p_Blocks )
+	{
+		kfree( p );
+		return -ENOMEM;
+	}
+	/* store the memory segment address */
+	p->p_Base = p_Blocks;
+	
+	p_Blocks += (PrefixSize+4);
+	p_Blocks += (PAD_ALIGNMENT( Alignment, (u32)p_Blocks)); 
+	p_Blocks -= (PrefixSize+4+p->AlignPad);
+
+	/* store name */
+	strncpy( p->Name, Name, 4 );
+
+	/* finally, initialize the blocks */
+	p->p_Last = p->p_First = (void **)p_Blocks;
+	for(i = 0; i < (Num-1); i++)
+	{
+	/* get next block */
+		p_Blocks += blockSize;
+
+	/* attach to end of chain */
+		if( p->p_Last )
+			*(p->p_Last) = (void *)p_Blocks;
+
+	/* advance last pointer */
+		p->p_Last = (void **)p_Blocks;
+	}
+
+	/* zero next pointer in last block */
+	*(p->p_Last) = 0;
+
+	/* return handle to caller */
+	*p_Handle = (void *)p;
+
+	return 0;
+}
+
+
+
+void  MEM_Free( void* p_Handle)
+{
+	t_MemorySegment *p = (t_MemorySegment*)p_Handle;
+
+	if ( p && p->LocallyAllocated)
+		kfree (p->p_Base);
+	kfree(p);
+}
+
+#define MEM_Put(Handle, p_Block)    \
+	((t_MemorySegment *)Handle)->f_MemPut( Handle, p_Block)
+
+
+
+
+#endif /* __STD_EXT_H */
diff -Nur linux/drivers/usb/host/Kconfig linux-8349-2.6/drivers/usb/host/Kconfig
--- linux/drivers/usb/host/Kconfig	2004-12-25 05:35:29.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/Kconfig	2005-08-16 14:58:56.000000000 +0800
@@ -5,6 +5,7 @@
 	boolean
 	default y if USB_ARCH_HAS_OHCI
 	default y if ARM				# SL-811
+	default y if FSL_USB20				# MPC83xx SYS
 	default PCI
 
 # many non-PCI hcds implement OHCI
@@ -24,7 +25,7 @@
 
 config USB_EHCI_HCD
 	tristate "EHCI HCD (USB 2.0) support"
-	depends on USB && PCI
+	depends on (USB && PCI) || (USB && FSL_USB20)
 	---help---
 	  The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
 	  "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
diff -Nur linux/drivers/usb/host/Makefile linux-8349-2.6/drivers/usb/host/Makefile
--- linux/drivers/usb/host/Makefile	2004-12-25 05:35:39.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/Makefile	2005-08-15 13:41:35.000000000 +0800
@@ -2,8 +2,11 @@
 # Makefile for USB Host Controller Driver
 # framework and drivers
 #
-
+ifeq ($(CONFIG_FSL_USB20),y)
+obj-$(CONFIG_USB_EHCI_HCD)	+= fsl-usb.o
+else
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
+endif
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
 obj-$(CONFIG_USB_UHCI_HCD)	+= uhci-hcd.o
 obj-$(CONFIG_USB_SL811_HCD)	+= sl811-hcd.o
diff -Nur linux/arch/ppc/platforms/83xx/Kconfig linux-8349-2.6/arch/ppc/platforms/83xx/Kconfig
--- linux/arch/ppc/platforms/83xx/Kconfig	2005-03-03 01:46:54.000000000 +0800
+++ linux-8349-2.6/arch/ppc/platforms/83xx/Kconfig	2005-08-25 11:44:57.000000000 +0800
@@ -27,4 +27,78 @@
 	depends on 83xx
 	default y
 
+config FSL_USB20
+	bool "MPC834x USB20 Host Support"
+	depends on MPC834x_SYS
+
+
+menu "USB20 Host Configuration"
+	depends on FSL_USB20 
+
+choice
+	prompt "MPC83xx USB20 host Mode"
+	depends on FSL_USB20 
+	default MPH_USB_SUPPORT
+
+config MPH_USB_SUPPORT
+	bool "MPH_MODE"
+		
+config DR_USB_SUPPORT
+	bool "DR_MODE"
+
+endchoice
+
+config MPH0_USB_ENABLE
+	bool "MPH0 USB HOST Enable"
+	depends on MPH_USB_SUPPORT
+
+choice
+	prompt "MPH0 PHY Interface Selection"
+	depends on MPH0_USB_ENABLE
+	default MPH0_ULPI
+
+config MPH0_ULPI
+	bool "ULPI"
+
+config MPH0_SERIAL
+	bool "Serial"
+
+endchoice
+
+config MPH1_USB_ENABLE
+	bool "MPH1 USB HOST Enable"
+	depends on MPH_USB_SUPPORT
+
+choice
+	prompt "MPH1 PHY Interface Selection"
+	depends on MPH1_USB_ENABLE
+	default MPH1_ULPI
+
+config MPH1_ULPI
+	bool "ULPI"
+
+config MPH1_SERIAL
+	bool "Serial"
+
+endchoice
+
+
+choice
+	prompt "DR PHY Interface Selection"
+	depends on DR_USB_SUPPORT
+	default DR_ULPI
+
+config DR_ULPI
+	bool "ULPI"
+
+config DR_SERIAL
+	bool "Serial"
+
+config DR_UTMI
+	bool "UTMI"
+
+endchoice
+
+endmenu
+
 endmenu


--
Leo Li
Freescale Semiconductor
 
LeoLi at freescale.com 
 




More information about the Linuxppc-embedded mailing list