>From 4280095e078f49e66890fc41ba2d78240eb93acc Mon Sep 17 00:00:00 2001 From: Jacob Pan <jacob.jun.pan@xxxxxxxxx> Date: Wed, 20 May 2009 14:41:55 +0800 Subject: [PATCH] EHCI: Support Intel Moorestown EHCI controller SRAM QH/QTD/ITD/SITD pool caching The Intel Moorestown platform has MPH and OTG EHCI controllers that have Internal SRAM could be used as descriptors DMA pool caching. The SRAM are exposed via PCI BAR1. The limitation here is the SRAM access should be 32bit aligned. A separate patch "EHCI: Make ehci_qh structure items all 32bit aligned" has been submitted to linux-usb mailling list. Signed-off-by: Jacob Pan <jacob.jun.pan@xxxxxxxxx> Signed-off-by: Alek Du <alek.du@xxxxxxxxx> --- drivers/usb/core/buffer.c | 5 +++++ drivers/usb/core/hcd.h | 1 + drivers/usb/host/ehci-hcd.c | 3 ++- drivers/usb/host/ehci-pci.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 8 +++++++- 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 3ba2fff..ab0f462 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -115,6 +115,11 @@ void *hcd_buffer_alloc( return kmalloc(size, mem_flags); } + /* we won't use internal SRAM as data payload, we can't get + any benefits from it */ + if (hcd->has_sram) + return dma_alloc_coherent(NULL, size, dma, mem_flags); + for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (size <= pool_max [i]) return dma_pool_alloc(hcd->pool [i], mem_flags, dma); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index e7d4479..696fcf2 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -104,6 +104,7 @@ struct usb_hcd { unsigned wireless:1; /* Wireless USB HCD */ unsigned authorized_default:1; unsigned has_tt:1; /* Integrated TT in root hub */ + unsigned has_sram:1; /* Local SRAM for caching */ int irq; /* irq allocated */ void __iomem *regs; /* device memory/io */ diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 32f79c7..89d4e52 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -495,7 +495,8 @@ static void ehci_stop (struct usb_hcd *hcd) ehci_work (ehci); spin_unlock_irq (&ehci->lock); ehci_mem_cleanup (ehci); - + if (hcd->has_sram) + sram_deinit(hcd); #ifdef EHCI_STATS ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index b9f4b88..b68ec9b 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -61,6 +61,39 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) return 0; } +/* enable SRAM if sram detected */ +static void sram_init(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + + if (!hcd->has_sram) + return; + ehci->sram_addr = pci_resource_start(pdev, 1); + ehci->sram_size = pci_resource_len(pdev, 1); + ehci_info(ehci, "Found HCD SRAM at %x size:%x\n", + ehci->sram_addr, ehci->sram_size); + if (pci_request_region(pdev, 1, kobject_name(&pdev->dev.kobj))) { + ehci_warn(ehci, "SRAM request failed\n"); + hcd->has_sram = 0; + } else if (!dma_declare_coherent_memory(&pdev->dev, ehci->sram_addr, + ehci->sram_addr, ehci->sram_size, DMA_MEMORY_MAP)) { + ehci_warn(ehci, "SRAM DMA declare failed\n"); + pci_release_region(pdev, 1); + hcd->has_sram = 0; + } +} + +static void sram_deinit(struct usb_hcd *hcd) +{ + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + + if (!hcd->has_sram) + return; + dma_release_declared_memory(&pdev->dev); + pci_release_region(pdev, 1); +} + /* called during probe() after chip reset completes */ static int ehci_pci_setup(struct usb_hcd *hcd) { @@ -92,11 +125,15 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ehci->has_hostpc = 1; ehci->has_otg = 1; force_otg_hc_mode = 1; + hcd->has_sram = 1; + sram_init(hcd); } else if (pdev->device == 0x0806) { ehci_info(ehci, "Detected Langwell MPH\n"); ehci->no_io_watchdog = 1; hcd->has_tt = 1; ehci->has_hostpc = 1; + hcd->has_sram = 1; + sram_init(hcd); } } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index a58640d..6972089 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -142,6 +142,8 @@ struct ehci_hcd { /* one per controller */ int (*otg_resume)(struct usb_hcd *hcd); u8 sbrn; /* packed release number */ + unsigned int sram_addr; + unsigned int sram_size; /* irq statistics */ #ifdef EHCI_STATS @@ -722,5 +724,9 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) #endif /* DEBUG */ /*-------------------------------------------------------------------------*/ - +#ifdef CONFIG_PCI +static void sram_deinit(struct usb_hcd *hcd); +#else +static void sram_deinit(struct usb_hcd *hcd) { return; }; +#endif #endif /* __LINUX_EHCI_HCD_H */ -- 1.6.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html