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 = devm_clk_get(&pdev->dev, "usb11"); 304 if (IS_ERR(usb11_clk)) 305 return PTR_ERR(usb11_clk); 306 307 usb20_clk = devm_clk_get(&pdev->dev, "usb20"); 308 if (IS_ERR(usb20_clk)) 309 return PTR_ERR(usb20_clk); 310 311 hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); 312 if (!hcd) 313 return -ENOMEM; 314 315 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 316 hcd->regs = devm_ioremap_resource(&pdev->dev, mem); 317 if (IS_ERR(hcd->regs)) { 318 error = PTR_ERR(hcd->regs); 319 goto err; 320 } 321 hcd->rsrc_start = mem->start; 322 hcd->rsrc_len = resource_size(mem); 323 324 ohci_hcd_init(hcd_to_ohci(hcd)); 325 326 irq = platform_get_irq(pdev, 0); 327 if (irq < 0) { 328 error = -ENODEV; 329 goto err; 330 } 331 error = usb_add_hcd(hcd, irq, 0); 332 if (error) 333 goto err; 334 335 device_wakeup_enable(hcd->self.controller); 336 337 if (hub->ocic_notify) { 338 error = hub->ocic_notify(ohci_da8xx_ocic_handler); 339 if (!error) 340 return 0; 341 } 342 343 usb_remove_hcd(hcd); 344 err: 345 usb_put_hcd(hcd); 346 return error; 347 } 348 349 /** 350 * usb_hcd_da8xx_remove - shutdown processing for DA8xx-based HCDs 351 * @dev: USB Host Controller being removed 352 * Context: !in_interrupt() 353 * 354 * Reverses the effect of usb_hcd_da8xx_probe(), first invoking 355 * the HCD's stop() method. It is always called from a thread 356 * context, normally "rmmod", "apmd", or something similar. 357 */ 358 static inline void 359 usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev) 360 { 361 struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev); 362 363 hub->ocic_notify(NULL); 364 usb_remove_hcd(hcd); 365 usb_put_hcd(hcd); 366 } 367 368 static int ohci_hcd_da8xx_drv_probe(struct platform_device *dev) 369 { 370 return usb_hcd_da8xx_probe(&ohci_da8xx_hc_driver, dev); 371 } 372 373 static int ohci_hcd_da8xx_drv_remove(struct platform_device *dev) 374 { 375 struct usb_hcd *hcd = platform_get_drvdata(dev); 376 377 usb_hcd_da8xx_remove(hcd, dev); 378 379 return 0; 380 } 381 382 #ifdef CONFIG_PM 383 static int ohci_da8xx_suspend(struct platform_device *pdev, 384 pm_message_t message) 385 { 386 struct usb_hcd *hcd = platform_get_drvdata(pdev); 387 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 388 bool do_wakeup = device_may_wakeup(&pdev->dev); 389 int ret; 390 391 392 if (time_before(jiffies, ohci->next_statechange)) 393 msleep(5); 394 ohci->next_statechange = jiffies; 395 396 ret = ohci_suspend(hcd, do_wakeup); 397 if (ret) 398 return ret; 399 400 ohci_da8xx_clock(0); 401 hcd->state = HC_STATE_SUSPENDED; 402 403 return ret; 404 } 405 406 static int ohci_da8xx_resume(struct platform_device *dev) 407 { 408 struct usb_hcd *hcd = platform_get_drvdata(dev); 409 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 410 411 if (time_before(jiffies, ohci->next_statechange)) 412 msleep(5); 413 ohci->next_statechange = jiffies; 414 415 ohci_da8xx_clock(1); 416 dev->dev.power.power_state = PMSG_ON; 417 usb_hcd_resume_root_hub(hcd); 418 return 0; 419 } 420 #endif 421 422 /* 423 * Driver definition to register with platform structure. 424 */ 425 static struct platform_driver ohci_hcd_da8xx_driver = { 426 .probe = ohci_hcd_da8xx_drv_probe, 427 .remove = ohci_hcd_da8xx_drv_remove, 428 .shutdown = usb_hcd_platform_shutdown, 429 #ifdef CONFIG_PM 430 .suspend = ohci_da8xx_suspend, 431 .resume = ohci_da8xx_resume, 432 #endif 433 .driver = { 434 .owner = THIS_MODULE, 435 .name = "ohci", 436 }, 437 }; 438 439 MODULE_ALIAS("platform:ohci"); 440