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 + +/**************************************************************************/ +/[EMAIL PROTECTED] 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