diff options
Diffstat (limited to 'drivers/firewire/fw-ohci.c')
-rw-r--r-- | drivers/firewire/fw-ohci.c | 188 |
1 files changed, 124 insertions, 64 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index c17342d3e6fd..0d08bf9b78c2 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c | |||
@@ -268,7 +268,7 @@ static int ar_context_add_page(struct ar_context *ctx) | |||
268 | 268 | ||
269 | dma_sync_single_for_device(dev, ab_bus, PAGE_SIZE, DMA_BIDIRECTIONAL); | 269 | dma_sync_single_for_device(dev, ab_bus, PAGE_SIZE, DMA_BIDIRECTIONAL); |
270 | 270 | ||
271 | ctx->last_buffer->descriptor.branch_address = ab_bus | 1; | 271 | ctx->last_buffer->descriptor.branch_address = cpu_to_le32(ab_bus | 1); |
272 | ctx->last_buffer->next = ab; | 272 | ctx->last_buffer->next = ab; |
273 | ctx->last_buffer = ab; | 273 | ctx->last_buffer = ab; |
274 | 274 | ||
@@ -417,11 +417,21 @@ ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 regs) | |||
417 | ctx->current_buffer = ab.next; | 417 | ctx->current_buffer = ab.next; |
418 | ctx->pointer = ctx->current_buffer->data; | 418 | ctx->pointer = ctx->current_buffer->data; |
419 | 419 | ||
420 | reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab.descriptor.branch_address); | 420 | return 0; |
421 | } | ||
422 | |||
423 | static void ar_context_run(struct ar_context *ctx) | ||
424 | { | ||
425 | struct ar_buffer *ab = ctx->current_buffer; | ||
426 | dma_addr_t ab_bus; | ||
427 | size_t offset; | ||
428 | |||
429 | offset = offsetof(struct ar_buffer, data); | ||
430 | ab_bus = ab->descriptor.data_address - offset; | ||
431 | |||
432 | reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab_bus | 1); | ||
421 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); | 433 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); |
422 | flush_writes(ctx->ohci); | 434 | flush_writes(ctx->ohci); |
423 | |||
424 | return 0; | ||
425 | } | 435 | } |
426 | 436 | ||
427 | static void context_tasklet(unsigned long data) | 437 | static void context_tasklet(unsigned long data) |
@@ -1038,11 +1048,78 @@ static irqreturn_t irq_handler(int irq, void *data) | |||
1038 | return IRQ_HANDLED; | 1048 | return IRQ_HANDLED; |
1039 | } | 1049 | } |
1040 | 1050 | ||
1051 | static int software_reset(struct fw_ohci *ohci) | ||
1052 | { | ||
1053 | int i; | ||
1054 | |||
1055 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); | ||
1056 | |||
1057 | for (i = 0; i < OHCI_LOOP_COUNT; i++) { | ||
1058 | if ((reg_read(ohci, OHCI1394_HCControlSet) & | ||
1059 | OHCI1394_HCControl_softReset) == 0) | ||
1060 | return 0; | ||
1061 | msleep(1); | ||
1062 | } | ||
1063 | |||
1064 | return -EBUSY; | ||
1065 | } | ||
1066 | |||
1041 | static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) | 1067 | static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) |
1042 | { | 1068 | { |
1043 | struct fw_ohci *ohci = fw_ohci(card); | 1069 | struct fw_ohci *ohci = fw_ohci(card); |
1044 | struct pci_dev *dev = to_pci_dev(card->device); | 1070 | struct pci_dev *dev = to_pci_dev(card->device); |
1045 | 1071 | ||
1072 | if (software_reset(ohci)) { | ||
1073 | fw_error("Failed to reset ohci card.\n"); | ||
1074 | return -EBUSY; | ||
1075 | } | ||
1076 | |||
1077 | /* | ||
1078 | * Now enable LPS, which we need in order to start accessing | ||
1079 | * most of the registers. In fact, on some cards (ALI M5251), | ||
1080 | * accessing registers in the SClk domain without LPS enabled | ||
1081 | * will lock up the machine. Wait 50msec to make sure we have | ||
1082 | * full link enabled. | ||
1083 | */ | ||
1084 | reg_write(ohci, OHCI1394_HCControlSet, | ||
1085 | OHCI1394_HCControl_LPS | | ||
1086 | OHCI1394_HCControl_postedWriteEnable); | ||
1087 | flush_writes(ohci); | ||
1088 | msleep(50); | ||
1089 | |||
1090 | reg_write(ohci, OHCI1394_HCControlClear, | ||
1091 | OHCI1394_HCControl_noByteSwapData); | ||
1092 | |||
1093 | reg_write(ohci, OHCI1394_LinkControlSet, | ||
1094 | OHCI1394_LinkControl_rcvSelfID | | ||
1095 | OHCI1394_LinkControl_cycleTimerEnable | | ||
1096 | OHCI1394_LinkControl_cycleMaster); | ||
1097 | |||
1098 | reg_write(ohci, OHCI1394_ATRetries, | ||
1099 | OHCI1394_MAX_AT_REQ_RETRIES | | ||
1100 | (OHCI1394_MAX_AT_RESP_RETRIES << 4) | | ||
1101 | (OHCI1394_MAX_PHYS_RESP_RETRIES << 8)); | ||
1102 | |||
1103 | ar_context_run(&ohci->ar_request_ctx); | ||
1104 | ar_context_run(&ohci->ar_response_ctx); | ||
1105 | |||
1106 | reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus); | ||
1107 | reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000); | ||
1108 | reg_write(ohci, OHCI1394_IntEventClear, ~0); | ||
1109 | reg_write(ohci, OHCI1394_IntMaskClear, ~0); | ||
1110 | reg_write(ohci, OHCI1394_IntMaskSet, | ||
1111 | OHCI1394_selfIDComplete | | ||
1112 | OHCI1394_RQPkt | OHCI1394_RSPkt | | ||
1113 | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | | ||
1114 | OHCI1394_isochRx | OHCI1394_isochTx | | ||
1115 | OHCI1394_masterIntEnable | | ||
1116 | OHCI1394_cycle64Seconds); | ||
1117 | |||
1118 | /* Activate link_on bit and contender bit in our self ID packets.*/ | ||
1119 | if (ohci_update_phy_reg(card, 4, 0, | ||
1120 | PHY_LINK_ACTIVE | PHY_CONTENDER) < 0) | ||
1121 | return -EIO; | ||
1122 | |||
1046 | /* | 1123 | /* |
1047 | * When the link is not yet enabled, the atomic config rom | 1124 | * When the link is not yet enabled, the atomic config rom |
1048 | * update mechanism described below in ohci_set_config_rom() | 1125 | * update mechanism described below in ohci_set_config_rom() |
@@ -1700,22 +1777,6 @@ static const struct fw_card_driver ohci_driver = { | |||
1700 | .stop_iso = ohci_stop_iso, | 1777 | .stop_iso = ohci_stop_iso, |
1701 | }; | 1778 | }; |
1702 | 1779 | ||
1703 | static int software_reset(struct fw_ohci *ohci) | ||
1704 | { | ||
1705 | int i; | ||
1706 | |||
1707 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); | ||
1708 | |||
1709 | for (i = 0; i < OHCI_LOOP_COUNT; i++) { | ||
1710 | if ((reg_read(ohci, OHCI1394_HCControlSet) & | ||
1711 | OHCI1394_HCControl_softReset) == 0) | ||
1712 | return 0; | ||
1713 | msleep(1); | ||
1714 | } | ||
1715 | |||
1716 | return -EBUSY; | ||
1717 | } | ||
1718 | |||
1719 | static int __devinit | 1780 | static int __devinit |
1720 | pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) | 1781 | pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) |
1721 | { | 1782 | { |
@@ -1761,33 +1822,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
1761 | goto fail_iomem; | 1822 | goto fail_iomem; |
1762 | } | 1823 | } |
1763 | 1824 | ||
1764 | if (software_reset(ohci)) { | ||
1765 | fw_error("Failed to reset ohci card.\n"); | ||
1766 | err = -EBUSY; | ||
1767 | goto fail_registers; | ||
1768 | } | ||
1769 | |||
1770 | /* | ||
1771 | * Now enable LPS, which we need in order to start accessing | ||
1772 | * most of the registers. In fact, on some cards (ALI M5251), | ||
1773 | * accessing registers in the SClk domain without LPS enabled | ||
1774 | * will lock up the machine. Wait 50msec to make sure we have | ||
1775 | * full link enabled. | ||
1776 | */ | ||
1777 | reg_write(ohci, OHCI1394_HCControlSet, | ||
1778 | OHCI1394_HCControl_LPS | | ||
1779 | OHCI1394_HCControl_postedWriteEnable); | ||
1780 | flush_writes(ohci); | ||
1781 | msleep(50); | ||
1782 | |||
1783 | reg_write(ohci, OHCI1394_HCControlClear, | ||
1784 | OHCI1394_HCControl_noByteSwapData); | ||
1785 | |||
1786 | reg_write(ohci, OHCI1394_LinkControlSet, | ||
1787 | OHCI1394_LinkControl_rcvSelfID | | ||
1788 | OHCI1394_LinkControl_cycleTimerEnable | | ||
1789 | OHCI1394_LinkControl_cycleMaster); | ||
1790 | |||
1791 | ar_context_init(&ohci->ar_request_ctx, ohci, | 1825 | ar_context_init(&ohci->ar_request_ctx, ohci, |
1792 | OHCI1394_AsReqRcvContextControlSet); | 1826 | OHCI1394_AsReqRcvContextControlSet); |
1793 | 1827 | ||
@@ -1800,11 +1834,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
1800 | context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE, | 1834 | context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE, |
1801 | OHCI1394_AsRspTrContextControlSet, handle_at_packet); | 1835 | OHCI1394_AsRspTrContextControlSet, handle_at_packet); |
1802 | 1836 | ||
1803 | reg_write(ohci, OHCI1394_ATRetries, | ||
1804 | OHCI1394_MAX_AT_REQ_RETRIES | | ||
1805 | (OHCI1394_MAX_AT_RESP_RETRIES << 4) | | ||
1806 | (OHCI1394_MAX_PHYS_RESP_RETRIES << 8)); | ||
1807 | |||
1808 | reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0); | 1837 | reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0); |
1809 | ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); | 1838 | ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); |
1810 | reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0); | 1839 | reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0); |
@@ -1834,18 +1863,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
1834 | goto fail_registers; | 1863 | goto fail_registers; |
1835 | } | 1864 | } |
1836 | 1865 | ||
1837 | reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus); | ||
1838 | reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000); | ||
1839 | reg_write(ohci, OHCI1394_IntEventClear, ~0); | ||
1840 | reg_write(ohci, OHCI1394_IntMaskClear, ~0); | ||
1841 | reg_write(ohci, OHCI1394_IntMaskSet, | ||
1842 | OHCI1394_selfIDComplete | | ||
1843 | OHCI1394_RQPkt | OHCI1394_RSPkt | | ||
1844 | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | | ||
1845 | OHCI1394_isochRx | OHCI1394_isochTx | | ||
1846 | OHCI1394_masterIntEnable | | ||
1847 | OHCI1394_cycle64Seconds); | ||
1848 | |||
1849 | bus_options = reg_read(ohci, OHCI1394_BusOptions); | 1866 | bus_options = reg_read(ohci, OHCI1394_BusOptions); |
1850 | max_receive = (bus_options >> 12) & 0xf; | 1867 | max_receive = (bus_options >> 12) & 0xf; |
1851 | link_speed = bus_options & 0x7; | 1868 | link_speed = bus_options & 0x7; |
@@ -1907,6 +1924,45 @@ static void pci_remove(struct pci_dev *dev) | |||
1907 | fw_notify("Removed fw-ohci device.\n"); | 1924 | fw_notify("Removed fw-ohci device.\n"); |
1908 | } | 1925 | } |
1909 | 1926 | ||
1927 | #ifdef CONFIG_PM | ||
1928 | static int pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1929 | { | ||
1930 | struct fw_ohci *ohci = pci_get_drvdata(pdev); | ||
1931 | int err; | ||
1932 | |||
1933 | software_reset(ohci); | ||
1934 | free_irq(pdev->irq, ohci); | ||
1935 | err = pci_save_state(pdev); | ||
1936 | if (err) { | ||
1937 | fw_error("pci_save_state failed with %d", err); | ||
1938 | return err; | ||
1939 | } | ||
1940 | err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
1941 | if (err) { | ||
1942 | fw_error("pci_set_power_state failed with %d", err); | ||
1943 | return err; | ||
1944 | } | ||
1945 | |||
1946 | return 0; | ||
1947 | } | ||
1948 | |||
1949 | static int pci_resume(struct pci_dev *pdev) | ||
1950 | { | ||
1951 | struct fw_ohci *ohci = pci_get_drvdata(pdev); | ||
1952 | int err; | ||
1953 | |||
1954 | pci_set_power_state(pdev, PCI_D0); | ||
1955 | pci_restore_state(pdev); | ||
1956 | err = pci_enable_device(pdev); | ||
1957 | if (err) { | ||
1958 | fw_error("pci_enable_device failed with %d", err); | ||
1959 | return err; | ||
1960 | } | ||
1961 | |||
1962 | return ohci_enable(&ohci->card, ohci->config_rom, CONFIG_ROM_SIZE); | ||
1963 | } | ||
1964 | #endif | ||
1965 | |||
1910 | static struct pci_device_id pci_table[] = { | 1966 | static struct pci_device_id pci_table[] = { |
1911 | { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) }, | 1967 | { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) }, |
1912 | { } | 1968 | { } |
@@ -1919,6 +1975,10 @@ static struct pci_driver fw_ohci_pci_driver = { | |||
1919 | .id_table = pci_table, | 1975 | .id_table = pci_table, |
1920 | .probe = pci_probe, | 1976 | .probe = pci_probe, |
1921 | .remove = pci_remove, | 1977 | .remove = pci_remove, |
1978 | #ifdef CONFIG_PM | ||
1979 | .resume = pci_resume, | ||
1980 | .suspend = pci_suspend, | ||
1981 | #endif | ||
1922 | }; | 1982 | }; |
1923 | 1983 | ||
1924 | MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); | 1984 | MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); |