aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
authorAndiry Xu <andiry.xu@amd.com>2011-12-12 03:45:28 -0500
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-03-12 12:31:24 -0400
commitf99298bfa7c42da8d27c2b42050941471c0866ab (patch)
tree3e41bfc8effe612b9626ea2011e6b37b9bc6b0d5 /drivers/usb/host/xhci.c
parentf7a0d426f3e7ec321b8037238b6426566df36edb (diff)
xHCI: BESL calculation based on USB2.0 LPM errata
The latest released errata for USB2.0 ECN LPM adds new fields to USB2.0 extension descriptor, defines two BESL values for device: baseline BESL and deep BESL. Baseline BESL value communicates a nominal power savings design point and the deep BESL value communicates a significant power savings design point. If device indicates BESL value, driver will use a value count in both host BESL and device BESL. Use baseline BESL value as default. Signed-off-by: Andiry Xu <andiry.xu@amd.com> Tested-by: Jason Fan <jcfan@qca.qualcomm.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c51
1 files changed, 27 insertions, 24 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index a629ad860329..262400c10075 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3614,26 +3614,38 @@ static int xhci_besl_encoding[16] = {125, 150, 200, 300, 400, 500, 1000, 2000,
3614 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000}; 3614 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000};
3615 3615
3616/* Calculate HIRD/BESL for USB2 PORTPMSC*/ 3616/* Calculate HIRD/BESL for USB2 PORTPMSC*/
3617static int xhci_calculate_hird_besl(int u2del, bool use_besl) 3617static int xhci_calculate_hird_besl(struct xhci_hcd *xhci,
3618 struct usb_device *udev)
3618{ 3619{
3619 int hird; 3620 int u2del, besl, besl_host;
3621 int besl_device = 0;
3622 u32 field;
3623
3624 u2del = HCS_U2_LATENCY(xhci->hcs_params3);
3625 field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
3620 3626
3621 if (use_besl) { 3627 if (field & USB_BESL_SUPPORT) {
3622 for (hird = 0; hird < 16; hird++) { 3628 for (besl_host = 0; besl_host < 16; besl_host++) {
3623 if (xhci_besl_encoding[hird] >= u2del) 3629 if (xhci_besl_encoding[besl_host] >= u2del)
3624 break; 3630 break;
3625 } 3631 }
3632 /* Use baseline BESL value as default */
3633 if (field & USB_BESL_BASELINE_VALID)
3634 besl_device = USB_GET_BESL_BASELINE(field);
3635 else if (field & USB_BESL_DEEP_VALID)
3636 besl_device = USB_GET_BESL_DEEP(field);
3626 } else { 3637 } else {
3627 if (u2del <= 50) 3638 if (u2del <= 50)
3628 hird = 0; 3639 besl_host = 0;
3629 else 3640 else
3630 hird = (u2del - 51) / 75 + 1; 3641 besl_host = (u2del - 51) / 75 + 1;
3631
3632 if (hird > 15)
3633 hird = 15;
3634 } 3642 }
3635 3643
3636 return hird; 3644 besl = besl_host + besl_device;
3645 if (besl > 15)
3646 besl = 15;
3647
3648 return besl;
3637} 3649}
3638 3650
3639static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd, 3651static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
@@ -3646,7 +3658,7 @@ static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
3646 u32 temp, dev_id; 3658 u32 temp, dev_id;
3647 unsigned int port_num; 3659 unsigned int port_num;
3648 unsigned long flags; 3660 unsigned long flags;
3649 int u2del, hird; 3661 int hird;
3650 int ret; 3662 int ret;
3651 3663
3652 if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support || 3664 if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support ||
@@ -3692,12 +3704,7 @@ static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
3692 * HIRD or BESL shoule be used. See USB2.0 LPM errata. 3704 * HIRD or BESL shoule be used. See USB2.0 LPM errata.
3693 */ 3705 */
3694 pm_addr = port_array[port_num] + 1; 3706 pm_addr = port_array[port_num] + 1;
3695 u2del = HCS_U2_LATENCY(xhci->hcs_params3); 3707 hird = xhci_calculate_hird_besl(xhci, udev);
3696 if (le32_to_cpu(udev->bos->ext_cap->bmAttributes) & (1 << 2))
3697 hird = xhci_calculate_hird_besl(u2del, 1);
3698 else
3699 hird = xhci_calculate_hird_besl(u2del, 0);
3700
3701 temp = PORT_L1DS(udev->slot_id) | PORT_HIRD(hird); 3708 temp = PORT_L1DS(udev->slot_id) | PORT_HIRD(hird);
3702 xhci_writel(xhci, temp, pm_addr); 3709 xhci_writel(xhci, temp, pm_addr);
3703 3710
@@ -3776,7 +3783,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
3776 u32 temp; 3783 u32 temp;
3777 unsigned int port_num; 3784 unsigned int port_num;
3778 unsigned long flags; 3785 unsigned long flags;
3779 int u2del, hird; 3786 int hird;
3780 3787
3781 if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support || 3788 if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support ||
3782 !udev->lpm_capable) 3789 !udev->lpm_capable)
@@ -3799,11 +3806,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
3799 xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", 3806 xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
3800 enable ? "enable" : "disable", port_num); 3807 enable ? "enable" : "disable", port_num);
3801 3808
3802 u2del = HCS_U2_LATENCY(xhci->hcs_params3); 3809 hird = xhci_calculate_hird_besl(xhci, udev);
3803 if (le32_to_cpu(udev->bos->ext_cap->bmAttributes) & (1 << 2))
3804 hird = xhci_calculate_hird_besl(u2del, 1);
3805 else
3806 hird = xhci_calculate_hird_besl(u2del, 0);
3807 3810
3808 if (enable) { 3811 if (enable) {
3809 temp &= ~PORT_HIRD_MASK; 3812 temp &= ~PORT_HIRD_MASK;