Hi all, I did other tests with this driver (attaching the latest version). Now I'm using a custom USB device, so that I can easily dump the device's internal memory and monitor the actual data received from the host controller. I use a simple testcase: I'm sending a buffer from the host controller to the device via control transfer, the device stores the buffer into its internal memory, then I re-read back the buffer and compare the data. I've found a very predictable pattern, only transfers using multiple of 8 bytes seem to succeed, in all the other cases I re-read wrong data at the end of the buffer (only for the reminder, considering 8-bytes chunks): bufsize 1: mismatch bufsize 2: mismatch bufsize 3: mismatch bufsize 4: mismatch bufsize 5: mismatch bufsize 6: mismatch bufsize 7: mismatch bufsize 8: ok bufsize 9: mismatch bufsize 10: mismatch bufsize 11: mismatch bufsize 12: mismatch bufsize 13: mismatch bufsize 14: mismatch bufsize 15: mismatch bufsize 16: ok bufsize 17: mismatch bufsize 18: mismatch bufsize 19: mismatch bufsize 20: mismatch bufsize 21: mismatch bufsize 22: mismatch bufsize 23: mismatch bufsize 24: ok ... [ always the same pattern up to bufsize=4096 ] So, it seems there's a big problem with the hardware... The datasheet states that it's possible to configure the burst-size for TX and RX operations and the default value is very suspicious (default burst len is 8 bytes): BurstSize Offset: 0x0160 Reset: 0x00000808 Read/write (writes must be DWord) - TX Prog Burst (bit 15-8): Programmable TX burst length. Maximum length of a burst, in 32-bit Burst words, while moving data from system memory to the USB. Default 8 - RX Prog Burst (bit 7-0): Programmable RX burst length. Maximum length of a burst, in 32-bit Burst words, while moving data from the USB to system memory. Default 8 Unfortunately, setting a different value doesn't seem to change anything. Maybe I misunderstand the meaning of this BurtSize setting, or I'm missing something else, but I can't find other concerning parameters in the datasheet. [ For those who worked in the past with the same chip: did you find a similar behaviour? Am I missing some obvious configurations? ] Could you suggest me if there's a possible way to workaround this issue at the EHCI layer? BTW padding the urb size to the upper 8-bytes (for example) is not a vaild solution, because the device could receive more data than the amount requested, causing unpredictable results. Thanks, -Andrea Signed-off-by: Andrea Righi <arighi@xxxxxxxxxxx> --- arch/x86/Kconfig | 2 +- drivers/usb/core/hcd.c | 47 ++++-- drivers/usb/host/Kconfig | 10 + drivers/usb/host/ehci-hcd.c | 25 +++- drivers/usb/host/ehci-oxu210hp.c | 370 ++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci-oxu210hp.h | 77 ++++++++ 6 files changed, 513 insertions(+), 18 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index dcb0593..2396776 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -43,7 +43,7 @@ config X86 select HAVE_KVM select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK - select HAVE_GENERIC_DMA_COHERENT if X86_32 + select HAVE_GENERIC_DMA_COHERENT select HAVE_EFFICIENT_UNALIGNED_ACCESS select USER_STACKTRACE_SUPPORT select HAVE_REGS_AND_STACK_ACCESS_API diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 12742f1..cabb14d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1212,28 +1212,43 @@ EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep); * */ +/* + * TODO: need refactoring. + * + * This is only needed to avoid the corruption of the coherent memory + * allocations with the EV-OXU210-PCI controller, that can only perform 8-bytes + * chunk r/w operations. + */ +#define HCD_COHERENT_CHUNK 8 static int hcd_alloc_coherent(struct usb_bus *bus, gfp_t mem_flags, dma_addr_t *dma_handle, void **vaddr_handle, size_t size, enum dma_data_direction dir) { unsigned char *vaddr; + size_t size2; - vaddr = hcd_buffer_alloc(bus, size + sizeof(vaddr), - mem_flags, dma_handle); - if (!vaddr) - return -ENOMEM; + if (*vaddr_handle == NULL) { + WARN_ON_ONCE(1); + return -EFAULT; + } /* - * Store the virtual address of the buffer at the end - * of the allocated dma buffer. The size of the buffer - * may be uneven so use unaligned functions instead - * of just rounding up. It makes sense to optimize for - * memory footprint over access speed since the amount - * of memory available for dma may be limited. + * Store the address of the original buffer at the end of the + * newly-allocated dma buffer, so that it can be put back when + * the dma buffer is deallocated. + * + * Avoid unaligned accesses (which some buses can't handle) by rounding + * up to a multiple of HCD_COHERENT_CHUNK. */ - put_unaligned((unsigned long)*vaddr_handle, - (unsigned long *)(vaddr + size)); + size2 = HCD_COHERENT_CHUNK * + DIV_ROUND_UP(size + sizeof(vaddr), HCD_COHERENT_CHUNK); + vaddr = hcd_buffer_alloc(bus, size2, mem_flags, dma_handle); + + if (!vaddr) + return -ENOMEM; + + *(void **)(vaddr + size2 - sizeof(vaddr)) = *vaddr_handle; if (dir == DMA_TO_DEVICE) memcpy(vaddr, *vaddr_handle, size); @@ -1247,17 +1262,21 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle, enum dma_data_direction dir) { unsigned char *vaddr = *vaddr_handle; + size_t size2; - vaddr = (void *)get_unaligned((unsigned long *)(vaddr + size)); + size2 = HCD_COHERENT_CHUNK * + DIV_ROUND_UP(size + sizeof(vaddr), HCD_COHERENT_CHUNK); + vaddr = *(void **)(vaddr + size2 - sizeof(vaddr)); if (dir == DMA_FROM_DEVICE) memcpy(vaddr, *vaddr_handle, size); - hcd_buffer_free(bus, size + sizeof(vaddr), *vaddr_handle, *dma_handle); + hcd_buffer_free(bus, size2, *vaddr_handle, *dma_handle); *vaddr_handle = vaddr; *dma_handle = 0; } +#undef HCD_COHERENT_SIZE static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) { diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f865be2..1668a5c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -137,6 +137,16 @@ config USB_W90X900_EHCI ---help--- Enables support for the W90X900 USB controller +config USB_EHCI_OXU210HP_PCI + bool "EHCI based EV-OXU210HP-PCI HCD support (EXPERIMENTAL)" + depends on PCI && USB_EHCI_HCD && EXPERIMENTAL + default n + ---help--- + The EV-OXU210HP-PCI is an USB host/OTG/device controller. Enable this + option if you have this evaluation board connected to the PCI bus. + + If unsure, say N. + config USB_OXU210HP_HCD tristate "OXU210HP HCD support" depends on USB diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a3ef2a9..c0b5a4b 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -606,7 +606,8 @@ static int ehci_init(struct usb_hcd *hcd) ehci->command = temp; /* Accept arbitrarily long scatter-gather lists */ - hcd->self.sg_tablesize = ~0; + if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + hcd->self.sg_tablesize = ~0; return 0; } @@ -1103,6 +1104,11 @@ MODULE_LICENSE ("GPL"); #define PCI_DRIVER ehci_pci_driver #endif +#ifdef CONFIG_USB_EHCI_OXU210HP_PCI +#include "ehci-oxu210hp.c" +#define OXU210HP_DRIVER oxu210hp_ehci_driver +#endif + #ifdef CONFIG_USB_EHCI_FSL #include "ehci-fsl.c" #define PLATFORM_DRIVER ehci_fsl_driver @@ -1160,7 +1166,7 @@ MODULE_LICENSE ("GPL"); #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ - !defined(XILINX_OF_PLATFORM_DRIVER) + !defined(XILINX_OF_PLATFORM_DRIVER) && !defined(OXU210HP_DRIVER) #error "missing bus glue for ehci-hcd" #endif @@ -1220,10 +1226,20 @@ static int __init ehci_hcd_init(void) if (retval < 0) goto clean4; #endif + +#ifdef OXU210HP_DRIVER + retval = pci_register_driver(&oxu210_pci_driver); + if (retval < 0) + goto clean5; +#endif return retval; +#ifdef OXU210HP_DRIVER + /* pci_unregister_driver(&oxu210_pci_driver); */ +clean5: +#endif #ifdef XILINX_OF_PLATFORM_DRIVER - /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */ + of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); clean4: #endif #ifdef OF_PLATFORM_DRIVER @@ -1254,6 +1270,9 @@ module_init(ehci_hcd_init); static void __exit ehci_hcd_cleanup(void) { +#ifdef OXU210HP_DRIVER + pci_unregister_driver(&oxu210_pci_driver); +#endif #ifdef XILINX_OF_PLATFORM_DRIVER of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); #endif diff --git a/drivers/usb/host/ehci-oxu210hp.c b/drivers/usb/host/ehci-oxu210hp.c new file mode 100644 index 0000000..82ad041 --- /dev/null +++ b/drivers/usb/host/ehci-oxu210hp.c @@ -0,0 +1,370 @@ +/* + * EV-OXU210-PCI EHCI Host Controller Driver + * + * Copyright (c) 2010 Andrea Righi <arighi@xxxxxxxxxxx> + * + * Part of this code is based on the OXU210HP-HCD driver by Rodolfo Giometti + * <giometti@xxxxxxxx> and EHCI-OXU210HP by Amit Walambe + * <amit.walambe@xxxxxxxxxxxx>. + * + * 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/irq.h> +#include <linux/pci.h> +#include <linux/types.h> +#include <asm-generic/dma-coherent.h> + +#include "ehci-oxu210hp.h" + +/* OXU210 PCI definitions */ +#define OXU210_PCI_VENDOR_ID 0x192e +#define OXU210_PCI_DEVICE_ID 0x032b +#define OXU210_PCI_BAR 3 +#define OXU210_MEM_SIZE 0x20000 + +/* OXU210 configurations */ +#define OXU_STARTUP_CONFIG 0x00000b7c + +static int oxu210hp_reset(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + int ret; + + printk(KERN_INFO "initializing SPH controller\n"); + + ehci->caps = hcd->regs + OXU_SPH_CAP_OFFSET; + ehci->regs = hcd->regs + OXU_SPH_CAP_OFFSET + HC_LENGTH(ehci_readl(ehci, + &ehci->caps->hc_capbase)); + dbg_hcs_params(ehci, "reset"); + dbg_hcc_params(ehci, "reset"); + + /* Cache this readonly data: minimize chip reads */ + ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); + + ret = ehci_halt(ehci); + if (ret) + return ret; + ret = ehci_init(hcd); + if (ret) + return ret; + + /* Serial Bus Release Number is at PCI 0x60 offset */ + pci_read_config_byte(pdev, 0x60, &ehci->sbrn); + + hcd->has_tt = 1; + tdi_reset(ehci); + + ehci_reset(ehci); + + /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */ + if (!pci_set_mwi(pdev)) + ehci_dbg(ehci, "MWI active\n"); + + ehci_port_power(ehci, 1); + if (!pci_set_mwi(pdev)) + ehci_dbg(ehci, "MWI active\n"); + return ret; +} + +static const struct hc_driver oxu210hp_ehci_hc_driver = { + .description = hcd_name, + .product_desc = "EV-OXU210-PCI EHCI Host Controller", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* generic hardware linkage */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_LOCAL_MEM | HCD_USB2, + + /* basic lifecycle operations */ + .reset = oxu210hp_reset, + .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, + .endpoint_reset = ehci_endpoint_reset, + + /* scheduling support */ + .get_frame_number = ehci_get_frame, + + /* root hub support */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, +#if defined(CONFIG_PM) + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, +#endif + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, + + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +}; + +static struct usb_hcd *oxu210hp_create(struct pci_dev *pdev, + unsigned long memstart, unsigned long memlen, + void *base, int irq) +{ + struct device *dev = &pdev->dev; + struct usb_hcd *hcd; + int ret; + + /* Set endian mode and host mode */ + writel(OXU_CM_HOST_ONLY | OXU_ES_LITTLE | OXU_VBPS, + base + OXU_SPH_CORE_OFFSET + OXU_USBMODE); + hcd = usb_create_hcd(&oxu210hp_ehci_hc_driver, dev, "oxu210hp_sph"); + if (!hcd) + return ERR_PTR(-ENOMEM); + + hcd->rsrc_start = memstart; + hcd->rsrc_len = memlen; + hcd->regs = base; + hcd->irq = irq; + hcd->state = HC_STATE_HALT; + + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (ret < 0) + return ERR_PTR(ret); + return hcd; +} + +static void oxu210hp_configuration(struct pci_dev *pdev, void *base) +{ + u32 reg; + + /* Initialize top level registers */ + writel(OXU_STARTUP_CONFIG, base + OXU_HOSTIFCONFIG); + writel(OXU_SRESET, base + OXU_SOFTRESET); + writel(OXU_STARTUP_CONFIG, base + OXU_HOSTIFCONFIG); + + /* Disable PIO & SDMA burst read*/ + writel(0, base + OXU_PIOBURSTREADCTRL); + writel(0, base + OXU_SDMABURSTREADCTRL); + + /* Application-speicific register */ + writel(OXU_SPHPOEN | OXU_OVRCCURPUPDEN | OXU_COMPARATOR | OXU_ASO_OP, + base + OXU_ASO); + + /* Configure clocking */ + writel(OXU_CLK_120MHZ, base + OXU_CLKFREQ); + reg = readl(base + OXU_CLKCTRL_SET); + writel(reg | OXU_SYSCLKEN, base + OXU_CLKCTRL_SET); + + /* Clear all top interrupt enable */ + writel(0xff, base + OXU_CHIPIRQEN_CLR); + + /* Clear all top interrupt status */ + writel(0xff, base + OXU_CHIPIRQSTATUS); + + /* Enable all needed top interrupt except OTG SPH core */ + writel(OXU_USBSPHLPWUI | OXU_USBOTGLPWUI, base + OXU_CHIPIRQEN_SET); +} + +static int oxu210hp_verify_id(struct pci_dev *pdev, void *base) +{ + const char *bo[] = { + "reserved", + "128-pin LQFP", + "84-pin TFBGA", + "reserved", + }; + u32 id; + + /* Read controller signature register to find a match */ + id = readl(base + OXU_DEVICEID); + dev_info(&pdev->dev, "device ID %x\n", id); + if ((id & OXU_REV_MASK) != (OXU_REV_2100 << OXU_REV_SHIFT)) + return -ENODEV; + dev_info(&pdev->dev, "found device %x %s (%04x:%04x)\n", + id >> OXU_REV_SHIFT, + bo[(id & OXU_BO_MASK) >> OXU_BO_SHIFT], + (id & OXU_MAJ_REV_MASK) >> OXU_MAJ_REV_SHIFT, + (id & OXU_MIN_REV_MASK) >> OXU_MIN_REV_SHIFT); + return 0; +} + +static int oxu210hp_init(struct pci_dev *pdev, + unsigned long memstart, unsigned long memlen, + void *base, int irq) +{ + struct usb_hcd *hcd = pci_get_drvdata(pdev); + int ret; + + oxu210hp_configuration(pdev, base); + + ret = oxu210hp_verify_id(pdev, base); + if (ret) { + dev_err(&pdev->dev, "no device found!\n"); + return -ENODEV; + } + + /* Create the SPH host controller */ + hcd = oxu210hp_create(pdev, memstart, memlen, base, irq); + if (IS_ERR(hcd)) { + dev_err(&pdev->dev, "could not create SPH controller!\n"); + return PTR_ERR(hcd); + } + pci_set_drvdata(pdev, hcd); + + writel(readl(base + OXU_CHIPIRQEN_SET) | OXU_USBSPHI, + base + OXU_CHIPIRQEN_SET); + return 0; +} + +static int +oxu210hp_ehci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + void __iomem *base; + unsigned long memstart, memlen; + int ret = 0; + + ret = pci_enable_device(pdev); + if (ret < 0) { + dev_err(&pdev->dev, "could not enable device\n"); + return ret; + } + if (!(pci_resource_flags(pdev, OXU210_PCI_BAR) & IORESOURCE_MEM)) { + dev_err(&pdev->dev, + "region #%d not an MMIO resource\n", + OXU210_PCI_BAR); + ret = -ENODEV; + goto err_out_disable; + } + memlen = pci_resource_len(pdev, OXU210_PCI_BAR); + if (memlen < OXU210_MEM_SIZE) { + dev_err(&pdev->dev, "invalid PCI region size\n"); + ret = -ENODEV; + goto err_out_disable; + } + ret = pci_request_regions(pdev, "oxu210hp-ehci"); + if (ret < 0) { + dev_err(&pdev->dev, "could not request regions\n"); + goto err_out_disable; + } + ret = set_irq_type(pdev->irq, IRQF_TRIGGER_FALLING); + if (ret < 0) { + dev_err(&pdev->dev, "error setting irq type\n"); + ret = -EFAULT; + goto err_out_release; + } + dev_info(&pdev->dev, "IRQ resource %d\n", pdev->irq); + memstart = pci_resource_start(pdev, OXU210_PCI_BAR); + + /* + * OXU210 memory map + * + * Block Address Size + * ----------------------------------------- + * Host interface 0x0000 1KB + * USB OTG regs 0x0400 1KB + * USB SPH regs 0x0800 1KB + * Reserved 0x0c00 1KB + * Memory expansion 0x1000 12KB + * Reserved 0x4000 32KB + * Memory expansion 0xc000 8KB + * Static RAM 0xe000 72KB + */ + base = ioremap(memstart, OXU_REG_SIZE); + if (!base) { + dev_err(&pdev->dev, "could not remap MMIO\n"); + ret = -EIO; + goto err_out_release; + } + if (!dma_declare_coherent_memory(&pdev->dev, + memstart + OXU_SRAM_OFFSET, /* bus address */ + memstart + OXU_SRAM_OFFSET, /* device address */ + OXU_SRAM_SIZE, /* size */ + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE)) { + dev_err(&pdev->dev, + "could not declare DMA coherent memory\n"); + ret = -ENXIO; + goto err_out_iounmap; + } + + /* prevent usb-core allocating system DMA pages */ + pdev->dev.dma_mask = NULL; + + /* Initialize OXU210 chipset */ + ret = oxu210hp_init(pdev, memstart, OXU_REG_SIZE, base, pdev->irq); + if (ret < 0) { + dev_dbg(&pdev->dev, "cannot init USB devices\n"); + goto err_out_dma; + } + dev_info(&pdev->dev, "devices enabled and running\n"); +out: + return ret; + +err_out_dma: + dma_release_declared_memory(&pdev->dev); +err_out_iounmap: + iounmap(base); +err_out_release: + pci_release_regions(pdev); +err_out_disable: + pci_disable_device(pdev); + goto out; +} + +static void oxu210hp_ehci_remove(struct pci_dev *pdev) +{ + struct usb_hcd *hcd; + + hcd = pci_get_drvdata(pdev); + if (!hcd) + return; + + usb_remove_hcd(hcd); + iounmap(hcd->regs); + pci_release_regions(pdev); + dma_release_declared_memory(&pdev->dev); + + dev_set_drvdata(&pdev->dev, NULL); + usb_put_hcd(hcd); + + pci_disable_device(pdev); +} + +static void oxu210hp_ehci_shutdown(struct pci_dev *pdev) +{ + struct usb_hcd *hcd; + + hcd = pci_get_drvdata(pdev); + if (!hcd) + return; + if (hcd->driver->shutdown) + hcd->driver->shutdown(hcd); +} + +MODULE_ALIAS("oxu210hp-ehci"); + +static struct pci_device_id oxu210hp_pci_table[] = { + { PCI_DEVICE(OXU210_PCI_VENDOR_ID, OXU210_PCI_DEVICE_ID), 0, 0, + (unsigned long)&oxu210hp_ehci_hc_driver}, + { }, +}; +MODULE_DEVICE_TABLE(pci, oxu210hp_pci_table); + +static struct pci_driver oxu210_pci_driver = { + .name = "oxu210hp-ehci", + .id_table = oxu210hp_pci_table, + + .probe = oxu210hp_ehci_probe, + .remove = oxu210hp_ehci_remove, + .shutdown = oxu210hp_ehci_shutdown, +}; diff --git a/drivers/usb/host/ehci-oxu210hp.h b/drivers/usb/host/ehci-oxu210hp.h new file mode 100644 index 0000000..8f93ff8 --- /dev/null +++ b/drivers/usb/host/ehci-oxu210hp.h @@ -0,0 +1,77 @@ +#ifndef EHCI_OXU210HP_H +#define EHCI_OXU210HP_H + +/* + * OXU210 registers and values definition + */ + +#define OXU_DEVICEID 0x00 + #define OXU_REV_MASK 0xffff0000 + #define OXU_REV_SHIFT 16 + #define OXU_REV_2100 0x2100 + #define OXU_BO_SHIFT 8 + #define OXU_BO_MASK (0x3 << OXU_BO_SHIFT) + #define OXU_MAJ_REV_SHIFT 4 + #define OXU_MAJ_REV_MASK (0xf << OXU_MAJ_REV_SHIFT) + #define OXU_MIN_REV_SHIFT 0 + #define OXU_MIN_REV_MASK (0xf << OXU_MIN_REV_SHIFT) +#define OXU_HOSTIFCONFIG 0x04 +#define OXU_SOFTRESET 0x08 + #define OXU_SRESET (1 << 0) + +#define OXU_PIOBURSTREADCTRL 0x0C +#define OXU_SDMABURSTREADCTRL 0x108 + +#define OXU_CHIPIRQSTATUS 0x10 +#define OXU_CHIPIRQEN_SET 0x14 +#define OXU_CHIPIRQEN_CLR 0x18 + #define OXU_USBSPHLPWUI 0x00000080 + #define OXU_USBOTGLPWUI 0x00000040 + #define OXU_USBSPHI 0x00000002 + #define OXU_USBOTGI 0x00000001 + +#define OXU_CLKCTRL_SET 0x1C + #define OXU_SYSCLKEN 0x00000008 + #define OXU_USBSPHCLKEN 0x00000002 + #define OXU_USBOTGCLKEN 0x00000001 + +#define OXU_CLKFREQ 0x24 + #define OXU_CLK_60MHZ 0x00000001 + #define OXU_CLK_80MHZ 0x00000003 + #define OXU_CLK_120MHZ 0x00000000 + #define OXU_CLK_160MHZ 0x00000002 + +#define OXU_ASO 0x68 + #define OXU_SPHPOEN 0x00000100 + #define OXU_OVRCCURPUPDEN 0x00000800 + #define OXU_ASO_OP (1 << 10) + #define OXU_COMPARATOR 0x000004000 + +#define OXU_USBMODE 0x1A8 + #define OXU_VBPS 0x00000020 + #define OXU_ES_LITTLE 0x00000000 + #define OXU_CM_HOST_ONLY 0x00000003 + +/* + * OXU210HP memory organization + */ + +#define OXU_OTG_CORE_OFFSET 0x00400 +#define OXU_OTG_CAP_OFFSET (OXU_OTG_CORE_OFFSET + 0x100) +#define OXU_SPH_CORE_OFFSET 0x00800 +#define OXU_SPH_CAP_OFFSET (OXU_SPH_CORE_OFFSET + 0x100) + +/* + * Register space is limited to the first 4KB of the first 32KB memory section: + * Chip, GPIO, slave DMA & mailbox registers. + */ +#define OXU_REG_OFFSET 0x1000 +#define OXU_REG_SIZE 0x1000 + +#define OXU_SRAM_OFFSET 0xe000 +#define OXU_SRAM_END 0x20000 +#define OXU_SRAM_SIZE (OXU_SRAM_END - OXU_SRAM_OFFSET) + +#include <linux/oxu210hp.h> + +#endif /* EHCI_OXU210HP_H */ -- 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