예제 #1
0
static int ehci_hcd_imapx200_drv_resume(struct device *dev)
{
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);

	/****************************************************/
	int valTmp,i;
	valTmp = __raw_readl(rPAD_CFG);
	if((valTmp & 0xf) != 0xe)
	{
		printk(KERN_ERR "eeeee\n");
		valTmp = __raw_readl(rPAD_CFG);
		valTmp &= ~0xe;
		__raw_writel(valTmp, rPAD_CFG);
		__raw_writel(0x0, rUSB_SRST);
		for(i=0;i<6000;i++);
		valTmp = __raw_readl(rPAD_CFG);
		valTmp |= 0xe;
		__raw_writel(valTmp,rPAD_CFG);
		mdelay(4);
		__raw_writel(0x5,rUSB_SRST);
		for(i=0;i<6000;i++);
		__raw_writel(0xf,rUSB_SRST);
	}

	// maybe restore FLADJ

	if (time_before(jiffies, ehci->next_statechange))
		msleep(100);

	/* Mark hardware accessible again as we are out of D3 state by now */
	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

	/* If CF is still set, we maintained PCI Vaux power.
	 * Just undo the effect of ehci_pci_suspend().
	 */
	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
		int	mask = INTR_MASK;

		if (!hcd->self.root_hub->do_remote_wakeup)
			mask &= ~STS_PCD;
		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
		ehci_readl(ehci, &ehci->regs->intr_enable);
		return 0;
	}

	ehci_dbg(ehci, "lost power, restarting\n");
	usb_root_hub_lost_power(hcd->self.root_hub);

	/* Else reset, to cope with power loss or flush-to-storage
	 * style "resume" having let BIOS kick in during reboot.
	 */
	(void) ehci_halt(ehci);
	(void) ehci_reset(ehci);

	/* emptying the schedule aborts any urbs */
	spin_lock_irq(&ehci->lock);
	if (ehci->reclaim)
		end_unlink_async(ehci);
	ehci_work(ehci);
	spin_unlock_irq(&ehci->lock);

	ehci_writel(ehci, ehci->command, &ehci->regs->command);
	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */

	/* here we "know" root ports should always stay powered */
	ehci_port_power(ehci, 1);

	hcd->state = HC_STATE_SUSPENDED;

	return 0;

}	
예제 #2
0
파일: ehci_sun5i.c 프로젝트: pocketbook/U7
/*
*******************************************************************************
*                     sw_ehci_hcd_resume
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int sw_ehci_hcd_resume(struct device *dev)
{
	struct sw_hci_hcd *sw_ehci = NULL;
	struct usb_hcd *hcd = NULL;
	struct ehci_hcd *ehci = NULL;

	if(dev == NULL){
		DMSG_PANIC("ERR: Argment is invalid\n");
		return 0;
	}

	hcd = dev_get_drvdata(dev);
	if(hcd == NULL){
		DMSG_PANIC("ERR: hcd is null\n");
		return 0;
	}

	sw_ehci = dev->platform_data;
	if(sw_ehci == NULL){
		DMSG_PANIC("ERR: sw_ehci is null\n");
		return 0;
	}

	if(sw_ehci->probe == 0){
		DMSG_PANIC("ERR: sw_ehci is disable, can not resume\n");
		return 0;
	}

	ehci = hcd_to_ehci(hcd);
	if(ehci == NULL){
		DMSG_PANIC("ERR: ehci is null\n");
		return 0;
	}

 	DMSG_INFO("[%s]: sw_ehci_hcd_resume\n", sw_ehci->hci_name);

	sw_start_ehci(sw_ehci);

	/* Mark hardware accessible again as we are out of D3 state by now */
	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
		int	mask = INTR_MASK;

		ehci_prepare_ports_for_controller_resume(ehci);

		if (!hcd->self.root_hub->do_remote_wakeup){
			mask &= ~STS_PCD;
		}

		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
		ehci_readl(ehci, &ehci->regs->intr_enable);

		return 0;
	}

 	DMSG_INFO("[%s]: lost power, restarting\n", sw_ehci->hci_name);

	usb_root_hub_lost_power(hcd->self.root_hub);

	/* Else reset, to cope with power loss or flush-to-storage
	 * style "resume" having let BIOS kick in during reboot.
	 */
	(void) ehci_halt(ehci);
	(void) ehci_reset(ehci);

	/* emptying the schedule aborts any urbs */
	spin_lock_irq(&ehci->lock);
	if (ehci->reclaim)
		end_unlink_async(ehci);
	ehci_work(ehci);
	spin_unlock_irq(&ehci->lock);

	ehci_writel(ehci, ehci->command, &ehci->regs->command);
	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */

	/* here we "know" root ports should always stay powered */
	ehci_port_power(ehci, 1);

	hcd->state = HC_STATE_SUSPENDED;

	return 0;

}
예제 #3
0
/* called during probe() after chip reset completes */
static int ehci_pci_setup(struct usb_hcd *hcd)
{
    struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
    struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
    struct pci_dev		*p_smbus;
    u8			rev;
    u32			temp;
    int			retval;

    switch (pdev->vendor) {
    case PCI_VENDOR_ID_TOSHIBA_2:
        /* celleb's companion chip */
        if (pdev->device == 0x01b5) {
#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
            ehci->big_endian_mmio = 1;
#else
            ehci_warn(ehci,
                      "unsupported big endian Toshiba quirk\n");
#endif
        }
        break;
    }

    ehci->caps = hcd->regs;
    ehci->regs = hcd->regs +
                 HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));

    dbg_hcs_params(ehci, "reset");
    dbg_hcc_params(ehci, "reset");

    /* ehci_init() causes memory for DMA transfers to be
     * allocated.  Thus, any vendor-specific workarounds based on
     * limiting the type of memory used for DMA transfers must
     * happen before ehci_init() is called. */
    switch (pdev->vendor) {
    case PCI_VENDOR_ID_NVIDIA:
        /* NVidia reports that certain chips don't handle
         * QH, ITD, or SITD addresses above 2GB.  (But TD,
         * data buffer, and periodic schedule are normal.)
         */
        switch (pdev->device) {
        case 0x003c:	/* MCP04 */
        case 0x005b:	/* CK804 */
        case 0x00d8:	/* CK8 */
        case 0x00e8:	/* CK8S */
            if (pci_set_consistent_dma_mask(pdev,
                                            DMA_BIT_MASK(31)) < 0)
                ehci_warn(ehci, "can't enable NVidia "
                          "workaround for >2GB RAM\n");
            break;
        }
        break;
    }

    /* cache this readonly data; minimize chip reads */
    ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);

    retval = ehci_halt(ehci);
    if (retval)
        return retval;

    if ((pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x7808) ||
            (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x4396)) {
        /* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
         * read/write memory space which does not belong to it when
         * there is NULL pointer with T-bit set to 1 in the frame list
         * table. To avoid the issue, the frame list link pointer
         * should always contain a valid pointer to a inactive qh.
         */
        ehci->use_dummy_qh = 1;
        ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI "
                  "dummy qh workaround\n");
    }

    /* data structure init */
    retval = ehci_init(hcd);
    if (retval)
        return retval;

    switch (pdev->vendor) {
    case PCI_VENDOR_ID_NEC:
        ehci->need_io_watchdog = 0;
        break;
    case PCI_VENDOR_ID_INTEL:
        ehci->need_io_watchdog = 0;
        ehci->fs_i_thresh = 1;
        if (pdev->device == 0x27cc) {
            ehci->broken_periodic = 1;
            ehci_info(ehci, "using broken periodic workaround\n");
        }
        if (pdev->device == 0x0806 || pdev->device == 0x0811
                || pdev->device == 0x0829) {
            ehci_info(ehci, "disable lpm for langwell/penwell\n");
            ehci->has_lpm = 0;
        }
        break;
    case PCI_VENDOR_ID_TDI:
        if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
            hcd->has_tt = 1;
            tdi_reset(ehci);
        }
        break;
    case PCI_VENDOR_ID_AMD:
        /* AMD8111 EHCI doesn't work, according to AMD errata */
        if (pdev->device == 0x7463) {
            ehci_info(ehci, "ignoring AMD8111 (errata)\n");
            retval = -EIO;
            goto done;
        }
        break;
    case PCI_VENDOR_ID_NVIDIA:
        switch (pdev->device) {
        /* Some NForce2 chips have problems with selective suspend;
         * fixed in newer silicon.
         */
        case 0x0068:
            if (pdev->revision < 0xa4)
                ehci->no_selective_suspend = 1;
            break;

        /* MCP89 chips on the MacBookAir3,1 give EPROTO when
         * fetching device descriptors unless LPM is disabled.
         * There are also intermittent problems enumerating
         * devices with PPCD enabled.
         */
        case 0x0d9d:
            ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
            ehci->has_lpm = 0;
            ehci->has_ppcd = 0;
            ehci->command &= ~CMD_PPCEE;
            break;
        }
        break;
    case PCI_VENDOR_ID_VIA:
        if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x60) {
            u8 tmp;

            /* The VT6212 defaults to a 1 usec EHCI sleep time which
             * hogs the PCI bus *badly*. Setting bit 5 of 0x4B makes
             * that sleep time use the conventional 10 usec.
             */
            pci_read_config_byte(pdev, 0x4b, &tmp);
            if (tmp & 0x20)
                break;
            pci_write_config_byte(pdev, 0x4b, tmp | 0x20);
        }
        break;
    case PCI_VENDOR_ID_ATI:
        /* SB600 and old version of SB700 have a bug in EHCI controller,
         * which causes usb devices lose response in some cases.
         */
        if ((pdev->device == 0x4386) || (pdev->device == 0x4396)) {
            p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
                                     PCI_DEVICE_ID_ATI_SBX00_SMBUS,
                                     NULL);
            if (!p_smbus)
                break;
            rev = p_smbus->revision;
            if ((pdev->device == 0x4386) || (rev == 0x3a)
                    || (rev == 0x3b)) {
                u8 tmp;
                ehci_info(ehci, "applying AMD SB600/SB700 USB "
                          "freeze workaround\n");
                pci_read_config_byte(pdev, 0x53, &tmp);
                pci_write_config_byte(pdev, 0x53, tmp | (1<<3));
            }
            pci_dev_put(p_smbus);
        }
        break;
    }

    /* optional debug port, normally in the first BAR */
    temp = pci_find_capability(pdev, 0x0a);
    if (temp) {
        pci_read_config_dword(pdev, temp, &temp);
        temp >>= 16;
        if ((temp & (3 << 13)) == (1 << 13)) {
            temp &= 0x1fff;
            ehci->debug = ehci_to_hcd(ehci)->regs + temp;
            temp = ehci_readl(ehci, &ehci->debug->control);
            ehci_info(ehci, "debug port %d%s\n",
                      HCS_DEBUG_PORT(ehci->hcs_params),
                      (temp & DBGP_ENABLED)
                      ? " IN USE"
                      : "");
            if (!(temp & DBGP_ENABLED))
                ehci->debug = NULL;
        }
    }

    ehci_reset(ehci);

    /* at least the Genesys GL880S needs fixup here */
    temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
    temp &= 0x0f;
    if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
        ehci_dbg(ehci, "bogus port configuration: "
                 "cc=%d x pcc=%d < ports=%d\n",
                 HCS_N_CC(ehci->hcs_params),
                 HCS_N_PCC(ehci->hcs_params),
                 HCS_N_PORTS(ehci->hcs_params));

        switch (pdev->vendor) {
        case 0x17a0:		/* GENESYS */
            /* GL880S: should be PORTS=2 */
            temp |= (ehci->hcs_params & ~0xf);
            ehci->hcs_params = temp;
            break;
        case PCI_VENDOR_ID_NVIDIA:
            /* NF4: should be PCC=10 */
            break;
        }
    }

    /* Serial Bus Release Number is at PCI 0x60 offset */
    pci_read_config_byte(pdev, 0x60, &ehci->sbrn);

    /* Keep this around for a while just in case some EHCI
     * implementation uses legacy PCI PM support.  This test
     * can be removed on 17 Dec 2009 if the dev_warn() hasn't
     * been triggered by then.
     */
    if (!device_can_wakeup(&pdev->dev)) {
        u16	port_wake;

        pci_read_config_word(pdev, 0x62, &port_wake);
        if (port_wake & 0x0001) {
            dev_warn(&pdev->dev, "Enabling legacy PCI PM\n");
            device_set_wakeup_capable(&pdev->dev, 1);
        }
    }

