aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/ohci.c185
1 files changed, 183 insertions, 2 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index c026f46fc157..b983581cfe35 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -264,6 +264,8 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
264#define PCI_DEVICE_ID_AGERE_FW643 0x5901 264#define PCI_DEVICE_ID_AGERE_FW643 0x5901
265#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380 265#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380
266#define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 266#define PCI_DEVICE_ID_TI_TSB12LV22 0x8009
267#define PCI_DEVICE_ID_TI_TSB12LV26 0x8020
268#define PCI_DEVICE_ID_TI_TSB82AA2 0x8025
267#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd 269#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd
268 270
269#define QUIRK_CYCLE_TIMER 1 271#define QUIRK_CYCLE_TIMER 1
@@ -271,6 +273,7 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
271#define QUIRK_BE_HEADERS 4 273#define QUIRK_BE_HEADERS 4
272#define QUIRK_NO_1394A 8 274#define QUIRK_NO_1394A 8
273#define QUIRK_NO_MSI 16 275#define QUIRK_NO_MSI 16
276#define QUIRK_TI_SLLZ059 32
274 277
275/* In case of multiple matches in ohci_quirks[], only the first one is used. */ 278/* In case of multiple matches in ohci_quirks[], only the first one is used. */
276static const struct { 279static const struct {
@@ -300,6 +303,12 @@ static const struct {
300 {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID, 303 {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
301 QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A}, 304 QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
302 305
306 {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV26, PCI_ANY_ID,
307 QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
308
309 {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB82AA2, PCI_ANY_ID,
310 QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
311
303 {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID, 312 {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
304 QUIRK_RESET_PACKET}, 313 QUIRK_RESET_PACKET},
305 314
@@ -316,6 +325,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
316 ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) 325 ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS)
317 ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) 326 ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A)
318 ", disable MSI = " __stringify(QUIRK_NO_MSI) 327 ", disable MSI = " __stringify(QUIRK_NO_MSI)
328 ", workaround for TI SLLZ059 errata = " __stringify(QUIRK_TI_SLLZ059)
319 ")"); 329 ")");
320 330
321#define OHCI_PARAM_DEBUG_AT_AR 1 331#define OHCI_PARAM_DEBUG_AT_AR 1
@@ -1714,6 +1724,114 @@ static u32 update_bus_time(struct fw_ohci *ohci)
1714 return ohci->bus_time | cycle_time_seconds; 1724 return ohci->bus_time | cycle_time_seconds;
1715} 1725}
1716 1726
1727static int get_status_for_port(struct fw_ohci *ohci, int port_index)
1728{
1729 int reg;
1730
1731 mutex_lock(&ohci->phy_reg_mutex);
1732 reg = write_phy_reg(ohci, 7, port_index);
1733 mutex_unlock(&ohci->phy_reg_mutex);
1734 if (reg < 0)
1735 return reg;
1736
1737 mutex_lock(&ohci->phy_reg_mutex);
1738 reg = read_phy_reg(ohci, 8);
1739 mutex_unlock(&ohci->phy_reg_mutex);
1740 if (reg < 0)
1741 return reg;
1742
1743 switch (reg & 0x0f) {
1744 case 0x06:
1745 return 2; /* is child node (connected to parent node) */
1746 case 0x0e:
1747 return 3; /* is parent node (connected to child node) */
1748 }
1749 return 1; /* not connected */
1750}
1751
1752static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id,
1753 int self_id_count)
1754{
1755 int i;
1756 u32 entry;
1757 for (i = 0; i < self_id_count; i++) {
1758 entry = ohci->self_id_buffer[i];
1759 if ((self_id & 0xff000000) == (entry & 0xff000000))
1760 return -1;
1761 if ((self_id & 0xff000000) < (entry & 0xff000000))
1762 return i;
1763 }
1764 return i;
1765}
1766
1767/*
1768 * This function implements a work around for the Texas Instruments PHY
1769 * TSB41BA3D. This phy has a bug at least in combination with the TI
1770 * LLCs TSB82AA2B and TSB12LV26. The selfid coming from the locally
1771 * connected phy is not propagated into the selfid buffer of the OHCI
1772 * (see http://www.ti.com/litv/pdf/sllz059 for details).
1773 * The main idea is to construct the selfid ourselves.
1774 */
1775
1776static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
1777{
1778 int reg;
1779 int i;
1780 int pos;
1781 int status;
1782 u32 self_id;
1783
1784/*
1785 * preset bits in self_id
1786 *
1787 * link active: 0b1
1788 * speed: 0b11
1789 * bridge: 0b00
1790 * contender: 0b1
1791 * initiated reset: 0b0
1792 * more packets: 0b0
1793 */
1794 self_id = 0x8040C800;
1795
1796 reg = reg_read(ohci, OHCI1394_NodeID);
1797 if (!(reg & OHCI1394_NodeID_idValid)) {
1798 fw_notify("node ID not valid, new bus reset in progress\n");
1799 return -EBUSY;
1800 }
1801 self_id |= ((reg & 0x3f) << 24); /* phy ID */
1802
1803 mutex_lock(&ohci->phy_reg_mutex);
1804 reg = read_phy_reg(ohci, 4);
1805 mutex_unlock(&ohci->phy_reg_mutex);
1806 if (reg < 0)
1807 return reg;
1808 self_id |= ((reg & 0x07) << 8); /* power class */
1809
1810 mutex_lock(&ohci->phy_reg_mutex);
1811 reg = read_phy_reg(ohci, 1);
1812 mutex_unlock(&ohci->phy_reg_mutex);
1813 if (reg < 0)
1814 return reg;
1815 self_id |= ((reg & 0x3f) << 16); /* gap count */
1816
1817 for (i = 0; i < 3; i++) {
1818 status = get_status_for_port(ohci, i);
1819 if (status < 0)
1820 return status;
1821 self_id |= ((status & 0x3) << (6 - (i * 2)));
1822 }
1823
1824 pos = get_self_id_pos(ohci, self_id, self_id_count);
1825 if (pos >= 0) {
1826 memmove(&(ohci->self_id_buffer[pos+1]),
1827 &(ohci->self_id_buffer[pos]),
1828 (self_id_count - pos) * sizeof(*ohci->self_id_buffer));
1829 ohci->self_id_buffer[pos] = self_id;
1830 self_id_count++;
1831 }
1832 return self_id_count;
1833}
1834
1717static void bus_reset_work(struct work_struct *work) 1835static void bus_reset_work(struct work_struct *work)
1718{ 1836{
1719 struct fw_ohci *ohci = 1837 struct fw_ohci *ohci =
@@ -1755,10 +1873,12 @@ static void bus_reset_work(struct work_struct *work)
1755 * bit extra to get the actual number of self IDs. 1873 * bit extra to get the actual number of self IDs.
1756 */ 1874 */
1757 self_id_count = (reg >> 3) & 0xff; 1875 self_id_count = (reg >> 3) & 0xff;
1758 if (self_id_count == 0 || self_id_count > 252) { 1876
1877 if (self_id_count > 252) {
1759 fw_notify("inconsistent self IDs\n"); 1878 fw_notify("inconsistent self IDs\n");
1760 return; 1879 return;
1761 } 1880 }
1881
1762 generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff; 1882 generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
1763 rmb(); 1883 rmb();
1764 1884
@@ -1770,6 +1890,19 @@ static void bus_reset_work(struct work_struct *work)
1770 ohci->self_id_buffer[j] = 1890 ohci->self_id_buffer[j] =
1771 cond_le32_to_cpu(ohci->self_id_cpu[i]); 1891 cond_le32_to_cpu(ohci->self_id_cpu[i]);
1772 } 1892 }
1893
1894 if (ohci->quirks & QUIRK_TI_SLLZ059) {
1895 self_id_count = find_and_insert_self_id(ohci, self_id_count);
1896 if (self_id_count < 0) {
1897 fw_notify("could not construct local self IDs\n");
1898 return;
1899 }
1900 }
1901
1902 if (self_id_count == 0) {
1903 fw_notify("inconsistent self IDs\n");
1904 return;
1905 }
1773 rmb(); 1906 rmb();
1774 1907
1775 /* 1908 /*
@@ -2050,13 +2183,50 @@ static int configure_1394a_enhancements(struct fw_ohci *ohci)
2050 return 0; 2183 return 0;
2051} 2184}
2052 2185
2186#define TSB41BA3D_VID 0x00080028
2187#define TSB41BA3D_PID 0x00833005
2188
2189static int probe_tsb41ba3d(struct fw_ohci *ohci)
2190{
2191 int reg;
2192 int i;
2193 int vendor_id;
2194 int product_id;
2195
2196 reg = read_phy_reg(ohci, 2);
2197 if (reg < 0)
2198 return reg;
2199
2200 if ((reg & PHY_EXTENDED_REGISTERS) == PHY_EXTENDED_REGISTERS) {
2201 vendor_id = 0;
2202 for (i = 10; i < 13; i++) {
2203 reg = read_paged_phy_reg(ohci, 1, i);
2204 if (reg < 0)
2205 return reg;
2206 vendor_id = (vendor_id << 8) | reg;
2207 }
2208 product_id = 0;
2209 for (i = 13; i < 16; i++) {
2210 reg = read_paged_phy_reg(ohci, 1, i);
2211 if (reg < 0)
2212 return reg;
2213 product_id = (product_id << 8) | reg;
2214 }
2215
2216 if ((vendor_id == TSB41BA3D_VID) &&
2217 (product_id == TSB41BA3D_PID))
2218 return 1;
2219 }
2220 return 0;
2221}
2222
2053static int ohci_enable(struct fw_card *card, 2223static int ohci_enable(struct fw_card *card,
2054 const __be32 *config_rom, size_t length) 2224 const __be32 *config_rom, size_t length)
2055{ 2225{
2056 struct fw_ohci *ohci = fw_ohci(card); 2226 struct fw_ohci *ohci = fw_ohci(card);
2057 struct pci_dev *dev = to_pci_dev(card->device); 2227 struct pci_dev *dev = to_pci_dev(card->device);
2058 u32 lps, seconds, version, irqs; 2228 u32 lps, seconds, version, irqs;
2059 int i, ret; 2229 int i, ret, tsb41ba3d_found;
2060 2230
2061 if (software_reset(ohci)) { 2231 if (software_reset(ohci)) {
2062 fw_error("Failed to reset ohci card.\n"); 2232 fw_error("Failed to reset ohci card.\n");
@@ -2087,6 +2257,17 @@ static int ohci_enable(struct fw_card *card,
2087 return -EIO; 2257 return -EIO;
2088 } 2258 }
2089 2259
2260 if (ohci->quirks & QUIRK_TI_SLLZ059) {
2261 tsb41ba3d_found = probe_tsb41ba3d(ohci);
2262 if (tsb41ba3d_found < 0)
2263 return tsb41ba3d_found;
2264 if (!tsb41ba3d_found) {
2265 fw_notify("No TSB41BA3D found, "
2266 "resetting QUIRK_TI_SLLZ059\n");
2267 ohci->quirks &= ~QUIRK_TI_SLLZ059;
2268 }
2269 }
2270
2090 reg_write(ohci, OHCI1394_HCControlClear, 2271 reg_write(ohci, OHCI1394_HCControlClear,
2091 OHCI1394_HCControl_noByteSwapData); 2272 OHCI1394_HCControl_noByteSwapData);
2092 2273