1 /* 2 * OHCI HCD (Host Controller Driver) for USB. 3 * 4 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> 5 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> 6 * (C) Copyright 2002 Hewlett-Packard Company 7 * 8 * Bus Glue for pxa27x 9 * 10 * Written by Christopher Hoover <ch@hpl.hp.com> 11 * Based on fragments of previous driver by Russell King et al. 12 * 13 * Modified for LH7A404 from ohci-sa1111.c 14 * by Durgesh Pattamatta <pattamattad@sharpsec.com> 15 * 16 * Modified for pxa27x from ohci-lh7a404.c 17 * by Nick Bane <nick@cecomputing.co.uk> 26-8-2004 18 * 19 * This file is licenced under the GPL. 20 */ 21 22 #include <linux/device.h> 23 #include <linux/signal.h> 24 #include <linux/platform_device.h> 25 26 #include <asm/mach-types.h> 27 #include <asm/hardware.h> 28 #include <asm/arch/pxa-regs.h> 29 30 31 #define PMM_NPS_MODE 1 32 #define PMM_GLOBAL_MODE 2 33 #define PMM_PERPORT_MODE 3 34 35 #define PXA_UHC_MAX_PORTNUM 3 36 37 #define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 ) 38 39 static int pxa27x_ohci_pmm_state; 40 41 /* 42 PMM_NPS_MODE -- PMM Non-power switching mode 43 Ports are powered continuously. 44 45 PMM_GLOBAL_MODE -- PMM global switching mode 46 All ports are powered at the same time. 47 48 PMM_PERPORT_MODE -- PMM per port switching mode 49 Ports are powered individually. 50 */ 51 static int pxa27x_ohci_select_pmm( int mode ) 52 { 53 pxa27x_ohci_pmm_state = mode; 54 55 switch ( mode ) { 56 case PMM_NPS_MODE: 57 UHCRHDA |= RH_A_NPS; 58 break; 59 case PMM_GLOBAL_MODE: 60 UHCRHDA &= ~(RH_A_NPS & RH_A_PSM); 61 break; 62 case PMM_PERPORT_MODE: 63 UHCRHDA &= ~(RH_A_NPS); 64 UHCRHDA |= RH_A_PSM; 65 66 /* Set port power control mask bits, only 3 ports. */ 67 UHCRHDB |= (0x7<<17); 68 break; 69 default: 70 printk( KERN_ERR 71 "Invalid mode %d, set to non-power switch mode.\n", 72 mode ); 73 74 pxa27x_ohci_pmm_state = PMM_NPS_MODE; 75 UHCRHDA |= RH_A_NPS; 76 } 77 78 return 0; 79 } 80 81 extern int usb_disabled(void); 82 83 /*-------------------------------------------------------------------------*/ 84 85 static void pxa27x_start_hc(struct platform_device *dev) 86 { 87 pxa_set_cken(CKEN10_USBHOST, 1); 88 89 UHCHR |= UHCHR_FHR; 90 udelay(11); 91 UHCHR &= ~UHCHR_FHR; 92 93 UHCHR |= UHCHR_FSBIR; 94 while (UHCHR & UHCHR_FSBIR) 95 cpu_relax(); 96 97 /* This could be properly abstracted away through the 98 device data the day more machines are supported and 99 their differences can be figured out correctly. */ 100 if (machine_is_mainstone()) { 101 /* setup Port1 GPIO pin. */ 102 pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */ 103 pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */ 104 105 /* Set the Power Control Polarity Low and Power Sense 106 Polarity Low to active low. Supply power to USB ports. */ 107 UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & 108 ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); 109 110 pxa27x_ohci_pmm_state = PMM_PERPORT_MODE; 111 } 112 113 UHCHR &= ~UHCHR_SSE; 114 115 UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE); 116 117 /* Clear any OTG Pin Hold */ 118 if (PSSR & PSSR_OTGPH) 119 PSSR |= PSSR_OTGPH; 120 } 121 122 static void pxa27x_stop_hc(struct platform_device *dev) 123 { 124 UHCHR |= UHCHR_FHR; 125 udelay(11); 126 UHCHR &= ~UHCHR_FHR; 127 128 UHCCOMS |= 1; 129 udelay(10); 130 131 pxa_set_cken(CKEN10_USBHOST, 0); 132 } 133 134 135 /*-------------------------------------------------------------------------*/ 136 137 /* configure so an HC device and id are always provided */ 138 /* always called with process context; sleeping is OK */ 139 140 141 /** 142 * usb_hcd_pxa27x_probe - initialize pxa27x-based HCDs 143 * Context: !in_interrupt() 144 * 145 * Allocates basic resources for this USB host controller, and 146 * then invokes the start() method for the HCD associated with it 147 * through the hotplug entry's driver_data. 148 * 149 */ 150 int usb_hcd_pxa27x_probe (const struct hc_driver *driver, 151 struct platform_device *dev) 152 { 153 int retval; 154 struct usb_hcd *hcd; 155 156 if (dev->resource[1].flags != IORESOURCE_IRQ) { 157 pr_debug ("resource[1] is not IORESOURCE_IRQ"); 158 return -ENOMEM; 159 } 160 161 hcd = usb_create_hcd (driver, &dev->dev, "pxa27x"); 162 if (!hcd) 163 return -ENOMEM; 164 hcd->rsrc_start = dev->resource[0].start; 165 hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; 166 167 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 168 pr_debug("request_mem_region failed"); 169 retval = -EBUSY; 170 goto err1; 171 } 172 173 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); 174 if (!hcd->regs) { 175 pr_debug("ioremap failed"); 176 retval = -ENOMEM; 177 goto err2; 178 } 179 180 pxa27x_start_hc(dev); 181 182 /* Select Power Management Mode */ 183 pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state); 184 185 ohci_hcd_init(hcd_to_ohci(hcd)); 186 187 retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); 188 if (retval == 0) 189 return retval; 190 191 pxa27x_stop_hc(dev); 192 iounmap(hcd->regs); 193 err2: 194 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 195 err1: 196 usb_put_hcd(hcd); 197 return retval; 198 } 199 200 201 /* may be called without controller electrically present */ 202 /* may be called with controller, bus, and devices active */ 203 204 /** 205 * usb_hcd_pxa27x_remove - shutdown processing for pxa27x-based HCDs 206 * @dev: USB Host Controller being removed 207 * Context: !in_interrupt() 208 * 209 * Reverses the effect of usb_hcd_pxa27x_probe(), first invoking 210 * the HCD's stop() method. It is always called from a thread 211 * context, normally "rmmod", "apmd", or something similar. 212 * 213 */ 214 void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev) 215 { 216 usb_remove_hcd(hcd); 217 pxa27x_stop_hc(dev); 218 iounmap(hcd->regs); 219 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 220 usb_put_hcd(hcd); 221 } 222 223 /*-------------------------------------------------------------------------*/ 224 225 static int __devinit 226 ohci_pxa27x_start (struct usb_hcd *hcd) 227 { 228 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 229 int ret; 230 231 ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci); 232 233 /* The value of NDP in roothub_a is incorrect on this hardware */ 234 ohci->num_ports = 3; 235 236 if ((ret = ohci_init(ohci)) < 0) 237 return ret; 238 239 if ((ret = ohci_run (ohci)) < 0) { 240 err ("can't start %s", hcd->self.bus_name); 241 ohci_stop (hcd); 242 return ret; 243 } 244 245 return 0; 246 } 247 248 /*-------------------------------------------------------------------------*/ 249 250 static const struct hc_driver ohci_pxa27x_hc_driver = { 251 .description = hcd_name, 252 .product_desc = "PXA27x OHCI", 253 .hcd_priv_size = sizeof(struct ohci_hcd), 254 255 /* 256 * generic hardware linkage 257 */ 258 .irq = ohci_irq, 259 .flags = HCD_USB11 | HCD_MEMORY, 260 261 /* 262 * basic lifecycle operations 263 */ 264 .start = ohci_pxa27x_start, 265 .stop = ohci_stop, 266 267 /* 268 * managing i/o requests and associated device resources 269 */ 270 .urb_enqueue = ohci_urb_enqueue, 271 .urb_dequeue = ohci_urb_dequeue, 272 .endpoint_disable = ohci_endpoint_disable, 273 274 /* 275 * scheduling support 276 */ 277 .get_frame_number = ohci_get_frame, 278 279 /* 280 * root hub support 281 */ 282 .hub_status_data = ohci_hub_status_data, 283 .hub_control = ohci_hub_control, 284 #ifdef CONFIG_PM 285 .bus_suspend = ohci_bus_suspend, 286 .bus_resume = ohci_bus_resume, 287 #endif 288 .start_port_reset = ohci_start_port_reset, 289 }; 290 291 /*-------------------------------------------------------------------------*/ 292 293 static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev) 294 { 295 int ret; 296 297 pr_debug ("In ohci_hcd_pxa27x_drv_probe"); 298 299 if (usb_disabled()) 300 return -ENODEV; 301 302 ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev); 303 return ret; 304 } 305 306 static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev) 307 { 308 struct usb_hcd *hcd = platform_get_drvdata(pdev); 309 310 usb_hcd_pxa27x_remove(hcd, pdev); 311 return 0; 312 } 313 314 static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *dev, pm_message_t state) 315 { 316 // struct usb_hcd *hcd = platform_get_drvdata(dev); 317 printk("%s: not implemented yet\n", __FUNCTION__); 318 319 return 0; 320 } 321 322 static int ohci_hcd_pxa27x_drv_resume(struct platform_device *dev) 323 { 324 // struct usb_hcd *hcd = platform_get_drvdata(dev); 325 printk("%s: not implemented yet\n", __FUNCTION__); 326 327 return 0; 328 } 329 330 331 static struct platform_driver ohci_hcd_pxa27x_driver = { 332 .probe = ohci_hcd_pxa27x_drv_probe, 333 .remove = ohci_hcd_pxa27x_drv_remove, 334 .suspend = ohci_hcd_pxa27x_drv_suspend, 335 .resume = ohci_hcd_pxa27x_drv_resume, 336 .driver = { 337 .name = "pxa27x-ohci", 338 }, 339 }; 340 341 static int __init ohci_hcd_pxa27x_init (void) 342 { 343 pr_debug (DRIVER_INFO " (pxa27x)"); 344 pr_debug ("block sizes: ed %d td %d\n", 345 sizeof (struct ed), sizeof (struct td)); 346 347 return platform_driver_register(&ohci_hcd_pxa27x_driver); 348 } 349 350 static void __exit ohci_hcd_pxa27x_cleanup (void) 351 { 352 platform_driver_unregister(&ohci_hcd_pxa27x_driver); 353 } 354 355 module_init (ohci_hcd_pxa27x_init); 356 module_exit (ohci_hcd_pxa27x_cleanup); 357