#ifdef	CONFIG_USB_SUSPEND
    /* REVISIT: the controller works fine for wakeup iff the root hub
     * itself is "globally" suspended, but usbcore currently doesn't
     * understand such things.
     *
     * System suspend currently expects to be able to suspend the entire
     * device tree, device-at-a-time.  If we failed selective suspend
     * reports, system suspend would fail; so the root hub code must claim
     * success.  That's lying to usbcore, and it matters for runtime
     * PM scenarios with selective suspend and remote wakeup...
     */
    if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev))
        ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
#endif

    ehci_port_power(ehci, 1);
    retval = ehci_pci_reinit(ehci, pdev);
done:
    return retval;
}
예제 #4
0
static int s5p_ehci_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = s5p_ehci->hcd;
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);

	clk_enable(s5p_ehci->clk);
	pm_runtime_resume(&pdev->dev);

	s5p_ehci_phy_init(pdev);

	/* if EHCI was off, hcd was removed */
	if (!s5p_ehci->power_on) {
		dev_info(dev, "Nothing to do for the device (power off)\n");
		return 0;
	}

	if (time_before(jiffies, ehci->next_statechange))
		msleep(10);

	/* Mark hardware accessible again as we are out of D3 state by now */
	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
		int	mask = INTR_MASK;

		if (!hcd->self.root_hub->do_remote_wakeup)
			mask &= ~STS_PCD;
		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
		ehci_readl(ehci, &ehci->regs->intr_enable);
		return 0;
	}

	ehci_dbg(ehci, "lost power, restarting\n");
	usb_root_hub_lost_power(hcd->self.root_hub);

	(void) ehci_halt(ehci);
	(void) ehci_reset(ehci);

	/* emptying the schedule aborts any urbs */
	spin_lock_irq(&ehci->lock);
	if (ehci->reclaim)
		end_unlink_async(ehci);
	ehci_work(ehci);
	spin_unlock_irq(&ehci->lock);

	ehci_writel(ehci, ehci->command, &ehci->regs->command);
	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */

	/* here we "know" root ports should always stay powered */
	ehci_port_power(ehci, 1);

	hcd->state = HC_STATE_SUSPENDED;
