#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/irq.h>
-#include <linux/sched.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
static void ohci1394_pci_remove(struct pci_dev *pdev);
#ifndef __LITTLE_ENDIAN
-const static size_t hdr_sizes[] = {
+static const size_t hdr_sizes[] = {
3, /* TCODE_WRITEQ */
4, /* TCODE_WRITEB */
3, /* TCODE_WRITE_RESPONSE */
/* Global initialization */
static void ohci_initialize(struct ti_ohci *ohci)
{
- char irq_buf[16];
quadlet_t buf;
int num_ports, i;
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
buf = reg_read(ohci, OHCI1394_Version);
- sprintf (irq_buf, "%d", ohci->dev->irq);
- PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] "
+ PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%d] "
"MMIO=[%llx-%llx] Max Packet=[%d] IR/IT contexts=[%d/%d]",
((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
- ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf,
+ ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq,
(unsigned long long)pci_resource_start(ohci->dev, 0),
(unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
ohci->max_packet_size,
int ctx;
int ret = -ENOMEM;
- recv = kmalloc(sizeof(*recv), SLAB_KERNEL);
+ recv = kmalloc(sizeof(*recv), GFP_KERNEL);
if (!recv)
return -ENOMEM;
int ctx;
int ret = -ENOMEM;
- xmit = kmalloc(sizeof(*xmit), SLAB_KERNEL);
+ xmit = kmalloc(sizeof(*xmit), GFP_KERNEL);
if (!xmit)
return -ENOMEM;
if (event & OHCI1394_postedWriteErr) {
PRINT(KERN_ERR, "physical posted write error");
/* no recovery strategy yet, had to involve protocol drivers */
+ event &= ~OHCI1394_postedWriteErr;
}
if (event & OHCI1394_cycleTooLong) {
if(printk_ratelimit())
return -ENOMEM;
}
- d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, SLAB_KERNEL, d->prg_bus+i);
+ d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i);
if (d->prg_cpu[i] != NULL) {
OHCI_DMA_ALLOC("dma_rcv prg pool");
for (i = 0; i < d->num_desc; i++) {
- d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, SLAB_KERNEL, d->prg_bus+i);
+ d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i);
if (d->prg_cpu[i] != NULL) {
struct ti_ohci *ohci; /* shortcut to currently handled device */
resource_size_t ohci_base;
+#ifdef CONFIG_PPC_PMAC
+ /* Necessary on some machines if ohci1394 was loaded/ unloaded before */
+ if (machine_is(powermac)) {
+ struct device_node *ofn = pci_device_to_OF_node(dev);
+
+ if (ofn) {
+ pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1);
+ pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+ }
+ }
+#endif /* CONFIG_PPC_PMAC */
+
if (pci_enable_device(dev))
FAIL(-ENXIO, "Failed to enable OHCI hardware");
pci_set_master(dev);
PRINT(KERN_WARNING, "PCI resource length of 0x%llx too small!",
(unsigned long long)pci_resource_len(dev, 0));
- /* Seems PCMCIA handles this internally. Not sure why. Seems
- * pretty bogus to force a driver to special case this. */
-#ifndef PCMCIA
- if (!request_mem_region (ohci_base, OHCI1394_REGISTER_SIZE, OHCI1394_DRIVER_NAME))
+ if (!request_mem_region(ohci_base, OHCI1394_REGISTER_SIZE,
+ OHCI1394_DRIVER_NAME))
FAIL(-ENOMEM, "MMIO resource (0x%llx - 0x%llx) unavailable",
(unsigned long long)ohci_base,
(unsigned long long)ohci_base + OHCI1394_REGISTER_SIZE);
-#endif
ohci->init_state = OHCI_INIT_HAVE_MEM_REGION;
ohci->registers = ioremap(ohci_base, OHCI1394_REGISTER_SIZE);
iounmap(ohci->registers);
case OHCI_INIT_HAVE_MEM_REGION:
-#ifndef PCMCIA
release_mem_region(pci_resource_start(ohci->dev, 0),
OHCI1394_REGISTER_SIZE);
-#endif
#ifdef CONFIG_PPC_PMAC
- /* On UniNorth, power down the cable and turn off the chip
- * clock when the module is removed to save power on
- * laptops. Turning it back ON is done by the arch code when
- * pci_enable_device() is called */
- {
- struct device_node* of_node;
+ /* On UniNorth, power down the cable and turn off the chip clock
+ * to save power on laptops */
+ if (machine_is(powermac)) {
+ struct device_node* ofn = pci_device_to_OF_node(ohci->dev);
- of_node = pci_device_to_OF_node(ohci->dev);
- if (of_node) {
- pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
- pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, of_node, 0, 0);
+ if (ofn) {
+ pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+ pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
}
}
#endif /* CONFIG_PPC_PMAC */
}
#ifdef CONFIG_PM
-static int ohci1394_pci_resume (struct pci_dev *pdev)
+static int ohci1394_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
-/* PowerMac resume code comes first */
-#ifdef CONFIG_PPC_PMAC
- if (machine_is(powermac)) {
- struct device_node *of_node;
+ int err;
+ struct ti_ohci *ohci = pci_get_drvdata(pdev);
- /* Re-enable 1394 */
- of_node = pci_device_to_OF_node (pdev);
- if (of_node)
- pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1);
+ if (!ohci) {
+ printk(KERN_ERR "%s: tried to suspend nonexisting host\n",
+ OHCI1394_DRIVER_NAME);
+ return -ENXIO;
}
-#endif /* CONFIG_PPC_PMAC */
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- return pci_enable_device(pdev);
-}
+ DBGMSG("suspend called");
-static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
-{
- int err;
+ /* Clear the async DMA contexts and stop using the controller */
+ hpsb_bus_reset(ohci->host);
- printk(KERN_INFO "%s does not fully support suspend and resume yet\n",
- OHCI1394_DRIVER_NAME);
+ /* See ohci1394_pci_remove() for comments on this sequence */
+ reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
+ reg_write(ohci, OHCI1394_BusOptions,
+ (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) |
+ 0x00ff0000);
+ reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
+ set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4));
+ reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
+ ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
+ ohci_soft_reset(ohci);
err = pci_save_state(pdev);
if (err) {
- printk(KERN_ERR "%s: pci_save_state failed with %d\n",
- OHCI1394_DRIVER_NAME, err);
+ PRINT(KERN_ERR, "pci_save_state failed with %d", err);
return err;
}
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
-#ifdef OHCI1394_DEBUG
if (err)
- printk(KERN_DEBUG "%s: pci_set_power_state failed with %d\n",
- OHCI1394_DRIVER_NAME, err);
-#endif /* OHCI1394_DEBUG */
+ DBGMSG("pci_set_power_state failed with %d", err);
/* PowerMac suspend code comes last */
#ifdef CONFIG_PPC_PMAC
if (machine_is(powermac)) {
- struct device_node *of_node;
+ struct device_node *ofn = pci_device_to_OF_node(pdev);
- /* Disable 1394 */
- of_node = pci_device_to_OF_node (pdev);
- if (of_node)
- pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
+ if (ofn)
+ pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
}
#endif /* CONFIG_PPC_PMAC */
return 0;
}
-#endif /* CONFIG_PM */
-#define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10)
+static int ohci1394_pci_resume(struct pci_dev *pdev)
+{
+ int err;
+ struct ti_ohci *ohci = pci_get_drvdata(pdev);
+
+ if (!ohci) {
+ printk(KERN_ERR "%s: tried to resume nonexisting host\n",
+ OHCI1394_DRIVER_NAME);
+ return -ENXIO;
+ }
+ DBGMSG("resume called");
+
+/* PowerMac resume code comes first */
+#ifdef CONFIG_PPC_PMAC
+ if (machine_is(powermac)) {
+ struct device_node *ofn = pci_device_to_OF_node(pdev);
+
+ if (ofn)
+ pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+ }
+#endif /* CONFIG_PPC_PMAC */
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ err = pci_enable_device(pdev);
+ if (err) {
+ PRINT(KERN_ERR, "pci_enable_device failed with %d", err);
+ return err;
+ }
+
+ /* See ohci1394_pci_probe() for comments on this sequence */
+ ohci_soft_reset(ohci);
+ reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
+ reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
+ mdelay(50);
+ ohci_initialize(ohci);
+
+ hpsb_resume_host(ohci->host);
+ return 0;
+}
+#endif /* CONFIG_PM */
static struct pci_device_id ohci1394_pci_tbl[] = {
{
- .class = PCI_CLASS_FIREWIRE_OHCI,
+ .class = PCI_CLASS_SERIAL_FIREWIRE_OHCI,
.class_mask = PCI_ANY_ID,
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
/* essentially the only purpose of this code is to allow another
module to hook into ohci's interrupt handler */
+/* returns zero if successful, one if DMA context is locked up */
int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg)
{
int i=0;