diff options
Diffstat (limited to 'drivers/usb/host/r8a66597-hcd.c')
| -rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 58 | 
1 files changed, 45 insertions, 13 deletions
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index b7a661c02bc..bee558aed42 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -35,7 +35,9 @@  #include <linux/usb.h>  #include <linux/platform_device.h>  #include <linux/io.h> +#include <linux/mm.h>  #include <linux/irq.h> +#include <asm/cacheflush.h>  #include "../core/hcd.h"  #include "r8a66597.h" @@ -216,8 +218,17 @@ static void disable_controller(struct r8a66597 *r8a66597)  {  	int port; +	/* disable interrupts */  	r8a66597_write(r8a66597, 0, INTENB0); -	r8a66597_write(r8a66597, 0, INTSTS0); +	r8a66597_write(r8a66597, 0, INTENB1); +	r8a66597_write(r8a66597, 0, BRDYENB); +	r8a66597_write(r8a66597, 0, BEMPENB); +	r8a66597_write(r8a66597, 0, NRDYENB); + +	/* clear status */ +	r8a66597_write(r8a66597, 0, BRDYSTS); +	r8a66597_write(r8a66597, 0, NRDYSTS); +	r8a66597_write(r8a66597, 0, BEMPSTS);  	for (port = 0; port < r8a66597->max_root_hub; port++)  		r8a66597_disable_port(r8a66597, port); @@ -811,6 +822,26 @@ static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb,  	enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb);  } +static void r8a66597_urb_done(struct r8a66597 *r8a66597, struct urb *urb, +			      int status) +__releases(r8a66597->lock) +__acquires(r8a66597->lock) +{ +	if (usb_pipein(urb->pipe) && usb_pipetype(urb->pipe) != PIPE_CONTROL) { +		void *ptr; + +		for (ptr = urb->transfer_buffer; +		     ptr < urb->transfer_buffer + urb->transfer_buffer_length; +		     ptr += PAGE_SIZE) +			flush_dcache_page(virt_to_page(ptr)); +	} + +	usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb); +	spin_unlock(&r8a66597->lock); +	usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, status); +	spin_lock(&r8a66597->lock); +} +  /* this function must be called with interrupt disabled */  static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)  { @@ -829,15 +860,9 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)  		list_del(&td->queue);  		kfree(td); -		if (urb) { -			usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), -					urb); +		if (urb) +			r8a66597_urb_done(r8a66597, urb, -ENODEV); -			spin_unlock(&r8a66597->lock); -			usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, -					-ENODEV); -			spin_lock(&r8a66597->lock); -		}  		break;  	}  } @@ -997,6 +1022,8 @@ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port,  /* this function must be called with interrupt disabled */  static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,  					u16 syssts) +__releases(r8a66597->lock) +__acquires(r8a66597->lock)  {  	if (syssts == SE0) {  		r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port)); @@ -1014,7 +1041,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,  			usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));  	} +	spin_unlock(&r8a66597->lock);  	usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597)); +	spin_lock(&r8a66597->lock);  }  /* this function must be called with interrupt disabled */ @@ -1274,10 +1303,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)  		if (usb_pipeisoc(urb->pipe))  			urb->start_frame = r8a66597_get_frame(hcd); -		usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb); -		spin_unlock(&r8a66597->lock); -		usb_hcd_giveback_urb(hcd, urb, status); -		spin_lock(&r8a66597->lock); +		r8a66597_urb_done(r8a66597, urb, status);  	}  	if (restart) { @@ -2466,6 +2492,12 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)  	r8a66597->rh_timer.data = (unsigned long)r8a66597;  	r8a66597->reg = (unsigned long)reg; +	/* make sure no interrupts are pending */ +	ret = r8a66597_clock_enable(r8a66597); +	if (ret < 0) +		goto clean_up3; +	disable_controller(r8a66597); +  	for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) {  		INIT_LIST_HEAD(&r8a66597->pipe_queue[i]);  		init_timer(&r8a66597->td_timer[i]);  |