#ifdef CONFIG_MDM_HSIC_PM
	set_host_stat(hsic_pm_dev, POWER_ON);
	wait_dev_pwr_stat(hsic_pm_dev, POWER_ON);
#endif
#if defined(CONFIG_LINK_DEVICE_HSIC) || defined(CONFIG_LINK_DEVICE_USB) \
		|| defined(CONFIG_MDM_HSIC_PM)
	s5p_wait_for_cp_resume(pdev, hcd);
#endif
	return 0;
}
예제 #5
0
static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
{
    struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
    struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);

    /* The BIOS on systems with the Intel Panther Point chipset may or may
     * not support xHCI natively.  That means that during system resume, it
     * may switch the ports back to EHCI so that users can use their
     * keyboard to select a kernel from GRUB after resume from hibernate.
     *
     * The BIOS is supposed to remember whether the OS had xHCI ports
     * enabled before resume, and switch the ports back to xHCI when the
     * BIOS/OS semaphore is written, but we all know we can't trust BIOS
     * writers.
     *
     * Unconditionally switch the ports back to xHCI after a system resume.
     * We can't tell whether the EHCI or xHCI controller will be resumed
     * first, so we have to do the port switchover in both drivers.  Writing
     * a '1' to the port switchover registers should have no effect if the
     * port was already switched over.
     */
    if (usb_is_intel_switchable_ehci(pdev))
        ehci_enable_xhci_companion();

    // maybe restore FLADJ

    if (time_before(jiffies, ehci->next_statechange))
        msleep(100);

    /* Mark hardware accessible again as we are out of D3 state by now */
    set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

    /* If CF is still set and we aren't resuming from hibernation
     * then we maintained PCI Vaux power.
     * Just undo the effect of ehci_pci_suspend().
     */
    if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
            !hibernated) {
        int	mask = INTR_MASK;

        ehci_prepare_ports_for_controller_resume(ehci);
        if (!hcd->self.root_hub->do_remote_wakeup)
            mask &= ~STS_PCD;
        ehci_writel(ehci, mask, &ehci->regs->intr_enable);
        ehci_readl(ehci, &ehci->regs->intr_enable);
        return 0;
    }

    usb_root_hub_lost_power(hcd->self.root_hub);

    /* Else reset, to cope with power loss or flush-to-storage
     * style "resume" having let BIOS kick in during reboot.
     */
    (void) ehci_halt(ehci);
    (void) ehci_reset(ehci);
    (void) ehci_pci_reinit(ehci, pdev);

    /* emptying the schedule aborts any urbs */
    spin_lock_irq(&ehci->lock);
    if (ehci->reclaim)
        end_unlink_async(ehci);
    ehci_work(ehci);
    spin_unlock_irq(&ehci->lock);

    ehci_writel(ehci, ehci->command, &ehci->regs->command);
    ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
    ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */

    /* here we "know" root ports should always stay powered */
    ehci_port_power(ehci, 1);

    hcd->state = HC_STATE_SUSPENDED;
    return 0;
}
예제 #6
0
static int
fsl_ehci_attach(device_t self)
{
	ehci_softc_t *sc;
	int rid;
	int err;
	bus_space_handle_t ioh;
	bus_space_tag_t iot;

	sc = device_get_softc(self);
	rid = 0;

	sc->sc_bus.parent = self;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
	sc->sc_bus.dma_bits = 32;

	if (usb_bus_mem_alloc_all(&sc->sc_bus,
	    USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc))
		return (ENOMEM);

	/* Allocate io resource for EHCI */
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (sc->sc_io_res == NULL) {
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENXIO);
	}
	iot = rman_get_bustag(sc->sc_io_res);

	/*
	 * Set handle to USB related registers subregion used by generic
	 * EHCI driver
	 */
	ioh = rman_get_bushandle(sc->sc_io_res);

	err = bus_space_subregion(iot, ioh, FSL_EHCI_REG_OFF, FSL_EHCI_REG_SIZE,
	    &sc->sc_io_hdl);
	if (err != 0) {
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENXIO);
	}

	/* Set little-endian tag for use by the generic EHCI driver */
	sc->sc_io_tag = &bs_le_tag;

	/* Allocate irq */
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENXIO);
	}

	/* Setup interrupt handler */
	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
	if (err) {
		device_printf(self, "Could not setup irq, %d\n", err);
		sc->sc_intr_hdl = NULL;
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENXIO);
	}

	/* Add USB device */
	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(self, "Could not add USB device\n");
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENOMEM);
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);

	sc->sc_id_vendor = 0x1234;
	strlcpy(sc->sc_vendor, "Freescale", sizeof(sc->sc_vendor));

	/* Enable USB */
	err = ehci_reset(sc);
	if (err) {
		device_printf(self, "Could not reset the controller\n");
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENXIO);
	}

	enable_usb(self, iot, ioh);
	set_snooping(iot, ioh);
	set_to_host_mode(sc);
	set_32b_prefetch(iot, ioh);

	/*
	 * If usb subsystem is enabled in U-Boot, port power has to be turned
	 * off to allow proper discovery of devices during boot up.
	 */
	clear_port_power(sc);

	/* Set flags */
	sc->sc_flags |= EHCI_SCFLG_DONTRESET | EHCI_SCFLG_NORESTERM;

	err = ehci_init(sc);
	if (!err) {
		sc->sc_flags |= EHCI_SCFLG_DONEINIT;
		err = device_probe_and_attach(sc->sc_bus.bdev);
	}

	if (err) {
		device_printf(self, "USB init failed err=%d\n", err);
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (EIO);
	}

	return (0);
}
예제 #7
0
static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
{
	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
	u16 pmc_enable = 0;
 	//CharlesTu,for PM high memory
	pci_read_config_word(pdev, 0x84, &pmc_enable);
	pmc_enable &= ~0x03;
	pci_write_config_word(pdev, 0x84, pmc_enable);

	// maybe restore FLADJ

	if (time_before(jiffies, ehci->next_statechange))
		msleep(100);

	/* Mark hardware accessible again as we are out of D3 state by now */
	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	/*CharlesTu,2011.01,21,move ahead,due to vbus lost when suspend
	* when resume ehci hub activate ,type= HUB_RESET_RESUME
	*/
  usb_root_hub_lost_power(hcd->self.root_hub);
	/* If CF is still set and we aren't resuming from hibernation
	 * then we maintained PCI Vaux power.
	 * Just undo the effect of ehci_pci_suspend().
	 */
	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
				!hibernated) {
		int	mask = INTR_MASK;

		if (!hcd->self.root_hub->do_remote_wakeup)
			mask &= ~STS_PCD;
		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
		ehci_readl(ehci, &ehci->regs->intr_enable);
		return 0;
	}
  //CharlesTu
	//usb_root_hub_lost_power(hcd->self.root_hub);

	/* Else reset, to cope with power loss or flush-to-storage
	 * style "resume" having let BIOS kick in during reboot.
	 */
	(void) ehci_halt(ehci);
	(void) ehci_reset(ehci);
	(void) ehci_pci_reinit(ehci, pdev);

	/* emptying the schedule aborts any urbs */
	spin_lock_irq(&ehci->lock);
	if (ehci->reclaim)
		end_unlink_async(ehci);
	ehci_work(ehci);
	spin_unlock_irq(&ehci->lock);

	ehci_writel(ehci, ehci->command, &ehci->regs->command);
	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */

	/* here we "know" root ports should always stay powered */
	ehci_port_power(ehci, 1);

	hcd->state = HC_STATE_SUSPENDED;
	return 0;
}
예제 #8
0
static int
ar71xx_ehci_attach(device_t self)
{
	struct ar71xx_ehci_softc *isc = device_get_softc(self);
	ehci_softc_t *sc = &isc->base;
	int err;
	int rid;

	/* initialise some bus fields */
	sc->sc_bus.parent = self;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
	sc->sc_bus.dma_bits = 32;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus,
	    USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
		return (ENOMEM);
	}

	sc->sc_bus.usbrev = USB_REV_2_0;

	/* NB: hints fix the memory location and irq */

	rid = 0;
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
	if (!sc->sc_io_res) {
		device_printf(self, "Could not map memory\n");
		goto error;
	}

	/*
	 * Craft special resource for bus space ops that handle
	 * byte-alignment of non-word addresses.  
	 */
	sc->sc_io_tag = ar71xx_bus_space_reversed;
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	sc->sc_io_size = rman_get_size(sc->sc_io_res);

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (sc->sc_irq_res == NULL) {
		device_printf(self, "Could not allocate irq\n");
		goto error;
	}
	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(self, "Could not add USB device\n");
		goto error;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
	device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);

	sprintf(sc->sc_vendor, "Atheros");

	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, ar71xx_ehci_intr, sc, &sc->sc_intr_hdl);
	if (err) {
		device_printf(self, "Could not setup irq, %d\n", err);
		sc->sc_intr_hdl = NULL;
		goto error;
	}

	/*
	 * Arrange to force Host mode, select big-endian byte alignment,
	 * and arrange to not terminate reset operations (the adapter
	 * will ignore it if we do but might as well save a reg write).
	 * Also, the controller has an embedded Transaction Translator
	 * which means port speed must be read from the Port Status
	 * register following a port enable.
	 */
	sc->sc_flags = 0;
	sc->sc_vendor_post_reset = ar71xx_ehci_post_reset;

	switch (ar71xx_soc) {
		case AR71XX_SOC_AR7241:
		case AR71XX_SOC_AR7242:
		case AR71XX_SOC_AR9130:
		case AR71XX_SOC_AR9132:
		case AR71XX_SOC_AR9330:
		case AR71XX_SOC_AR9331:
		case AR71XX_SOC_AR9341:
		case AR71XX_SOC_AR9342:
		case AR71XX_SOC_AR9344:
		case AR71XX_SOC_QCA9533:
		case AR71XX_SOC_QCA9533_V2:
		case AR71XX_SOC_QCA9556:
		case AR71XX_SOC_QCA9558:
			sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
			sc->sc_vendor_get_port_speed =
			    ehci_get_port_speed_portsc;
			break;
		default:
			/* fallthrough */
			break;
	}

	/*
	 * ehci_reset() needs the correct offset to access the host controller
	 * registers. The AR724x/AR913x offsets aren't 0.
	*/
	sc->sc_offs = EHCI_CAPLENGTH(EREAD4(sc, EHCI_CAPLEN_HCIVERSION));

	(void) ehci_reset(sc);

	err = ehci_init(sc);
	if (!err) {
		err = device_probe_and_attach(sc->sc_bus.bdev);
	}
	if (err) {
		device_printf(self, "USB init failed err=%d\n", err);
		goto error;
	}
	return (0);

