1 /* 2 * OHCI HCD (Host Controller Driver) for USB. 3 * 4 * TI DA8xx (OMAP-L1x) Bus Glue 5 * 6 * Derived from: ohci-omap.c and ohci-s3c2410.c 7 * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com> 8 * 9 * This file is licensed under the terms of the GNU General Public License 10 * version 2. This program is licensed "as is" without any warranty of any 11 * kind, whether express or implied. 12 */ 13 14 #include <linux/interrupt.h> 15 #include <linux/jiffies.h> 16 #include <linux/platform_device.h> 17 #include <linux/clk.h> 18 19 #include <mach/da8xx.h> 20 #include <linux/platform_data/usb-davinci.h> 21 22 #ifndef CONFIG_ARCH_DAVINCI_DA8XX 23 #error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX." 24 #endif 25 26 #define CFGCHIP2 DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG) 27 28 static struct clk *usb11_clk; 29 static struct clk *usb20_clk; 30 31 /* Over-current indicator change bitmask */ 32 static volatile u16 ocic_mask; 33 34 static void ohci_da8xx_clock(int on) 35 { 36 u32 cfgchip2; 37 38 cfgchip2 = __raw_readl(CFGCHIP2); 39 if (on) { 40 clk_enable(usb11_clk); 41 42 /* 43 * If USB 1.1 reference clock is sourced from USB 2.0 PHY, we 44 * need to enable the USB 2.0 module clocking, start its PHY, 45 * and not allow it to stop the clock during USB 2.0 suspend. 46 */ 47 if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX)) { 48 clk_enable(usb20_clk); 49 50 cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN); 51 cfgchip2 |= CFGCHIP2_PHY_PLLON; 52 __raw_writel(cfgchip2, CFGCHIP2); 53 54 pr_info("Waiting for USB PHY clock good...\n"); 55 while (!(__raw_readl(CFGCHIP2) & CFGCHIP2_PHYCLKGD)) 56 cpu_relax(); 57 } 58 59 /* Enable USB 1.1 PHY */ 60 cfgchip2 |= CFGCHIP2_USB1SUSPENDM; 61 } else { 62 clk_disable(usb11_clk); 63 if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX)) 64 clk_disable(usb20_clk); 65 66 /* Disable USB 1.1 PHY */ 67 cfgchip2 &= ~CFGCHIP2_USB1SUSPENDM; 68 } 69 __raw_writel(cfgchip2, CFGCHIP2); 70 } 71 72 /* 73 * Handle the port over-current indicator change. 74 */ 75 static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub, 76 unsigned port) 77 { 78 ocic_mask |= 1 << port; 79 80 /* Once over-current is detected, the port needs to be powered down */ 81 if (hub->get_oci(port) > 0) 82 hub->set_power(port, 0); 83 } 84 85 static int ohci_da8xx_init(struct usb_hcd *hcd) 86 { 87 struct device *dev = hcd->self.controller; 88 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); 89 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 90 int result; 91 u32 rh_a; 92 93 dev_dbg(dev, "starting USB controller\n"); 94 95 ohci_da8xx_clock(1); 96 97 /* 98 * DA8xx only have 1 port connected to the pins but the HC root hub 99 * register A reports 2 ports, thus we'll have to override it... 100 */ 101 ohci->num_ports = 1; 102 103 result = ohci_init(ohci); 104 if (result < 0) 105 return result; 106 107 /* 108 * Since we're providing a board-specific root hub port power control 109 * and over-current reporting, we have to override the HC root hub A 110 * register's default value, so that ohci_hub_control() could return 111 * the correct hub descriptor... 112 */ 113 rh_a = ohci_readl(ohci, &ohci->regs->roothub.a); 114 if (hub->set_power) { 115 rh_a &= ~RH_A_NPS; 116 rh_a |= RH_A_PSM; 117 } 118 if (hub->get_oci) { 119 rh_a &= ~RH_A_NOCP; 120 rh_a |= RH_A_OCPM; 121 } 122 rh_a &= ~RH_A_POTPGT; 123 rh_a |= hub->potpgt << 24; 124 ohci_writel(ohci, rh_a, &ohci->regs->roothub.a); 125 126 return result; 127 } 128 129 static void ohci_da8xx_stop(struct usb_hcd *hcd) 130 { 131 ohci_stop(hcd); 132 ohci_da8xx_clock(0); 133 } 134 135 static int ohci_da8xx_start(struct usb_hcd *hcd) 136 { 137 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 138 int result; 139 140 result = ohci_run(ohci); 141 if (result < 0) 142 ohci_da8xx_stop(hcd); 143 144 return result; 145 } 146 147 /* 148 * Update the status data from the hub with the over-current indicator change. 149 */ 150 static int ohci_da8xx_hub_status_data(struct usb_hcd *hcd, char *buf) 151 { 152 int length = ohci_hub_status_data(hcd, buf); 153 154 /* See if we have OCIC bit set on port 1 */ 155 if (ocic_mask & (1 << 1)) { 156 dev_dbg(hcd->self.controller, "over-current indicator change " 157 "on port 1\n"); 158 159 if (!length) 160 length = 1; 161 162 buf[0] |= 1 << 1; 163 } 164 return length; 165 } 166 167 /* 168 * Look at the control requests to the root hub and see if we need to override. 169 */ 170 static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, 171 u16 wIndex, char *buf, u16 wLength) 172 { 173 struct device *dev = hcd->self.controller; 174 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); 175 int temp; 176 177 switch (typeReq) { 178 case GetPortStatus: 179 /* Check the port number */ 180 if (wIndex != 1) 181 break; 182 183 dev_dbg(dev, "GetPortStatus(%u)\n", wIndex); 184 185 temp = roothub_portstatus(hcd_to_ohci(hcd), wIndex - 1); 186 187 /* The port power status (PPS) bit defaults to 1 */ 188 if (hub->get_power && hub->get_power(wIndex) == 0) 189 temp &= ~RH_PS_PPS; 190 191 /* The port over-current indicator (POCI) bit is always 0 */ 192 if (hub->get_oci && hub->get_oci(wIndex) > 0) 193 temp |= RH_PS_POCI; 194 195 /* The over-current indicator change (OCIC) bit is 0 too */ 196 if (ocic_mask & (1 << wIndex)) 197 temp |= RH_PS_OCIC; 198 199 put_unaligned(cpu_to_le32(temp), (__le32 *)buf); 200 return 0; 201 case SetPortFeature: 202 temp = 1; 203 goto check_port; 204 case ClearPortFeature: 205 temp = 0; 206 207 check_port: 208 /* Check the port number */ 209 if (wIndex != 1) 210 break; 211 212 switch (wValue) { 213 case USB_PORT_FEAT_POWER: 214 dev_dbg(dev, "%sPortFeature(%u): %s\n", 215 temp ? "Set" : "Clear", wIndex, "POWER"); 216 217 if (!hub->set_power) 218 return -EPIPE; 219 220 return hub->set_power(wIndex, temp) ? -EPIPE : 0; 221 case USB_PORT_FEAT_C_OVER_CURRENT: 222 dev_dbg(dev, "%sPortFeature(%u): %s\n", 223 temp ? "Set" : "Clear", wIndex, 224 "C_OVER_CURRENT"); 225 226 if (temp) 227 ocic_mask |= 1 << wIndex; 228 else 229 ocic_mask &= ~(1 << wIndex); 230 return 0; 231 } 232 } 233 234 return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); 235 } 236 237 static const struct hc_driver ohci_da8xx_hc_driver = { 238 .description = hcd_name, 239 .product_desc = "DA8xx OHCI", 240 .hcd_priv_size = sizeof(struct ohci_hcd), 241 242 /* 243 * generic hardware linkage 244 */ 245 .irq = ohci_irq, 246 .flags = HCD_USB11 | HCD_MEMORY, 247 248 /* 249 * basic lifecycle operations 250 */ 251 .reset = ohci_da8xx_init, 252 .start = ohci_da8xx_start, 253 .stop = ohci_da8xx_stop, 254 .shutdown = ohci_shutdown, 255 256 /* 257 * managing i/o requests and associated device resources 258 */ 259 .urb_enqueue = ohci_urb_enqueue, 260 .urb_dequeue = ohci_urb_dequeue, 261 .endpoint_disable = ohci_endpoint_disable, 262 263 /* 264 * scheduling support 265 */ 266 .get_frame_number = ohci_get_frame, 267 268 /* 269 * root hub support 270 */ 271 .hub_status_data = ohci_da8xx_hub_status_data, 272 .hub_control = ohci_da8xx_hub_control, 273 274 #ifdef CONFIG_PM 275 .bus_suspend = ohci_bus_suspend, 276 .bus_resume = ohci_bus_resume, 277 #endif 278 .start_port_reset = ohci_start_port_reset, 279 }; 280 281 /*-------------------------------------------------------------------------*/ 282 283 284 /** 285 * usb_hcd_da8xx_probe - initialize DA8xx-based HCDs 286 * Context: !in_interrupt() 287 * 288 * Allocates basic resources for this USB host controller, and 289 * then invokes the start() method for the HCD associated with it 290 * through the hotplug entry's driver_data. 291 */ 292 static int usb_hcd_da8xx_probe(const struct hc_driver *driver, 293 struct platform_device *pdev) 294 { 295 struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev); 296 struct usb_hcd *hcd; 297 struct resource *mem; 298 int error, irq; 299 300 if (hub == NULL) 301 return -ENODEV; 302 303 usb11_clk = clk_get(&pdev->dev, "usb11"); 304 if (IS_ERR(usb11_clk)) 305 return PTR_ERR(usb11_clk); 306 307 usb20_clk = clk_get(&pdev->dev, "usb20"); 308 if (IS_ERR(usb20_clk)) { 309 error = PTR_ERR(usb20_clk); 310 goto err0; 311 } 312 313 hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); 314 if (!hcd) { 315 error = -ENOMEM; 316 goto err1; 317 } 318 319 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 320 if (!mem) { 321 error = -ENODEV; 322 goto err2; 323 } 324 hcd->rsrc_start = mem->start; 325 hcd->rsrc_len = resource_size(mem); 326 327 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 328 dev_dbg(&pdev->dev, "request_mem_region failed\n"); 329 error = -EBUSY; 330 goto err2; 331 } 332 333 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); 334 if (!hcd->regs) { 335 dev_err(&pdev->dev, "ioremap failed\n"); 336 error = -ENOMEM; 337 goto err3; 338 } 339 340 ohci_hcd_init(hcd_to_ohci(hcd)); 341 342 irq = platform_get_irq(pdev, 0); 343 if (irq < 0) { 344 error = -ENODEV; 345 goto err4; 346 } 347 error = usb_add_hcd(hcd, irq, 0); 348 if (error) 349 goto err4; 350 351 if (hub->ocic_notify) { 352 error = hub->ocic_notify(ohci_da8xx_ocic_handler); 353 if (!error) 354 return 0; 355 } 356 357 usb_remove_hcd(hcd); 358 err4: 359 iounmap(hcd->regs); 360 err3: 361 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 362 err2: 363 usb_put_hcd(hcd); 364 err1: 365 clk_put(usb20_clk); 366 err0: 367 clk_put(usb11_clk); 368 return error; 369 } 370 371 /** 372 * usb_hcd_da8xx_remove - shutdown processing for DA8xx-based HCDs 373 * @dev: USB Host Controller being removed 374 * Context: !in_interrupt() 375 * 376 * Reverses the effect of usb_hcd_da8xx_probe(), first invoking 377 * the HCD's stop() method. It is always called from a thread 378 * context, normally "rmmod", "apmd", or something similar. 379 */ 380 static inline void 381 usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev) 382 { 383 struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev); 384 385 hub->ocic_notify(NULL); 386 usb_remove_hcd(hcd); 387 iounmap(hcd->regs); 388 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 389 usb_put_hcd(hcd); 390 clk_put(usb20_clk); 391 clk_put(usb11_clk); 392 } 393 394 static int ohci_hcd_da8xx_drv_probe(struct platform_device *dev) 395 { 396 return usb_hcd_da8xx_probe(&ohci_da8xx_hc_driver, dev); 397 } 398 399 static int ohci_hcd_da8xx_drv_remove(struct platform_device *dev) 400 { 401 struct usb_hcd *hcd = platform_get_drvdata(dev); 402 403 usb_hcd_da8xx_remove(hcd, dev); 404 405 return 0; 406 } 407 408 #ifdef CONFIG_PM 409 static int ohci_da8xx_suspend(struct platform_device *dev, pm_message_t message) 410 { 411 struct usb_hcd *hcd = platform_get_drvdata(dev); 412 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 413 414 if (time_before(jiffies, ohci->next_statechange)) 415 msleep(5); 416 ohci->next_statechange = jiffies; 417 418 ohci_da8xx_clock(0); 419 hcd->state = HC_STATE_SUSPENDED; 420 dev->dev.power.power_state = PMSG_SUSPEND; 421 return 0; 422 } 423 424 static int ohci_da8xx_resume(struct platform_device *dev) 425 { 426 struct usb_hcd *hcd = platform_get_drvdata(dev); 427 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 428 429 if (time_before(jiffies, ohci->next_statechange)) 430 msleep(5); 431 ohci->next_statechange = jiffies; 432 433 ohci_da8xx_clock(1); 434 dev->dev.power.power_state = PMSG_ON; 435 usb_hcd_resume_root_hub(hcd); 436 return 0; 437 } 438 #endif 439 440 /* 441 * Driver definition to register with platform structure. 442 */ 443 static struct platform_driver ohci_hcd_da8xx_driver = { 444 .probe = ohci_hcd_da8xx_drv_probe, 445 .remove = ohci_hcd_da8xx_drv_remove, 446 .shutdown = usb_hcd_platform_shutdown, 447 #ifdef CONFIG_PM 448 .suspend = ohci_da8xx_suspend, 449 .resume = ohci_da8xx_resume, 450 #endif 451 .driver = { 452 .owner = THIS_MODULE, 453 .name = "ohci", 454 }, 455 }; 456 457 MODULE_ALIAS("platform:ohci"); 458