static void __devexit
ohci_pci_remove (struct pci_dev *dev)
{
	ohci_t		*ohci = (ohci_t *) pci_get_drvdata(dev);

	dbg ("remove %s controller usb-%s%s%s",
		hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
		dev->slot_name,
		ohci->disabled ? " (disabled)" : "",
		in_interrupt () ? " in interrupt" : ""
		);

	hc_remove_ohci(ohci);

	release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
	pci_disable_device (dev);
}
static int
ohci_pci_suspend (struct pci_dev *dev, u32 state)
{
	ohci_t			*ohci = (ohci_t *) pci_get_drvdata(dev);
	unsigned long		flags;
	u16 cmd;

	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
		dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
		return -EIO;
	}

	/* act as if usb suspend can always be used */
	info ("USB suspend: usb-%s", dev->slot_name);
	ohci->sleeping = 1;

	/* First stop processing */
  	spin_lock_irqsave (&usb_ed_lock, flags);
	ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
	writel (ohci->hc_control, &ohci->regs->control);
	writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
	(void) readl (&ohci->regs->intrstatus);
  	spin_unlock_irqrestore (&usb_ed_lock, flags);

	/* Wait a frame or two */
	mdelay(1);
	if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
		mdelay (1);
		
#ifdef CONFIG_PMAC_PBOOK
	if (_machine == _MACH_Pmac)
		disable_irq (ohci->irq);
	/* else, 2.4 assumes shared irqs -- don't disable */
#endif
	/* Enable remote wakeup */
	writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);

	/* Suspend chip and let things settle down a bit */
	ohci->hc_control = OHCI_USB_SUSPEND;
	writel (ohci->hc_control, &ohci->regs->control);
	(void) readl (&ohci->regs->control);
	mdelay (500); /* No schedule here ! */
	switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
		case OHCI_USB_RESET:
			dbg("Bus in reset phase ???");
			break;
		case OHCI_USB_RESUME:
			dbg("Bus in resume phase ???");
			break;
		case OHCI_USB_OPER:
			dbg("Bus in operational phase ???");
			break;
		case OHCI_USB_SUSPEND:
			dbg("Bus suspended");
			break;
	}
	/* In some rare situations, Apple's OHCI have happily trashed
	 * memory during sleep. We disable it's bus master bit during
	 * suspend
	 */
	pci_read_config_word (dev, PCI_COMMAND, &cmd);
	cmd &= ~PCI_COMMAND_MASTER;
	pci_write_config_word (dev, PCI_COMMAND, cmd);
#ifdef CONFIG_PMAC_PBOOK
	{
	   	struct device_node	*of_node;

		/* Disable USB PAD & cell clock */
		of_node = pci_device_to_OF_node (ohci->ohci_dev);
		if (of_node)
			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
	}
#endif
	return 0;
}
Exemplo n.º 3
0
static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
{
	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
	u16			cmd;
	u32			tmp;

	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
		ohci_dbg (ohci, "can't suspend (state is %s)\n",
			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
		return -EIO;
	}

	/* act as if usb suspend can always be used */
	ohci_dbg (ohci, "suspend to %d\n", state);
	
	/* First stop processing */
  	spin_lock_irq (&ohci->lock);
	ohci->hc_control &=
		~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
	writel (ohci->hc_control, &ohci->regs->control);
	writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
	(void) readl (&ohci->regs->intrstatus);
  	spin_unlock_irq (&ohci->lock);

	/* Wait a frame or two */
	mdelay (1);
	if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
		mdelay (1);
		
#ifdef CONFIG_PMAC_PBOOK
	if (_machine == _MACH_Pmac)
		disable_irq (hcd->pdev->irq);
 	/* else, 2.4 assumes shared irqs -- don't disable */
#endif

	/* Enable remote wakeup */
	writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD,
		&ohci->regs->intrenable);

	/* Suspend chip and let things settle down a bit */
  	spin_lock_irq (&ohci->lock);
 	ohci->hc_control = OHCI_USB_SUSPEND;
 	writel (ohci->hc_control, &ohci->regs->control);
	(void) readl (&ohci->regs->control);
  	spin_unlock_irq (&ohci->lock);

	set_current_state (TASK_UNINTERRUPTIBLE);
	schedule_timeout (HZ/2);

	tmp = readl (&ohci->regs->control) | OHCI_CTRL_HCFS;
	switch (tmp) {
		case OHCI_USB_RESET:
		case OHCI_USB_RESUME:
		case OHCI_USB_OPER:
			ohci_err (ohci, "can't suspend; hcfs %d\n", tmp);
			break;
		case OHCI_USB_SUSPEND:
			ohci_dbg (ohci, "suspended\n");
			break;
	}

	/* In some rare situations, Apple's OHCI have happily trashed
	 * memory during sleep. We disable its bus master bit during
	 * suspend
	 */
	pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd);
	cmd &= ~PCI_COMMAND_MASTER;
	pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd);
#ifdef CONFIG_PMAC_PBOOK
	{
	   	struct device_node	*of_node;
 
		/* Disable USB PAD & cell clock */
		of_node = pci_device_to_OF_node (hcd->pdev);
		if (of_node)
			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
	}
#endif
	return 0;
}