error:
	ar71xx_ehci_detach(self);
	return (ENXIO);
}
예제 #9
0
/* called during probe() after chip reset completes */
static int ehci_fsl_setup(struct usb_hcd *hcd)
{
    struct ehci_hcd *ehci = hcd_to_ehci(hcd);
    int retval;
    struct fsl_usb2_platform_data *pdata;
    pdata = hcd->self.controller->platform_data;

    ehci->big_endian_desc = pdata->big_endian_desc;
    ehci->big_endian_mmio = pdata->big_endian_mmio;

    /* EHCI registers start at offset 0x100 */
    ehci->caps = hcd->regs + 0x100;
    ehci->regs = hcd->regs + 0x100 +
                 HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
    dbg_hcs_params(ehci, "reset");
    dbg_hcc_params(ehci, "reset");

    /* cache this readonly data; minimize chip reads */
    ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);

    retval = ehci_halt(ehci);

    /* data structure init */
    retval = ehci_init(hcd);
    if (retval)
        return retval;

    hcd->has_tt = 1;

    ehci->sbrn = 0x20;

    ehci_reset(ehci);

    retval = ehci_fsl_reinit(ehci);


#ifdef CHUMBY_USB_MODIFICATIONS
    /* Also, disable the IRQ for the 5V line.  Turning on the screen causes
     * a massive drop in power, and the battery circuitry thinks we've
     * pulled the 5V line.
     */
    HW_POWER_CTRL_CLR(1);




    /* Wait just enough time for the brownout.  Any less than this and it
     * reboots when we bring the USB card up, or segfaults.
     */
    msleep(5);


    /* Set bank 0, pins 26 and 28 to GPIO. */
    HW_PINCTRL_MUXSEL1_SET(0x03300000);


    /* Set both pins to low, which ensures a reset takes place. */
    HW_PINCTRL_DOUT0_CLR(0x24000000);
    HW_PINCTRL_DOE0_SET(0x24000000);
    HW_PINCTRL_DOUT0_CLR(0x24000000);
    msleep(5);


    /* Delay for one second, giving most USB devices the chance to
     * recognize they've been "unplugged".
     */
    msleep(1000);


    /* Write a "1" to bank 0, pin 28. */
    HW_PINCTRL_DOUT0_SET(0x20000000);
    msleep(5);


    /* Write a "1" to bank 0, pin 26, to disable USB.  This ensures a reset.
     * Wait a short time after, then re-enable the IRQ that fires when power
     * is pulled.  This is because by now, the voltages should have
     * stabilized.
     */
    HW_PINCTRL_DOUT0_SET(0x04000000);
    msleep(5);


    /* Re-enable the power interrupt. */
    HW_POWER_CTRL_SET(1);


