aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-ohci.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-05-30 19:06:35 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-05-31 15:40:14 -0400
commit2aef469a35a273609beaa7094d5a07c1f6d75285 (patch)
tree3aad939f26bee97a7998b67a634478d081192cee /drivers/firewire/fw-ohci.c
parentb32744751e751e0abb184cf3b7359c9387a4bdf8 (diff)
firewire: Implement suspend/resume PCI driver hooks.
It's a low-impact design, that just makes suspend/resume look like a bus reset to the upper level drivers, but it should be sufficient. Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-ohci.c')
-rw-r--r--drivers/firewire/fw-ohci.c187
1 files changed, 123 insertions, 64 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 2e4cfa57126d..0d08bf9b78c2 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -417,12 +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), 420 return 0;
421 le32_to_cpu(ab.descriptor.branch_address)); 421}
422
423static 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);
422 reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); 433 reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
423 flush_writes(ctx->ohci); 434 flush_writes(ctx->ohci);
424
425 return 0;
426} 435}
427 436
428static void context_tasklet(unsigned long data) 437static void context_tasklet(unsigned long data)
@@ -1039,11 +1048,78 @@ static irqreturn_t irq_handler(int irq, void *data)
1039 return IRQ_HANDLED; 1048 return IRQ_HANDLED;
1040} 1049}
1041 1050
1051static 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
1042static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) 1067static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
1043{ 1068{
1044 struct fw_ohci *ohci = fw_ohci(card); 1069 struct fw_ohci *ohci = fw_ohci(card);
1045 struct pci_dev *dev = to_pci_dev(card->device); 1070 struct pci_dev *dev = to_pci_dev(card->device);
1046 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
1047 /* 1123 /*
1048 * When the link is not yet enabled, the atomic config rom 1124 * When the link is not yet enabled, the atomic config rom
1049 * update mechanism described below in ohci_set_config_rom() 1125 * update mechanism described below in ohci_set_config_rom()
@@ -1701,22 +1777,6 @@ static const struct fw_card_driver ohci_driver = {
1701 .stop_iso = ohci_stop_iso, 1777 .stop_iso = ohci_stop_iso,
1702}; 1778};
1703 1779
1704static int software_reset(struct fw_ohci *ohci)
1705{
1706 int i;
1707
1708 reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
1709
1710 for (i = 0; i < OHCI_LOOP_COUNT; i++) {
1711 if ((reg_read(ohci, OHCI1394_HCControlSet) &
1712 OHCI1394_HCControl_softReset) == 0)
1713 return 0;
1714 msleep(1);
1715 }
1716
1717 return -EBUSY;
1718}
1719
1720static int __devinit 1780static int __devinit
1721pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) 1781pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
1722{ 1782{
@@ -1762,33 +1822,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
1762 goto fail_iomem; 1822 goto fail_iomem;
1763 } 1823 }
1764 1824
1765 if (software_reset(ohci)) {
1766 fw_error("Failed to reset ohci card.\n");
1767 err = -EBUSY;
1768 goto fail_registers;
1769 }
1770
1771 /*
1772 * Now enable LPS, which we need in order to start accessing
1773 * most of the registers. In fact, on some cards (ALI M5251),
1774 * accessing registers in the SClk domain without LPS enabled
1775 * will lock up the machine. Wait 50msec to make sure we have
1776 * full link enabled.
1777 */
1778 reg_write(ohci, OHCI1394_HCControlSet,
1779 OHCI1394_HCControl_LPS |
1780 OHCI1394_HCControl_postedWriteEnable);
1781 flush_writes(ohci);
1782 msleep(50);
1783
1784 reg_write(ohci, OHCI1394_HCControlClear,
1785 OHCI1394_HCControl_noByteSwapData);
1786
1787 reg_write(ohci, OHCI1394_LinkControlSet,
1788 OHCI1394_LinkControl_rcvSelfID |
1789 OHCI1394_LinkControl_cycleTimerEnable |
1790 OHCI1394_LinkControl_cycleMaster);
1791
1792 ar_context_init(&ohci->ar_request_ctx, ohci, 1825 ar_context_init(&ohci->ar_request_ctx, ohci,
1793 OHCI1394_AsReqRcvContextControlSet); 1826 OHCI1394_AsReqRcvContextControlSet);
1794 1827
@@ -1801,11 +1834,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
1801 context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE, 1834 context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE,
1802 OHCI1394_AsRspTrContextControlSet, handle_at_packet); 1835 OHCI1394_AsRspTrContextControlSet, handle_at_packet);
1803 1836
1804 reg_write(ohci, OHCI1394_ATRetries,
1805 OHCI1394_MAX_AT_REQ_RETRIES |
1806 (OHCI1394_MAX_AT_RESP_RETRIES << 4) |
1807 (OHCI1394_MAX_PHYS_RESP_RETRIES << 8));
1808
1809 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0); 1837 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
1810 ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); 1838 ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
1811 reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0); 1839 reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
@@ -1835,18 +1863,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
1835 goto fail_registers; 1863 goto fail_registers;
1836 } 1864 }
1837 1865
1838 reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus);
1839 reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000);
1840 reg_write(ohci, OHCI1394_IntEventClear, ~0);
1841 reg_write(ohci, OHCI1394_IntMaskClear, ~0);
1842 reg_write(ohci, OHCI1394_IntMaskSet,
1843 OHCI1394_selfIDComplete |
1844 OHCI1394_RQPkt | OHCI1394_RSPkt |
1845 OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
1846 OHCI1394_isochRx | OHCI1394_isochTx |
1847 OHCI1394_masterIntEnable |
1848 OHCI1394_cycle64Seconds);
1849
1850 bus_options = reg_read(ohci, OHCI1394_BusOptions); 1866 bus_options = reg_read(ohci, OHCI1394_BusOptions);
1851 max_receive = (bus_options >> 12) & 0xf; 1867 max_receive = (bus_options >> 12) & 0xf;
1852 link_speed = bus_options & 0x7; 1868 link_speed = bus_options & 0x7;
@@ -1908,6 +1924,45 @@ static void pci_remove(struct pci_dev *dev)
1908 fw_notify("Removed fw-ohci device.\n"); 1924 fw_notify("Removed fw-ohci device.\n");
1909} 1925}
1910 1926
1927#ifdef CONFIG_PM
1928static 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
1949static 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
1911static struct pci_device_id pci_table[] = { 1966static struct pci_device_id pci_table[] = {
1912 { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) }, 1967 { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) },
1913 { } 1968 { }
@@ -1920,6 +1975,10 @@ static struct pci_driver fw_ohci_pci_driver = {
1920 .id_table = pci_table, 1975 .id_table = pci_table,
1921 .probe = pci_probe, 1976 .probe = pci_probe,
1922 .remove = pci_remove, 1977 .remove = pci_remove,
1978#ifdef CONFIG_PM
1979 .resume = pci_resume,
1980 .suspend = pci_suspend,
1981#endif
1923}; 1982};
1924 1983
1925MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); 1984MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");