aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-tegra.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-tegra.c')
-rw-r--r--drivers/usb/host/ehci-tegra.c69
1 files changed, 26 insertions, 43 deletions
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 87e271b9c157..4a44bf833611 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -147,18 +147,7 @@ static int tegra_ehci_hub_control(
147 147
148 spin_lock_irqsave(&ehci->lock, flags); 148 spin_lock_irqsave(&ehci->lock, flags);
149 149
150 /* 150 if (typeReq == GetPortStatus) {
151 * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits
152 * that are write on clear, by writing back the register read value, so
153 * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits
154 */
155 if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) {
156 temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS;
157 ehci_writel(ehci, temp & ~PORT_PE, status_reg);
158 goto done;
159 }
160
161 else if (typeReq == GetPortStatus) {
162 temp = ehci_readl(ehci, status_reg); 151 temp = ehci_readl(ehci, status_reg);
163 if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { 152 if (tegra->port_resuming && !(temp & PORT_SUSPEND)) {
164 /* Resume completed, re-enable disconnect detection */ 153 /* Resume completed, re-enable disconnect detection */
@@ -174,7 +163,7 @@ static int tegra_ehci_hub_control(
174 goto done; 163 goto done;
175 } 164 }
176 165
177 temp &= ~PORT_WKCONN_E; 166 temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E);
178 temp |= PORT_WKDISC_E | PORT_WKOC_E; 167 temp |= PORT_WKDISC_E | PORT_WKOC_E;
179 ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); 168 ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
180 169
@@ -319,26 +308,23 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
319 return retval; 308 return retval;
320} 309}
321 310
322struct temp_buffer { 311struct dma_aligned_buffer {
323 void *kmalloc_ptr; 312 void *kmalloc_ptr;
324 void *old_xfer_buffer; 313 void *old_xfer_buffer;
325 u8 data[0]; 314 u8 data[0];
326}; 315};
327 316
328static void free_temp_buffer(struct urb *urb) 317static void free_dma_aligned_buffer(struct urb *urb)
329{ 318{
330 enum dma_data_direction dir; 319 struct dma_aligned_buffer *temp;
331 struct temp_buffer *temp;
332 320
333 if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) 321 if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
334 return; 322 return;
335 323
336 dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; 324 temp = container_of(urb->transfer_buffer,
337 325 struct dma_aligned_buffer, data);
338 temp = container_of(urb->transfer_buffer, struct temp_buffer,
339 data);
340 326
341 if (dir == DMA_FROM_DEVICE) 327 if (usb_urb_dir_in(urb))
342 memcpy(temp->old_xfer_buffer, temp->data, 328 memcpy(temp->old_xfer_buffer, temp->data,
343 urb->transfer_buffer_length); 329 urb->transfer_buffer_length);
344 urb->transfer_buffer = temp->old_xfer_buffer; 330 urb->transfer_buffer = temp->old_xfer_buffer;
@@ -347,10 +333,9 @@ static void free_temp_buffer(struct urb *urb)
347 urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; 333 urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
348} 334}
349 335
350static int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags) 336static int alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
351{ 337{
352 enum dma_data_direction dir; 338 struct dma_aligned_buffer *temp, *kmalloc_ptr;
353 struct temp_buffer *temp, *kmalloc_ptr;
354 size_t kmalloc_size; 339 size_t kmalloc_size;
355 340
356 if (urb->num_sgs || urb->sg || 341 if (urb->num_sgs || urb->sg ||
@@ -358,22 +343,19 @@ static int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
358 !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1))) 343 !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1)))
359 return 0; 344 return 0;
360 345
361 dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
362
363 /* Allocate a buffer with enough padding for alignment */ 346 /* Allocate a buffer with enough padding for alignment */
364 kmalloc_size = urb->transfer_buffer_length + 347 kmalloc_size = urb->transfer_buffer_length +
365 sizeof(struct temp_buffer) + TEGRA_USB_DMA_ALIGN - 1; 348 sizeof(struct dma_aligned_buffer) + TEGRA_USB_DMA_ALIGN - 1;
366 349
367 kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); 350 kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
368 if (!kmalloc_ptr) 351 if (!kmalloc_ptr)
369 return -ENOMEM; 352 return -ENOMEM;
370 353
371 /* Position our struct temp_buffer such that data is aligned */ 354 /* Position our struct dma_aligned_buffer such that data is aligned */
372 temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1; 355 temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1;
373
374 temp->kmalloc_ptr = kmalloc_ptr; 356 temp->kmalloc_ptr = kmalloc_ptr;
375 temp->old_xfer_buffer = urb->transfer_buffer; 357 temp->old_xfer_buffer = urb->transfer_buffer;
376 if (dir == DMA_TO_DEVICE) 358 if (usb_urb_dir_out(urb))
377 memcpy(temp->data, urb->transfer_buffer, 359 memcpy(temp->data, urb->transfer_buffer,
378 urb->transfer_buffer_length); 360 urb->transfer_buffer_length);
379 urb->transfer_buffer = temp->data; 361 urb->transfer_buffer = temp->data;
@@ -388,13 +370,13 @@ static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
388{ 370{
389 int ret; 371 int ret;
390 372
391 ret = alloc_temp_buffer(urb, mem_flags); 373 ret = alloc_dma_aligned_buffer(urb, mem_flags);
392 if (ret) 374 if (ret)
393 return ret; 375 return ret;
394 376
395 ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); 377 ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
396 if (ret) 378 if (ret)
397 free_temp_buffer(urb); 379 free_dma_aligned_buffer(urb);
398 380
399 return ret; 381 return ret;
400} 382}
@@ -402,38 +384,39 @@ static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
402static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) 384static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
403{ 385{
404 usb_hcd_unmap_urb_for_dma(hcd, urb); 386 usb_hcd_unmap_urb_for_dma(hcd, urb);
405 free_temp_buffer(urb); 387 free_dma_aligned_buffer(urb);
406} 388}
407 389
408static const struct hc_driver tegra_ehci_hc_driver = { 390static const struct hc_driver tegra_ehci_hc_driver = {
409 .description = hcd_name, 391 .description = hcd_name,
410 .product_desc = "Tegra EHCI Host Controller", 392 .product_desc = "Tegra EHCI Host Controller",
411 .hcd_priv_size = sizeof(struct ehci_hcd), 393 .hcd_priv_size = sizeof(struct ehci_hcd),
412
413 .flags = HCD_USB2 | HCD_MEMORY, 394 .flags = HCD_USB2 | HCD_MEMORY,
414 395
415 .reset = tegra_ehci_setup, 396 /* standard ehci functions */
416 .irq = ehci_irq, 397 .irq = ehci_irq,
417
418 .start = ehci_run, 398 .start = ehci_run,
419 .stop = ehci_stop, 399 .stop = ehci_stop,
420 .shutdown = tegra_ehci_shutdown,
421 .urb_enqueue = ehci_urb_enqueue, 400 .urb_enqueue = ehci_urb_enqueue,
422 .urb_dequeue = ehci_urb_dequeue, 401 .urb_dequeue = ehci_urb_dequeue,
423 .map_urb_for_dma = tegra_ehci_map_urb_for_dma,
424 .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma,
425 .endpoint_disable = ehci_endpoint_disable, 402 .endpoint_disable = ehci_endpoint_disable,
426 .endpoint_reset = ehci_endpoint_reset, 403 .endpoint_reset = ehci_endpoint_reset,
427 .get_frame_number = ehci_get_frame, 404 .get_frame_number = ehci_get_frame,
428 .hub_status_data = ehci_hub_status_data, 405 .hub_status_data = ehci_hub_status_data,
429 .hub_control = tegra_ehci_hub_control,
430 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 406 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
407 .relinquish_port = ehci_relinquish_port,
408 .port_handed_over = ehci_port_handed_over,
409
410 /* modified ehci functions for tegra */
411 .reset = tegra_ehci_setup,
412 .shutdown = tegra_ehci_shutdown,
413 .map_urb_for_dma = tegra_ehci_map_urb_for_dma,
414 .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma,
415 .hub_control = tegra_ehci_hub_control,
431#ifdef CONFIG_PM 416#ifdef CONFIG_PM
432 .bus_suspend = ehci_bus_suspend, 417 .bus_suspend = ehci_bus_suspend,
433 .bus_resume = ehci_bus_resume, 418 .bus_resume = ehci_bus_resume,
434#endif 419#endif
435 .relinquish_port = ehci_relinquish_port,
436 .port_handed_over = ehci_port_handed_over,
437}; 420};
438 421
439static int setup_vbus_gpio(struct platform_device *pdev, 422static int setup_vbus_gpio(struct platform_device *pdev,