#endif /*CHUMBY_USB_MODIFICATIONS*/

    return retval;
}
예제 #10
0
/**
 * ehci_hcd_omap_probe - initialize TI-based HCDs
 *
 * Allocates basic resources for this USB host controller, and
 * then invokes the start() method for the HCD associated with it
 * through the hotplug entry's driver_data.
 */
static int ehci_hcd_omap_probe(struct platform_device *pdev)
{
	struct device				*dev = &pdev->dev;
	struct ehci_hcd_omap_platform_data	*pdata = dev->platform_data;
	struct resource				*res;
	struct usb_hcd				*hcd;
	void __iomem				*regs;
	struct ehci_hcd				*omap_ehci;
	int					ret = -ENODEV;
	int					irq;
	int					i;
	char					supply[7];

	if (usb_disabled())
		return -ENODEV;

	if (!dev->parent) {
		dev_err(dev, "Missing parent device\n");
		return -ENODEV;
	}

	irq = platform_get_irq_byname(pdev, "ehci-irq");
	if (irq < 0) {
		dev_err(dev, "EHCI irq failed\n");
		return -ENODEV;
	}

	res =  platform_get_resource_byname(pdev,
				IORESOURCE_MEM, "ehci");
	if (!res) {
		dev_err(dev, "UHH EHCI get resource failed\n");
		return -ENODEV;
	}

	regs = ioremap(res->start, resource_size(res));
	if (!regs) {
		dev_err(dev, "UHH EHCI ioremap failed\n");
		return -ENOMEM;
	}

	hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
			dev_name(dev));
	if (!hcd) {
		dev_err(dev, "failed to create hcd with err %d\n", ret);
		ret = -ENOMEM;
		goto err_io;
	}

	hcd->rsrc_start = res->start;
	hcd->rsrc_len = resource_size(res);
	hcd->regs = regs;

	/* get ehci regulator and enable */
	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
		if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
			pdata->regulator[i] = NULL;
			continue;
		}
		snprintf(supply, sizeof(supply), "hsusb%d", i);
		pdata->regulator[i] = regulator_get(dev, supply);
		if (IS_ERR(pdata->regulator[i])) {
			pdata->regulator[i] = NULL;
			dev_dbg(dev,
			"failed to get ehci port%d regulator\n", i);
		} else {
			regulator_enable(pdata->regulator[i]);
		}
	}

	if (pdata->phy_reset) {
		if (gpio_is_valid(pdata->reset_gpio_port[0]))
			gpio_request_one(pdata->reset_gpio_port[0],
					 GPIOF_OUT_INIT_LOW, "USB1 PHY reset");

		if (gpio_is_valid(pdata->reset_gpio_port[1]))
			gpio_request_one(pdata->reset_gpio_port[1],
					 GPIOF_OUT_INIT_LOW, "USB2 PHY reset");

		/* Hold the PHY in RESET for enough time till DIR is high */
		udelay(10);
	}

	pm_runtime_enable(dev);
	pm_runtime_get_sync(dev);

	/*
	 * An undocumented "feature" in the OMAP3 EHCI controller,
	 * causes suspended ports to be taken out of suspend when
	 * the USBCMD.Run/Stop bit is cleared (for example when
	 * we do ehci_bus_suspend).
	 * This breaks suspend-resume if the root-hub is allowed
	 * to suspend. Writing 1 to this undocumented register bit
	 * disables this feature and restores normal behavior.
	 */
	ehci_write(regs, EHCI_INSNREG04,
				EHCI_INSNREG04_DISABLE_UNSUSPEND);

	/* Soft reset the PHY using PHY reset command over ULPI */
	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
		omap_ehci_soft_phy_reset(pdev, 0);
	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
		omap_ehci_soft_phy_reset(pdev, 1);

	omap_ehci = hcd_to_ehci(hcd);
	omap_ehci->sbrn = 0x20;

	/* we know this is the memory we want, no need to ioremap again */
	omap_ehci->caps = hcd->regs;
	omap_ehci->regs = hcd->regs
		+ HC_LENGTH(ehci, readl(&omap_ehci->caps->hc_capbase));

	dbg_hcs_params(omap_ehci, "reset");
	dbg_hcc_params(omap_ehci, "reset");

	/* cache this readonly data; minimize chip reads */
	omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);

	ehci_reset(omap_ehci);

	if (pdata->phy_reset) {
		/* Hold the PHY in RESET for enough time till
		 * PHY is settled and ready
		 */
		udelay(10);

		if (gpio_is_valid(pdata->reset_gpio_port[0]))
			gpio_set_value(pdata->reset_gpio_port[0], 1);

		if (gpio_is_valid(pdata->reset_gpio_port[1]))
			gpio_set_value(pdata->reset_gpio_port[1], 1);
	}

	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
	if (ret) {
		dev_err(dev, "failed to add hcd with err %d\n", ret);
		goto err_add_hcd;
	}

	/* root ports should always stay powered */
	ehci_port_power(omap_ehci, 1);

	return 0;

