diff options
Diffstat (limited to 'drivers/usb/host/r8a66597-hcd.c')
-rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 77 |
1 files changed, 67 insertions, 10 deletions
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index b46ff9a80b66..dac2f7dd69b9 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); | |||
46 | MODULE_AUTHOR("Yoshihiro Shimoda"); | 46 | MODULE_AUTHOR("Yoshihiro Shimoda"); |
47 | MODULE_ALIAS("platform:r8a66597_hcd"); | 47 | MODULE_ALIAS("platform:r8a66597_hcd"); |
48 | 48 | ||
49 | #define DRIVER_VERSION "29 May 2007" | 49 | #define DRIVER_VERSION "10 Apr 2008" |
50 | 50 | ||
51 | static const char hcd_name[] = "r8a66597_hcd"; | 51 | static const char hcd_name[] = "r8a66597_hcd"; |
52 | 52 | ||
@@ -577,13 +577,9 @@ static void pipe_buffer_setting(struct r8a66597 *r8a66597, | |||
577 | PIPEBUF); | 577 | PIPEBUF); |
578 | r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket, | 578 | r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket, |
579 | PIPEMAXP); | 579 | PIPEMAXP); |
580 | if (info->interval) | ||
581 | info->interval--; | ||
582 | r8a66597_write(r8a66597, info->interval, PIPEPERI); | 580 | r8a66597_write(r8a66597, info->interval, PIPEPERI); |
583 | } | 581 | } |
584 | 582 | ||
585 | |||
586 | |||
587 | /* this function must be called with interrupt disabled */ | 583 | /* this function must be called with interrupt disabled */ |
588 | static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td) | 584 | static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td) |
589 | { | 585 | { |
@@ -825,6 +821,25 @@ static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597, | |||
825 | dev->dma_map = 0; | 821 | dev->dma_map = 0; |
826 | } | 822 | } |
827 | 823 | ||
824 | static unsigned long get_timer_interval(struct urb *urb, __u8 interval) | ||
825 | { | ||
826 | __u8 i; | ||
827 | unsigned long time = 1; | ||
828 | |||
829 | if (usb_pipeisoc(urb->pipe)) | ||
830 | return 0; | ||
831 | |||
832 | if (get_r8a66597_usb_speed(urb->dev->speed) == HSMODE) { | ||
833 | for (i = 0; i < (interval - 1); i++) | ||
834 | time *= 2; | ||
835 | time = time * 125 / 1000; /* uSOF -> msec */ | ||
836 | } else { | ||
837 | time = interval; | ||
838 | } | ||
839 | |||
840 | return time; | ||
841 | } | ||
842 | |||
828 | /* this function must be called with interrupt disabled */ | 843 | /* this function must be called with interrupt disabled */ |
829 | static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, | 844 | static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, |
830 | struct usb_host_endpoint *hep, | 845 | struct usb_host_endpoint *hep, |
@@ -840,7 +855,16 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, | |||
840 | & USB_ENDPOINT_XFERTYPE_MASK); | 855 | & USB_ENDPOINT_XFERTYPE_MASK); |
841 | info.bufnum = get_bufnum(info.pipenum); | 856 | info.bufnum = get_bufnum(info.pipenum); |
842 | info.buf_bsize = get_buf_bsize(info.pipenum); | 857 | info.buf_bsize = get_buf_bsize(info.pipenum); |
843 | info.interval = ep->bInterval; | 858 | if (info.type == R8A66597_BULK) { |
859 | info.interval = 0; | ||
860 | info.timer_interval = 0; | ||
861 | } else { | ||
862 | if (ep->bInterval > IITV) | ||
863 | info.interval = IITV; | ||
864 | else | ||
865 | info.interval = ep->bInterval ? ep->bInterval - 1 : 0; | ||
866 | info.timer_interval = get_timer_interval(urb, ep->bInterval); | ||
867 | } | ||
844 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 868 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) |
845 | info.dir_in = 1; | 869 | info.dir_in = 1; |
846 | else | 870 | else |
@@ -1582,6 +1606,29 @@ static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port) | |||
1582 | } | 1606 | } |
1583 | } | 1607 | } |
1584 | 1608 | ||
1609 | static void r8a66597_interval_timer(unsigned long _r8a66597) | ||
1610 | { | ||
1611 | struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; | ||
1612 | unsigned long flags; | ||
1613 | u16 pipenum; | ||
1614 | struct r8a66597_td *td; | ||
1615 | |||
1616 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1617 | |||
1618 | for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | ||
1619 | if (!(r8a66597->interval_map & (1 << pipenum))) | ||
1620 | continue; | ||
1621 | if (timer_pending(&r8a66597->interval_timer[pipenum])) | ||
1622 | continue; | ||
1623 | |||
1624 | td = r8a66597_get_td(r8a66597, pipenum); | ||
1625 | if (td) | ||
1626 | start_transfer(r8a66597, td); | ||
1627 | } | ||
1628 | |||
1629 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1630 | } | ||
1631 | |||
1585 | static void r8a66597_td_timer(unsigned long _r8a66597) | 1632 | static void r8a66597_td_timer(unsigned long _r8a66597) |
1586 | { | 1633 | { |
1587 | struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; | 1634 | struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; |
@@ -1763,10 +1810,17 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd, | |||
1763 | urb->hcpriv = td; | 1810 | urb->hcpriv = td; |
1764 | 1811 | ||
1765 | if (request) { | 1812 | if (request) { |
1766 | ret = start_transfer(r8a66597, td); | 1813 | if (td->pipe->info.timer_interval) { |
1767 | if (ret < 0) { | 1814 | r8a66597->interval_map |= 1 << td->pipenum; |
1768 | list_del(&td->queue); | 1815 | mod_timer(&r8a66597->interval_timer[td->pipenum], |
1769 | kfree(td); | 1816 | jiffies + msecs_to_jiffies( |
1817 | td->pipe->info.timer_interval)); | ||
1818 | } else { | ||
1819 | ret = start_transfer(r8a66597, td); | ||
1820 | if (ret < 0) { | ||
1821 | list_del(&td->queue); | ||
1822 | kfree(td); | ||
1823 | } | ||
1770 | } | 1824 | } |
1771 | } else | 1825 | } else |
1772 | set_td_timer(r8a66597, td); | 1826 | set_td_timer(r8a66597, td); |
@@ -2192,6 +2246,9 @@ static int __init r8a66597_probe(struct platform_device *pdev) | |||
2192 | init_timer(&r8a66597->td_timer[i]); | 2246 | init_timer(&r8a66597->td_timer[i]); |
2193 | r8a66597->td_timer[i].function = r8a66597_td_timer; | 2247 | r8a66597->td_timer[i].function = r8a66597_td_timer; |
2194 | r8a66597->td_timer[i].data = (unsigned long)r8a66597; | 2248 | r8a66597->td_timer[i].data = (unsigned long)r8a66597; |
2249 | setup_timer(&r8a66597->interval_timer[i], | ||
2250 | r8a66597_interval_timer, | ||
2251 | (unsigned long)r8a66597); | ||
2195 | } | 2252 | } |
2196 | INIT_LIST_HEAD(&r8a66597->child_device); | 2253 | INIT_LIST_HEAD(&r8a66597->child_device); |
2197 | 2254 | ||