diff options
Diffstat (limited to 'drivers/usb/host/r8a66597-hcd.c')
-rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 118 |
1 files changed, 108 insertions, 10 deletions
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 319041205b57..f1626e58c141 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -660,9 +660,9 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, | |||
660 | u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min; | 660 | u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min; |
661 | 661 | ||
662 | memset(array, 0, sizeof(array)); | 662 | memset(array, 0, sizeof(array)); |
663 | switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | 663 | switch (usb_endpoint_type(ep)) { |
664 | case USB_ENDPOINT_XFER_BULK: | 664 | case USB_ENDPOINT_XFER_BULK: |
665 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 665 | if (usb_endpoint_dir_in(ep)) |
666 | array[i++] = 4; | 666 | array[i++] = 4; |
667 | else { | 667 | else { |
668 | array[i++] = 3; | 668 | array[i++] = 3; |
@@ -670,7 +670,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, | |||
670 | } | 670 | } |
671 | break; | 671 | break; |
672 | case USB_ENDPOINT_XFER_INT: | 672 | case USB_ENDPOINT_XFER_INT: |
673 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { | 673 | if (usb_endpoint_dir_in(ep)) { |
674 | array[i++] = 6; | 674 | array[i++] = 6; |
675 | array[i++] = 7; | 675 | array[i++] = 7; |
676 | array[i++] = 8; | 676 | array[i++] = 8; |
@@ -678,7 +678,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, | |||
678 | array[i++] = 9; | 678 | array[i++] = 9; |
679 | break; | 679 | break; |
680 | case USB_ENDPOINT_XFER_ISOC: | 680 | case USB_ENDPOINT_XFER_ISOC: |
681 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 681 | if (usb_endpoint_dir_in(ep)) |
682 | array[i++] = 2; | 682 | array[i++] = 2; |
683 | else | 683 | else |
684 | array[i++] = 1; | 684 | array[i++] = 1; |
@@ -928,10 +928,9 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, | |||
928 | 928 | ||
929 | info.pipenum = get_empty_pipenum(r8a66597, ep); | 929 | info.pipenum = get_empty_pipenum(r8a66597, ep); |
930 | info.address = get_urb_to_r8a66597_addr(r8a66597, urb); | 930 | info.address = get_urb_to_r8a66597_addr(r8a66597, urb); |
931 | info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 931 | info.epnum = usb_endpoint_num(ep); |
932 | info.maxpacket = le16_to_cpu(ep->wMaxPacketSize); | 932 | info.maxpacket = le16_to_cpu(ep->wMaxPacketSize); |
933 | info.type = get_r8a66597_type(ep->bmAttributes | 933 | info.type = get_r8a66597_type(usb_endpoint_type(ep)); |
934 | & USB_ENDPOINT_XFERTYPE_MASK); | ||
935 | info.bufnum = get_bufnum(info.pipenum); | 934 | info.bufnum = get_bufnum(info.pipenum); |
936 | info.buf_bsize = get_buf_bsize(info.pipenum); | 935 | info.buf_bsize = get_buf_bsize(info.pipenum); |
937 | if (info.type == R8A66597_BULK) { | 936 | if (info.type == R8A66597_BULK) { |
@@ -941,7 +940,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, | |||
941 | info.interval = get_interval(urb, ep->bInterval); | 940 | info.interval = get_interval(urb, ep->bInterval); |
942 | info.timer_interval = get_timer_interval(urb, ep->bInterval); | 941 | info.timer_interval = get_timer_interval(urb, ep->bInterval); |
943 | } | 942 | } |
944 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 943 | if (usb_endpoint_dir_in(ep)) |
945 | info.dir_in = 1; | 944 | info.dir_in = 1; |
946 | else | 945 | else |
947 | info.dir_in = 0; | 946 | info.dir_in = 0; |
@@ -1014,6 +1013,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, | |||
1014 | 1013 | ||
1015 | r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); | 1014 | r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); |
1016 | r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); | 1015 | r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); |
1016 | |||
1017 | if (r8a66597->bus_suspended) | ||
1018 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); | ||
1017 | } | 1019 | } |
1018 | 1020 | ||
1019 | /* this function must be called with interrupt disabled */ | 1021 | /* this function must be called with interrupt disabled */ |
@@ -1395,7 +1397,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) | |||
1395 | (int)urb->iso_frame_desc[td->iso_cnt].length); | 1397 | (int)urb->iso_frame_desc[td->iso_cnt].length); |
1396 | } else { | 1398 | } else { |
1397 | buf = (u16 *)(urb->transfer_buffer + urb->actual_length); | 1399 | buf = (u16 *)(urb->transfer_buffer + urb->actual_length); |
1398 | size = min((int)bufsize, | 1400 | size = min_t(u32, bufsize, |
1399 | urb->transfer_buffer_length - urb->actual_length); | 1401 | urb->transfer_buffer_length - urb->actual_length); |
1400 | } | 1402 | } |
1401 | 1403 | ||
@@ -1615,6 +1617,11 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) | |||
1615 | r8a66597_bclr(r8a66597, DTCHE, INTENB2); | 1617 | r8a66597_bclr(r8a66597, DTCHE, INTENB2); |
1616 | r8a66597_usb_disconnect(r8a66597, 1); | 1618 | r8a66597_usb_disconnect(r8a66597, 1); |
1617 | } | 1619 | } |
1620 | if (mask2 & BCHG) { | ||
1621 | r8a66597_write(r8a66597, ~BCHG, INTSTS2); | ||
1622 | r8a66597_bclr(r8a66597, BCHGE, INTENB2); | ||
1623 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); | ||
1624 | } | ||
1618 | } | 1625 | } |
1619 | 1626 | ||
1620 | if (mask1) { | 1627 | if (mask1) { |
@@ -1630,6 +1637,12 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) | |||
1630 | r8a66597_bclr(r8a66597, DTCHE, INTENB1); | 1637 | r8a66597_bclr(r8a66597, DTCHE, INTENB1); |
1631 | r8a66597_usb_disconnect(r8a66597, 0); | 1638 | r8a66597_usb_disconnect(r8a66597, 0); |
1632 | } | 1639 | } |
1640 | if (mask1 & BCHG) { | ||
1641 | r8a66597_write(r8a66597, ~BCHG, INTSTS1); | ||
1642 | r8a66597_bclr(r8a66597, BCHGE, INTENB1); | ||
1643 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); | ||
1644 | } | ||
1645 | |||
1633 | if (mask1 & SIGN) { | 1646 | if (mask1 & SIGN) { |
1634 | r8a66597_write(r8a66597, ~SIGN, INTSTS1); | 1647 | r8a66597_write(r8a66597, ~SIGN, INTSTS1); |
1635 | status = get_urb_error(r8a66597, 0); | 1648 | status = get_urb_error(r8a66597, 0); |
@@ -2141,7 +2154,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
2141 | 2154 | ||
2142 | switch (wValue) { | 2155 | switch (wValue) { |
2143 | case USB_PORT_FEAT_ENABLE: | 2156 | case USB_PORT_FEAT_ENABLE: |
2144 | rh->port &= (1 << USB_PORT_FEAT_POWER); | 2157 | rh->port &= ~(1 << USB_PORT_FEAT_POWER); |
2145 | break; | 2158 | break; |
2146 | case USB_PORT_FEAT_SUSPEND: | 2159 | case USB_PORT_FEAT_SUSPEND: |
2147 | break; | 2160 | break; |
@@ -2213,6 +2226,68 @@ error: | |||
2213 | return ret; | 2226 | return ret; |
2214 | } | 2227 | } |
2215 | 2228 | ||
2229 | #if defined(CONFIG_PM) | ||
2230 | static int r8a66597_bus_suspend(struct usb_hcd *hcd) | ||
2231 | { | ||
2232 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
2233 | int port; | ||
2234 | |||
2235 | dbg("%s", __func__); | ||
2236 | |||
2237 | for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { | ||
2238 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | ||
2239 | unsigned long dvstctr_reg = get_dvstctr_reg(port); | ||
2240 | |||
2241 | if (!(rh->port & (1 << USB_PORT_FEAT_ENABLE))) | ||
2242 | continue; | ||
2243 | |||
2244 | dbg("suspend port = %d", port); | ||
2245 | r8a66597_bclr(r8a66597, UACT, dvstctr_reg); /* suspend */ | ||
2246 | rh->port |= 1 << USB_PORT_FEAT_SUSPEND; | ||
2247 | |||
2248 | if (rh->dev->udev->do_remote_wakeup) { | ||
2249 | msleep(3); /* waiting last SOF */ | ||
2250 | r8a66597_bset(r8a66597, RWUPE, dvstctr_reg); | ||
2251 | r8a66597_write(r8a66597, ~BCHG, get_intsts_reg(port)); | ||
2252 | r8a66597_bset(r8a66597, BCHGE, get_intenb_reg(port)); | ||
2253 | } | ||
2254 | } | ||
2255 | |||
2256 | r8a66597->bus_suspended = 1; | ||
2257 | |||
2258 | return 0; | ||
2259 | } | ||
2260 | |||
2261 | static int r8a66597_bus_resume(struct usb_hcd *hcd) | ||
2262 | { | ||
2263 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
2264 | int port; | ||
2265 | |||
2266 | dbg("%s", __func__); | ||
2267 | |||
2268 | for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { | ||
2269 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | ||
2270 | unsigned long dvstctr_reg = get_dvstctr_reg(port); | ||
2271 | |||
2272 | if (!(rh->port & (1 << USB_PORT_FEAT_SUSPEND))) | ||
2273 | continue; | ||
2274 | |||
2275 | dbg("resume port = %d", port); | ||
2276 | rh->port &= ~(1 << USB_PORT_FEAT_SUSPEND); | ||
2277 | rh->port |= 1 << USB_PORT_FEAT_C_SUSPEND; | ||
2278 | r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg); | ||
2279 | msleep(50); | ||
2280 | r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg); | ||
2281 | } | ||
2282 | |||
2283 | return 0; | ||
2284 | |||
2285 | } | ||
2286 | #else | ||
2287 | #define r8a66597_bus_suspend NULL | ||
2288 | #define r8a66597_bus_resume NULL | ||
2289 | #endif | ||
2290 | |||
2216 | static struct hc_driver r8a66597_hc_driver = { | 2291 | static struct hc_driver r8a66597_hc_driver = { |
2217 | .description = hcd_name, | 2292 | .description = hcd_name, |
2218 | .hcd_priv_size = sizeof(struct r8a66597), | 2293 | .hcd_priv_size = sizeof(struct r8a66597), |
@@ -2243,16 +2318,39 @@ static struct hc_driver r8a66597_hc_driver = { | |||
2243 | */ | 2318 | */ |
2244 | .hub_status_data = r8a66597_hub_status_data, | 2319 | .hub_status_data = r8a66597_hub_status_data, |
2245 | .hub_control = r8a66597_hub_control, | 2320 | .hub_control = r8a66597_hub_control, |
2321 | .bus_suspend = r8a66597_bus_suspend, | ||
2322 | .bus_resume = r8a66597_bus_resume, | ||
2246 | }; | 2323 | }; |
2247 | 2324 | ||
2248 | #if defined(CONFIG_PM) | 2325 | #if defined(CONFIG_PM) |
2249 | static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state) | 2326 | static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state) |
2250 | { | 2327 | { |
2328 | struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); | ||
2329 | int port; | ||
2330 | |||
2331 | dbg("%s", __func__); | ||
2332 | |||
2333 | disable_controller(r8a66597); | ||
2334 | |||
2335 | for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { | ||
2336 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | ||
2337 | |||
2338 | rh->port = 0x00000000; | ||
2339 | } | ||
2340 | |||
2251 | return 0; | 2341 | return 0; |
2252 | } | 2342 | } |
2253 | 2343 | ||
2254 | static int r8a66597_resume(struct platform_device *pdev) | 2344 | static int r8a66597_resume(struct platform_device *pdev) |
2255 | { | 2345 | { |
2346 | struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); | ||
2347 | struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); | ||
2348 | |||
2349 | dbg("%s", __func__); | ||
2350 | |||
2351 | enable_controller(r8a66597); | ||
2352 | usb_root_hub_lost_power(hcd->self.root_hub); | ||
2353 | |||
2256 | return 0; | 2354 | return 0; |
2257 | } | 2355 | } |
2258 | #else /* if defined(CONFIG_PM) */ | 2356 | #else /* if defined(CONFIG_PM) */ |