err_add_hcd:
	disable_put_regulator(pdata);
	pm_runtime_put_sync(dev);

err_io:
	iounmap(regs);
	return ret;
}
예제 #11
0
파일: ehci-pci.c 프로젝트: ena30/snake-os
/* called during probe() after chip reset completes */
static int ehci_pci_setup(struct usb_hcd *hcd)
{
	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
	u32			temp;
	int			retval;

	ehci->caps = hcd->regs;
	ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
	dbg_hcs_params(ehci, "reset");
	dbg_hcc_params(ehci, "reset");

	/* cache this readonly data; minimize chip reads */
	ehci->hcs_params = readl(&ehci->caps->hcs_params);

	retval = ehci_halt(ehci);
	if (retval)
		return retval;

	/* data structure init */
	retval = ehci_init(hcd);
	if (retval)
		return retval;

	/* NOTE:  only the parts below this line are PCI-specific */

	switch (pdev->vendor) {
	case PCI_VENDOR_ID_TDI:
		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
			ehci->is_tdi_rh_tt = 1;
			tdi_reset(ehci);
		}
		break;
	case PCI_VENDOR_ID_AMD:
		/* AMD8111 EHCI doesn't work, according to AMD errata */
		if (pdev->device == 0x7463) {
			ehci_info(ehci, "ignoring AMD8111 (errata)\n");
			retval = -EIO;
			goto done;
		}
		break;
	case PCI_VENDOR_ID_NVIDIA:
		/* NVidia reports that certain chips don't handle
		 * QH, ITD, or SITD addresses above 2GB.  (But TD,
		 * data buffer, and periodic schedule are normal.)
		 */
		switch (pdev->device) {
		case 0x003c:	/* MCP04 */
		case 0x005b:	/* CK804 */
		case 0x00d8:	/* CK8 */
		case 0x00e8:	/* CK8S */
			if (pci_set_consistent_dma_mask(pdev,
						DMA_31BIT_MASK) < 0)
				ehci_warn(ehci, "can't enable NVidia "
					"workaround for >2GB RAM\n");
			break;
		}
		break;
	}

	if (ehci_is_TDI(ehci))
		ehci_reset(ehci);

	/* at least the Genesys GL880S needs fixup here */
	temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
	temp &= 0x0f;
	if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
		ehci_dbg(ehci, "bogus port configuration: "
			"cc=%d x pcc=%d < ports=%d\n",
			HCS_N_CC(ehci->hcs_params),
			HCS_N_PCC(ehci->hcs_params),
			HCS_N_PORTS(ehci->hcs_params));

		switch (pdev->vendor) {
		case 0x17a0:		/* GENESYS */
			/* GL880S: should be PORTS=2 */
			temp |= (ehci->hcs_params & ~0xf);
			ehci->hcs_params = temp;
			break;
		case PCI_VENDOR_ID_NVIDIA:
			/* NF4: should be PCC=10 */
			break;
		}
	}

	/* Serial Bus Release Number is at PCI 0x60 offset */
	pci_read_config_byte(pdev, 0x60, &ehci->sbrn);

	/* Workaround current PCI init glitch:  wakeup bits aren't
	 * being set from PCI PM capability.
	 */
	if (!device_can_wakeup(&pdev->dev)) {
		u16	port_wake;

		pci_read_config_word(pdev, 0x62, &port_wake);
		if (port_wake & 0x0001)
			device_init_wakeup(&pdev->dev, 1);
	}

	retval = ehci_pci_reinit(ehci, pdev);
