aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-sched.c
diff options
context:
space:
mode:
authorAndiry Xu <andiry.xu@amd.com>2011-01-25 05:41:21 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-04 14:42:52 -0500
commitb7d5b439b7a40dd0a0202fe1c118615a3fcc3b25 (patch)
tree8a9be25f550e4a9921733d5b0dae9c8fcdc274f6 /drivers/usb/host/ehci-sched.c
parenta51ea8cc9cfcfd719240455ff8f217b4f165d1d0 (diff)
USB host: Move AMD PLL quirk to pci-quirks.c
This patch moves the AMD PLL quirk code in OHCI/EHCI driver to pci-quirks.c, and exports the functions to be used by xHCI driver later. AMD PLL quirk disable the optional PM feature inside specific SB700/SB800/Hudson-2/3 platforms under the following conditions: 1. If an isochronous device is connected to OHCI/EHCI/xHCI port and is active; 2. Optional PM feature that powers down the internal Bus PLL when the link is in low power state is enabled. Without AMD PLL quirk, USB isochronous stream may stutter or have breaks occasionally, which greatly impair the performance of audio/video streams. Currently AMD PLL quirk is implemented in OHCI and EHCI driver, and will be added to xHCI driver too. They are doing similar things actually, so move the quirk code to pci-quirks.c, which has several advantages: 1. Remove duplicate defines and functions in OHCI/EHCI (and xHCI) driver and make them cleaner; 2. AMD chipset information will be probed only once and then stored. Currently they're probed during every OHCI/EHCI initialization, move the detect code to pci-quirks.c saves the repeat detect cost; 3. Build up synchronization among OHCI/EHCI/xHCI driver. In current code, every host controller enable/disable PLL only according to its own status, and may enable PLL while there is still isoc transfer on other HCs. Move the quirk to pci-quirks.c prevents this issue. Signed-off-by: Andiry Xu <andiry.xu@amd.com> Cc: David Brownell <dbrownell@users.sourceforge.net> Cc: Alex He <alex.he@amd.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ehci-sched.c')
-rw-r--r--drivers/usb/host/ehci-sched.c73
1 files changed, 8 insertions, 65 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index aa46f57f9ec8..b3bd1c6dc61f 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1590,63 +1590,6 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
1590 *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); 1590 *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
1591} 1591}
1592 1592
1593#define AB_REG_BAR_LOW 0xe0
1594#define AB_REG_BAR_HIGH 0xe1
1595#define AB_INDX(addr) ((addr) + 0x00)
1596#define AB_DATA(addr) ((addr) + 0x04)
1597#define NB_PCIE_INDX_ADDR 0xe0
1598#define NB_PCIE_INDX_DATA 0xe4
1599#define NB_PIF0_PWRDOWN_0 0x01100012
1600#define NB_PIF0_PWRDOWN_1 0x01100013
1601
1602static void ehci_quirk_amd_L1(struct ehci_hcd *ehci, int disable)
1603{
1604 u32 addr, addr_low, addr_high, val;
1605
1606 outb_p(AB_REG_BAR_LOW, 0xcd6);
1607 addr_low = inb_p(0xcd7);
1608 outb_p(AB_REG_BAR_HIGH, 0xcd6);
1609 addr_high = inb_p(0xcd7);
1610 addr = addr_high << 8 | addr_low;
1611 outl_p(0x30, AB_INDX(addr));
1612 outl_p(0x40, AB_DATA(addr));
1613 outl_p(0x34, AB_INDX(addr));
1614 val = inl_p(AB_DATA(addr));
1615
1616 if (disable) {
1617 val &= ~0x8;
1618 val |= (1 << 4) | (1 << 9);
1619 } else {
1620 val |= 0x8;
1621 val &= ~((1 << 4) | (1 << 9));
1622 }
1623 outl_p(val, AB_DATA(addr));
1624
1625 if (amd_nb_dev) {
1626 addr = NB_PIF0_PWRDOWN_0;
1627 pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
1628 pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
1629 if (disable)
1630 val &= ~(0x3f << 7);
1631 else
1632 val |= 0x3f << 7;
1633
1634 pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
1635
1636 addr = NB_PIF0_PWRDOWN_1;
1637 pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
1638 pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
1639 if (disable)
1640 val &= ~(0x3f << 7);
1641 else
1642 val |= 0x3f << 7;
1643
1644 pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
1645 }
1646
1647 return;
1648}
1649
1650/* fit urb's itds into the selected schedule slot; activate as needed */ 1593/* fit urb's itds into the selected schedule slot; activate as needed */
1651static int 1594static int
1652itd_link_urb ( 1595itd_link_urb (
@@ -1675,8 +1618,8 @@ itd_link_urb (
1675 } 1618 }
1676 1619
1677 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 1620 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
1678 if (ehci->amd_l1_fix == 1) 1621 if (ehci->amd_pll_fix == 1)
1679 ehci_quirk_amd_L1(ehci, 1); 1622 usb_amd_quirk_pll_disable();
1680 } 1623 }
1681 1624
1682 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; 1625 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -1804,8 +1747,8 @@ itd_complete (
1804 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; 1747 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
1805 1748
1806 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 1749 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
1807 if (ehci->amd_l1_fix == 1) 1750 if (ehci->amd_pll_fix == 1)
1808 ehci_quirk_amd_L1(ehci, 0); 1751 usb_amd_quirk_pll_enable();
1809 } 1752 }
1810 1753
1811 if (unlikely(list_is_singular(&stream->td_list))) { 1754 if (unlikely(list_is_singular(&stream->td_list))) {
@@ -2095,8 +2038,8 @@ sitd_link_urb (
2095 } 2038 }
2096 2039
2097 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 2040 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
2098 if (ehci->amd_l1_fix == 1) 2041 if (ehci->amd_pll_fix == 1)
2099 ehci_quirk_amd_L1(ehci, 1); 2042 usb_amd_quirk_pll_disable();
2100 } 2043 }
2101 2044
2102 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; 2045 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -2200,8 +2143,8 @@ sitd_complete (
2200 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; 2143 ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
2201 2144
2202 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 2145 if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
2203 if (ehci->amd_l1_fix == 1) 2146 if (ehci->amd_pll_fix == 1)
2204 ehci_quirk_amd_L1(ehci, 0); 2147 usb_amd_quirk_pll_enable();
2205 } 2148 }
2206 2149
2207 if (list_is_singular(&stream->td_list)) { 2150 if (list_is_singular(&stream->td_list)) {