Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: EHCI big endian data structures support (for 440EPx)

This patch adds support for the AMCC 440EPx EHCI controller whose
in-memory data structures and the registers are represented in big-
endian format.

Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Stefan Roese and committed by
Greg Kroah-Hartman
fc65a15f 97cd49eb

+187
+5
drivers/usb/host/ehci-hcd.c
··· 1009 1009 #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_sb_driver 1010 1010 #endif 1011 1011 1012 + #ifdef CONFIG_440EPX 1013 + #include "ehci-ppc-soc.c" 1014 + #define PLATFORM_DRIVER ehci_ppc_soc_driver 1015 + #endif 1016 + 1012 1017 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ 1013 1018 !defined(PS3_SYSTEM_BUS_DRIVER) 1014 1019 #error "missing bus glue for ehci-hcd"
+182
drivers/usb/host/ehci-ppc-soc.c
··· 1 + /* 2 + * EHCI HCD (Host Controller Driver) for USB. 3 + * 4 + * (C) Copyright 2006-2007 Stefan Roese <sr@denx.de>, DENX Software Engineering 5 + * 6 + * Bus Glue for PPC On-Chip EHCI driver 7 + * Tested on AMCC 440EPx 8 + * 9 + * Based on "ehci-au12xx.c" by David Brownell <dbrownell@users.sourceforge.net> 10 + * 11 + * This file is licenced under the GPL. 12 + */ 13 + 14 + #include <linux/platform_device.h> 15 + 16 + extern int usb_disabled(void); 17 + 18 + /** 19 + * usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs 20 + * Context: !in_interrupt() 21 + * 22 + * Allocates basic resources for this USB host controller, and 23 + * then invokes the start() method for the HCD associated with it 24 + * through the hotplug entry's driver_data. 25 + * 26 + */ 27 + int usb_ehci_ppc_soc_probe(const struct hc_driver *driver, 28 + struct usb_hcd **hcd_out, 29 + struct platform_device *dev) 30 + { 31 + int retval; 32 + struct usb_hcd *hcd; 33 + struct ehci_hcd *ehci; 34 + 35 + if (dev->resource[1].flags != IORESOURCE_IRQ) { 36 + pr_debug("resource[1] is not IORESOURCE_IRQ"); 37 + retval = -ENOMEM; 38 + } 39 + hcd = usb_create_hcd(driver, &dev->dev, "PPC-SOC EHCI"); 40 + if (!hcd) 41 + return -ENOMEM; 42 + hcd->rsrc_start = dev->resource[0].start; 43 + hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; 44 + 45 + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 46 + pr_debug("request_mem_region failed"); 47 + retval = -EBUSY; 48 + goto err1; 49 + } 50 + 51 + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); 52 + if (!hcd->regs) { 53 + pr_debug("ioremap failed"); 54 + retval = -ENOMEM; 55 + goto err2; 56 + } 57 + 58 + ehci = hcd_to_ehci(hcd); 59 + ehci->big_endian_mmio = 1; 60 + ehci->big_endian_desc = 1; 61 + ehci->caps = hcd->regs; 62 + ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); 63 + 64 + /* cache this readonly data; minimize chip reads */ 65 + ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); 66 + 67 + #if defined(CONFIG_440EPX) 68 + /* 69 + * 440EPx Errata USBH_3 70 + * Fix: Enable Break Memory Transfer (BMT) in INSNREG3 71 + */ 72 + out_be32((void *)((ulong)(&ehci->regs->command) + 0x8c), (1 << 0)); 73 + ehci_dbg(ehci, "Break Memory Transfer (BMT) has beed enabled!\n"); 74 + #endif 75 + 76 + retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED); 77 + if (retval == 0) 78 + return retval; 79 + 80 + iounmap(hcd->regs); 81 + err2: 82 + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 83 + err1: 84 + usb_put_hcd(hcd); 85 + return retval; 86 + } 87 + 88 + /* may be called without controller electrically present */ 89 + /* may be called with controller, bus, and devices active */ 90 + 91 + /** 92 + * usb_ehci_hcd_ppc_soc_remove - shutdown processing for PPC-SoC-based HCDs 93 + * @dev: USB Host Controller being removed 94 + * Context: !in_interrupt() 95 + * 96 + * Reverses the effect of usb_ehci_hcd_ppc_soc_probe(), first invoking 97 + * the HCD's stop() method. It is always called from a thread 98 + * context, normally "rmmod", "apmd", or something similar. 99 + * 100 + */ 101 + void usb_ehci_ppc_soc_remove(struct usb_hcd *hcd, struct platform_device *dev) 102 + { 103 + usb_remove_hcd(hcd); 104 + iounmap(hcd->regs); 105 + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 106 + usb_put_hcd(hcd); 107 + } 108 + 109 + static const struct hc_driver ehci_ppc_soc_hc_driver = { 110 + .description = hcd_name, 111 + .product_desc = "PPC-SOC EHCI", 112 + .hcd_priv_size = sizeof(struct ehci_hcd), 113 + 114 + /* 115 + * generic hardware linkage 116 + */ 117 + .irq = ehci_irq, 118 + .flags = HCD_MEMORY | HCD_USB2, 119 + 120 + /* 121 + * basic lifecycle operations 122 + */ 123 + .reset = ehci_init, 124 + .start = ehci_run, 125 + .stop = ehci_stop, 126 + .shutdown = ehci_shutdown, 127 + 128 + /* 129 + * managing i/o requests and associated device resources 130 + */ 131 + .urb_enqueue = ehci_urb_enqueue, 132 + .urb_dequeue = ehci_urb_dequeue, 133 + .endpoint_disable = ehci_endpoint_disable, 134 + 135 + /* 136 + * scheduling support 137 + */ 138 + .get_frame_number = ehci_get_frame, 139 + 140 + /* 141 + * root hub support 142 + */ 143 + .hub_status_data = ehci_hub_status_data, 144 + .hub_control = ehci_hub_control, 145 + #ifdef CONFIG_PM 146 + .hub_suspend = ehci_hub_suspend, 147 + .hub_resume = ehci_hub_resume, 148 + #endif 149 + }; 150 + 151 + static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) 152 + { 153 + struct usb_hcd *hcd = NULL; 154 + int ret; 155 + 156 + pr_debug("In ehci_hcd_ppc_soc_drv_probe\n"); 157 + 158 + if (usb_disabled()) 159 + return -ENODEV; 160 + 161 + ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev); 162 + return ret; 163 + } 164 + 165 + static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) 166 + { 167 + struct usb_hcd *hcd = platform_get_drvdata(pdev); 168 + 169 + usb_ehci_ppc_soc_remove(hcd, pdev); 170 + return 0; 171 + } 172 + 173 + MODULE_ALIAS("ppc-soc-ehci"); 174 + static struct platform_driver ehci_ppc_soc_driver = { 175 + .probe = ehci_hcd_ppc_soc_drv_probe, 176 + .remove = ehci_hcd_ppc_soc_drv_remove, 177 + .shutdown = usb_hcd_platform_shutdown, 178 + .driver = { 179 + .name = "ppc-soc-ehci", 180 + .bus = &platform_bus_type 181 + } 182 + };