done:
	return retval;
}
예제 #12
0
파일: ehci-pci.c 프로젝트: ena30/snake-os
static int ehci_pci_resume(struct usb_hcd *hcd)
{
	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
	unsigned		port;
	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
	int			retval = -EINVAL;

	// maybe restore FLADJ

	if (time_before(jiffies, ehci->next_statechange))
		msleep(100);

	/* Mark hardware accessible again as we are out of D3 state by now */
	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

	/* If CF is clear, we lost PCI Vaux power and need to restart.  */
	if (readl(&ehci->regs->configured_flag) != FLAG_CF)
		goto restart;

	/* If any port is suspended (or owned by the companion),
	 * we know we can/must resume the HC (and mustn't reset it).
	 * We just defer that to the root hub code.
	 */
	for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
		u32	status;
		port--;
		status = readl(&ehci->regs->port_status [port]);
		if (!(status & PORT_POWER))
			continue;
		if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) {
			usb_hcd_resume_root_hub(hcd);
			return 0;
		}
	}

restart:
	ehci_dbg(ehci, "lost power, restarting\n");
	usb_root_hub_lost_power(hcd->self.root_hub);

	/* Else reset, to cope with power loss or flush-to-storage
	 * style "resume" having let BIOS kick in during reboot.
	 */
	(void) ehci_halt(ehci);
	(void) ehci_reset(ehci);
	(void) ehci_pci_reinit(ehci, pdev);

	/* emptying the schedule aborts any urbs */
	spin_lock_irq(&ehci->lock);
	if (ehci->reclaim)
		ehci->reclaim_ready = 1;
	ehci_work(ehci, NULL);
	spin_unlock_irq(&ehci->lock);

	/* restart; khubd will disconnect devices */
	retval = ehci_run(hcd);

	/* here we "know" root ports should always stay powered */
	ehci_port_power(ehci, 1);

	return retval;
}
예제 #13
0
static int
ehci_ixp_attach(device_t self)
{
	struct ixp_ehci_softc *isc = device_get_softc(self);
	ehci_softc_t *sc = &isc->base;
	int err;
	int rid;

	/* initialise some bus fields */
	sc->sc_bus.parent = self;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus,
	    USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
		return (ENOMEM);
	}

	sc->sc_bus.usbrev = USB_REV_2_0;

	/* NB: hints fix the memory location and irq */

	rid = 0;
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
	if (!sc->sc_io_res) {
		device_printf(self, "Could not map memory\n");
		goto error;
	}

	/*
	 * Craft special resource for bus space ops that handle
	 * byte-alignment of non-word addresses.  Also, since
	 * we're already intercepting bus space ops we handle
	 * the register window offset that could otherwise be
	 * done with bus_space_subregion.
	 */
	isc->iot = rman_get_bustag(sc->sc_io_res);
	isc->tag.bs_cookie = isc->iot;
	/* read single */
	isc->tag.bs_r_1	= ehci_bs_r_1,
	isc->tag.bs_r_2	= ehci_bs_r_2,
	isc->tag.bs_r_4	= ehci_bs_r_4,
	/* write (single) */
	isc->tag.bs_w_1	= ehci_bs_w_1,
	isc->tag.bs_w_2	= ehci_bs_w_2,
	isc->tag.bs_w_4	= ehci_bs_w_4,

	sc->sc_io_tag = &isc->tag;
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	sc->sc_io_size = IXP435_USB1_SIZE - 0x100;

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		device_printf(self, "Could not allocate irq\n");
		goto error;
	}
	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(self, "Could not add USB device\n");
		goto error;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
	device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);

	sprintf(sc->sc_vendor, "Intel");


	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
	if (err) {
		device_printf(self, "Could not setup irq, %d\n", err);
		sc->sc_intr_hdl = NULL;
		goto error;
	}

	/*
	 * Arrange to force Host mode, select big-endian byte alignment,
	 * and arrange to not terminate reset operations (the adapter
	 * will ignore it if we do but might as well save a reg write).
	 * Also, the controller has an embedded Transaction Translator
	 * which means port speed must be read from the Port Status
	 * register following a port enable.
	 */
	sc->sc_flags |= EHCI_SCFLG_TT
		     | EHCI_SCFLG_SETMODE
		     | EHCI_SCFLG_BIGEDESC
		     | EHCI_SCFLG_BIGEMMIO
		     | EHCI_SCFLG_NORESTERM
		     ;
	(void) ehci_reset(sc);

	err = ehci_init(sc);
	if (!err) {
		err = device_probe_and_attach(sc->sc_bus.bdev);
	}
	if (err) {
		device_printf(self, "USB init failed err=%d\n", err);
		goto error;
	}
	return (0);

