aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/r8a66597-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/r8a66597-hcd.c')
-rw-r--r--drivers/usb/host/r8a66597-hcd.c77
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");
46MODULE_AUTHOR("Yoshihiro Shimoda"); 46MODULE_AUTHOR("Yoshihiro Shimoda");
47MODULE_ALIAS("platform:r8a66597_hcd"); 47MODULE_ALIAS("platform:r8a66597_hcd");
48 48
49#define DRIVER_VERSION "29 May 2007" 49#define DRIVER_VERSION "10 Apr 2008"
50 50
51static const char hcd_name[] = "r8a66597_hcd"; 51static 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 */
588static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td) 584static 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
824static 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 */
829static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, 844static 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
1609static 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
1585static void r8a66597_td_timer(unsigned long _r8a66597) 1632static 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