error:
	ehci_ixp_detach(self);
	return (ENXIO);
}
static irqreturn_t ehci_irq (struct usb_hcd *hcd)
{
	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
	u32			status, masked_status, pcd_status = 0, cmd;
	int			bh;

	spin_lock (&ehci->lock);

	status = ehci_readl(ehci, &ehci->regs->status);

	/* e.g. cardbus physical eject */
	if (status == ~(u32) 0) {
		ehci_dbg (ehci, "device removed\n");
		goto dead;
	}

	masked_status = status & INTR_MASK;
	if (!masked_status) {		/* irq sharing? */
		spin_unlock(&ehci->lock);
		return IRQ_NONE;
	}

	/* clear (just) interrupts */
	ehci_writel(ehci, masked_status, &ehci->regs->status);
	cmd = ehci_readl(ehci, &ehci->regs->command);
	bh = 0;

#ifdef	VERBOSE_DEBUG
	/* unrequested/ignored: Frame List Rollover */
	dbg_status (ehci, "irq", status);
#endif

	/* INT, ERR, and IAA interrupt rates can be throttled */

	/* normal [4.15.1.2] or error [4.15.1.1] completion */
	if (likely ((status & (STS_INT|STS_ERR)) != 0)) {
		if (likely ((status & STS_ERR) == 0))
			COUNT (ehci->stats.normal);
		else
			COUNT (ehci->stats.error);
		bh = 1;
	}

	/* complete the unlinking of some qh [4.15.2.3] */
	if (status & STS_IAA) {
		/* guard against (alleged) silicon errata */
		if (cmd & CMD_IAAD) {
			ehci_writel(ehci, cmd & ~CMD_IAAD,
					&ehci->regs->command);
			ehci_dbg(ehci, "IAA with IAAD still set?\n");
		}
		if (ehci->reclaim) {
			COUNT(ehci->stats.reclaim);
			end_unlink_async(ehci);
		} else
			ehci_dbg(ehci, "IAA with nothing to reclaim?\n");
	}

	/* remote wakeup [4.3.1] */
	if (status & STS_PCD) {
		unsigned	i = HCS_N_PORTS (ehci->hcs_params);

		/* kick root hub later */
		pcd_status = status;

		/* resume root hub? */
		if (!(cmd & CMD_RUN))
			usb_hcd_resume_root_hub(hcd);

		while (i--) {
			int pstatus = ehci_readl(ehci,
						 &ehci->regs->port_status [i]);

			if (pstatus & PORT_OWNER)
				continue;
			if (!(test_bit(i, &ehci->suspended_ports) &&
					((pstatus & PORT_RESUME) ||
						!(pstatus & PORT_SUSPEND)) &&
					(pstatus & PORT_PE) &&
					ehci->reset_done[i] == 0))
				continue;

			/* start 20 msec resume signaling from this port,
			 * and make khubd collect PORT_STAT_C_SUSPEND to
			 * stop that signaling.
			 */
			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
		}
	}

	/* PCI errors [4.15.2.4] */
	if (unlikely ((status & STS_FATAL) != 0)) {
		ehci_err(ehci, "fatal error\n");
		dbg_cmd(ehci, "fatal", cmd);
		dbg_status(ehci, "fatal", status);
		ehci_halt(ehci);
dead:
		ehci_reset(ehci);
		ehci_writel(ehci, 0, &ehci->regs->configured_flag);
		/* generic layer kills/unlinks all urbs, then
		 * uses ehci_stop to clean up the rest
		 */
		bh = 1;
	}

	if (bh)
		ehci_work (ehci);
	spin_unlock (&ehci->lock);
	if (pcd_status)
		usb_hcd_poll_rh_status(hcd);
	return IRQ_HANDLED;
}
예제 #15
0
/* called during probe() after chip reset completes */
static int ehci_pci_setup(struct usb_hcd *hcd)
{
	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
	u32			temp;
	int			retval;

	ehci->caps = hcd->regs;
	ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
	dbg_hcs_params(ehci, "reset");
	dbg_hcc_params(ehci, "reset");

        /* ehci_init() causes memory for DMA transfers to be
         * allocated.  Thus, any vendor-specific workarounds based on
         * limiting the type of memory used for DMA transfers must
         * happen before ehci_init() is called. */
	switch (pdev->vendor) {
	case PCI_VENDOR_ID_NVIDIA:
		/* NVidia reports that certain chips don't handle
		 * QH, ITD, or SITD addresses above 2GB.  (But TD,
		 * data buffer, and periodic schedule are normal.)
		 */
		switch (pdev->device) {
		case 0x003c:	/* MCP04 */
		case 0x005b:	/* CK804 */
		case 0x00d8:	/* CK8 */
		case 0x00e8:	/* CK8S */
			if (pci_set_consistent_dma_mask(pdev,
						DMA_31BIT_MASK) < 0)
				ehci_warn(ehci, "can't enable NVidia "
					"workaround for >2GB RAM\n");
			break;
		}
		break;
	}

	/* cache this readonly data; minimize chip reads */
	ehci->hcs_params = readl(&ehci->caps->hcs_params);

	retval = ehci_halt(ehci);
	if (retval)
		return retval;

	/* data structure init */
	retval = ehci_init(hcd);
	if (retval)
		return retval;

	switch (pdev->vendor) {
	case PCI_VENDOR_ID_TDI:
		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
			ehci->is_tdi_rh_tt = 1;
			tdi_reset(ehci);
		}
		break;
	case PCI_VENDOR_ID_AMD:
		/* AMD8111 EHCI doesn't work, according to AMD errata */
		if (pdev->device == 0x7463) {
			ehci_info(ehci, "ignoring AMD8111 (errata)\n");
			retval = -EIO;
			goto done;
		}
		break;
	case PCI_VENDOR_ID_NVIDIA:
		switch (pdev->device) {
		/* Some NForce2 chips have problems with selective suspend;
		 * fixed in newer silicon.
		 */
		case 0x0068:
			pci_read_config_dword(pdev, PCI_REVISION_ID, &temp);
			if ((temp & 0xff) < 0xa4)
				ehci->no_selective_suspend = 1;
			break;
		}
		break;
	}

	if (ehci_is_TDI(ehci))
		ehci_reset(ehci);

	/* at least the Genesys GL880S needs fixup here */
	temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
	temp &= 0x0f;
	if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
		ehci_dbg(ehci, "bogus port configuration: "
			"cc=%d x pcc=%d < ports=%d\n",
			HCS_N_CC(ehci->hcs_params),
			HCS_N_PCC(ehci->hcs_params),
			HCS_N_PORTS(ehci->hcs_params));

		switch (pdev->vendor) {
		case 0x17a0:		/* GENESYS */
			/* GL880S: should be PORTS=2 */
			temp |= (ehci->hcs_params & ~0xf);
			ehci->hcs_params = temp;
			break;
		case PCI_VENDOR_ID_NVIDIA:
			/* NF4: should be PCC=10 */
			break;
		}
	}

	/* Serial Bus Release Number is at PCI 0x60 offset */
	pci_read_config_byte(pdev, 0x60, &ehci->sbrn);

	/* Workaround current PCI init glitch:  wakeup bits aren't
	 * being set from PCI PM capability.
	 */
	if (!device_can_wakeup(&pdev->dev)) {
		u16	port_wake;

		pci_read_config_word(pdev, 0x62, &port_wake);
		if (port_wake & 0x0001)
			device_init_wakeup(&pdev->dev, 1);
	}

#ifdef	CONFIG_USB_SUSPEND
	/* REVISIT: the controller works fine for wakeup iff the root hub
	 * itself is "globally" suspended, but usbcore currently doesn't
	 * understand such things.
	 *
	 * System suspend currently expects to be able to suspend the entire
	 * device tree, device-at-a-time.  If we failed selective suspend
	 * reports, system suspend would fail; so the root hub code must claim
	 * success.  That's lying to usbcore, and it matters for for runtime
	 * PM scenarios with selective suspend and remote wakeup...
	 */
	if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev))
		ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
#endif

	retval = ehci_pci_reinit(ehci, pdev);
done:
	return retval;
}